1
zhang
2025-09-10 763eefe2b46820b583185ba00b34cb9887662fcd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
package com.algo.model;
 
import java.util.List;
import java.util.Objects;
 
/**
 * AGV状态信息
 * 包含AGV的完整状态数据,包括剩余路径和CTU物理参数
 */
public class AGVStatus {
 
    /**
     * AGV编号
     */
    private String agvId;
 
    /**
     * AGV状态
     */
    private int status;
 
    /**
     * AGV当前位置
     */
    private String position;
 
    /**
     * 空背篓数量
     */
    private String empty;
 
    /**
     * AGV方向角度
     */
    private String direction;
 
    /**
     * 电压电量值
     */
    private int vol;
 
    /**
     * 异常码,0表示正常
     */
    private int error;
 
    /**
     * 背篓数据列表
     */
    private List<BackpackData> backpack;
 
    /**
     * 低电量设定阈值,低于该值可以去自动充电也可以继续做任务
     */
    private int autoCharge;
 
    /**
     * 最低电量,电量低于该值必须去充电
     */
    private int lowVol;
 
    /**
     * CTU剩余未完成的路径,格式与输出路径相同
     */
    private PlannedPath remainingPath;
 
    /**
     * CTU物理参数配置
     */
    private CTUPhysicalConfig physicalConfig;
 
    /**
     * 当前执行路径中的位置索引(从剩余路径开始计算)
     */
    private int currentPathIndex;
 
    /**
     * 预计到达下一个路径点的时间戳(毫秒)
     */
    private long nextPointArrivalTime;
 
    // 构造函数
    public AGVStatus() {
        this.physicalConfig = new CTUPhysicalConfig(); // 使用默认配置
        this.currentPathIndex = 0;
        this.nextPointArrivalTime = System.currentTimeMillis();
    }
 
    public AGVStatus(String agvId, int status, String position, String empty,
                     String direction, int vol, int error, List<BackpackData> backpack,
                     int autoCharge, int lowVol) {
        this.agvId = agvId;
        this.status = status;
        this.position = position;
        this.empty = empty;
        this.direction = direction;
        this.vol = vol;
        this.error = error;
        this.backpack = backpack;
        this.autoCharge = autoCharge;
        this.lowVol = lowVol;
        this.physicalConfig = new CTUPhysicalConfig(); // 使用默认配置
        this.currentPathIndex = 0;
        this.nextPointArrivalTime = System.currentTimeMillis();
    }
 
    // 原有的Getter和Setter方法
    public String getAgvId() {
        return agvId;
    }
 
    public void setAgvId(String agvId) {
        this.agvId = agvId;
    }
 
    public int getStatus() {
        return status;
    }
 
    public void setStatus(int status) {
        this.status = status;
    }
 
    public String getPosition() {
        return position;
    }
 
    public void setPosition(String position) {
        this.position = position;
    }
 
    public String getEmpty() {
        return empty;
    }
 
    public void setEmpty(String empty) {
        this.empty = empty;
    }
 
    public String getDirection() {
        return direction;
    }
 
    public void setDirection(String direction) {
        this.direction = direction;
    }
 
    public int getVol() {
        return vol;
    }
 
    public void setVol(int vol) {
        this.vol = vol;
    }
 
    public int getError() {
        return error;
    }
 
    public void setError(int error) {
        this.error = error;
    }
 
    public List<BackpackData> getBackpack() {
        return backpack;
    }
 
    public void setBackpack(List<BackpackData> backpack) {
        this.backpack = backpack;
    }
 
    public int getAutoCharge() {
        return autoCharge;
    }
 
    public void setAutoCharge(int autoCharge) {
        this.autoCharge = autoCharge;
    }
 
    public int getLowVol() {
        return lowVol;
    }
 
    public void setLowVol(int lowVol) {
        this.lowVol = lowVol;
    }
 
    // 新增的剩余路径和物理参数相关的Getter和Setter方法
    public PlannedPath getRemainingPath() {
        return remainingPath;
    }
 
    public void setRemainingPath(PlannedPath remainingPath) {
        this.remainingPath = remainingPath;
    }
 
    public CTUPhysicalConfig getPhysicalConfig() {
        return physicalConfig;
    }
 
    public void setPhysicalConfig(CTUPhysicalConfig physicalConfig) {
        this.physicalConfig = physicalConfig;
    }
 
    public int getCurrentPathIndex() {
        return currentPathIndex;
    }
 
    public void setCurrentPathIndex(int currentPathIndex) {
        this.currentPathIndex = currentPathIndex;
    }
 
    public long getNextPointArrivalTime() {
        return nextPointArrivalTime;
    }
 
    public void setNextPointArrivalTime(long nextPointArrivalTime) {
        this.nextPointArrivalTime = nextPointArrivalTime;
    }
 
    /**
     * 检查CTU是否有剩余未完成的路径
     *
     * @return true如果有剩余路径
     */
    public boolean hasRemainingPath() {
        return remainingPath != null &&
                remainingPath.getCodeList() != null &&
                !remainingPath.getCodeList().isEmpty() &&
                currentPathIndex < remainingPath.getCodeList().size();
    }
 
    /**
     * 获取剩余路径的长度(从当前位置开始)
     *
     * @return 剩余路径点数量
     */
    public int getRemainingPathLength() {
        if (!hasRemainingPath()) {
            return 0;
        }
        return remainingPath.getCodeList().size() - currentPathIndex;
    }
 
    /**
     * 获取当前正在执行的路径点
     *
     * @return 当前路径点,如果没有则返回null
     */
    public PathCode getCurrentPathCode() {
        if (!hasRemainingPath()) {
            return null;
        }
        return remainingPath.getCodeList().get(currentPathIndex);
    }
 
    /**
     * 获取下一个要到达的路径点
     *
     * @return 下一个路径点,如果没有则返回null
     */
    public PathCode getNextPathCode() {
        if (!hasRemainingPath() || currentPathIndex + 1 >= remainingPath.getCodeList().size()) {
            return null;
        }
        return remainingPath.getCodeList().get(currentPathIndex + 1);
    }
 
    /**
     * 检查AGV是否可用(空闲且非故障状态)
     *
     * @return true如果AGV可用
     */
    public boolean isAvailable() {
        return error == 0 && status == 0 && vol > lowVol;
    }
 
    /**
     * 检查CTU是否可以接受新任务(考虑剩余路径)
     *
     * @return true如果可以接受新任务
     */
    public boolean canAcceptNewTask() {
        // 如果有剩余路径,需要等待完成后才能接受新任务
        // 除非剩余路径很短(比如只有1个点)
        if (hasRemainingPath()) {
            int remainingLength = getRemainingPathLength();
            return remainingLength <= 1; // 允许在即将完成当前路径时接受新任务
        }
        return isAvailable();
    }
 
    /**
     * 获取可用的背篓数量
     *
     * @return 可用背篓数量
     */
    public int getAvailableBackpackCount() {
        if (backpack == null || backpack.isEmpty()) {
            return 0;
        }
 
        int count = 0;
        for (BackpackData bp : backpack) {
            if (!bp.isLoaded() && bp.getTaskId() == null) {
                count++;
            }
        }
        return count;
    }
 
    /**
     * 查找可用的背篓位置
     *
     * @return 可用背篓的索引,如果没有可用则返回-1
     */
    public int findAvailableBackpackIndex() {
        if (backpack == null || backpack.isEmpty()) {
            return -1;
        }
 
        for (BackpackData bp : backpack) {
            if (!bp.isLoaded() && bp.getTaskId() == null) {
                return bp.getIndex();
            }
        }
        return -1;
    }
 
    /**
     * 检查AGV是否需要充电
     *
     * @return true如果需要充电
     */
    public boolean needsCharging() {
        return vol <= autoCharge;
    }
 
    /**
     * 检查AGV是否必须充电
     *
     * @return true如果必须充电
     */
    public boolean mustCharge() {
        return vol <= lowVol;
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        AGVStatus agvStatus = (AGVStatus) o;
        return Objects.equals(agvId, agvStatus.agvId);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(agvId);
    }
 
    @Override
    public String toString() {
        return "AGVStatus{" +
                "agvId='" + agvId + '\'' +
                ", status=" + status +
                ", position='" + position + '\'' +
                ", empty='" + empty + '\'' +
                ", direction='" + direction + '\'' +
                ", vol=" + vol +
                ", error=" + error +
                ", backpack=" + (backpack != null ? backpack.size() : 0) +
                ", autoCharge=" + autoCharge +
                ", lowVol=" + lowVol +
                ", hasRemainingPath=" + hasRemainingPath() +
                ", remainingPathLength=" + getRemainingPathLength() +
                ", physicalConfig=" + physicalConfig +
                '}';
    }