diff --git a/agv_app/app.py b/agv_app/app.py index 6a05065..49dc6af 100644 --- a/agv_app/app.py +++ b/agv_app/app.py @@ -1242,7 +1242,12 @@ def api_agv_reset(): @app.route("/api/mission/start", methods=["POST"]) def api_mission_start(): """开始执行任务(V3: M×N Grid 蛇形路径)""" - if gs.state == State.RUNNING: + # 清除可能存在的旧实例,确保可以启动 + if hasattr(MissionExecutorV3, "_instance"): + MissionExecutorV3._instance = None + gs.state = State.IDLE + + if hasattr(MissionExecutorV3, "_instance") and MissionExecutorV3._instance: return jsonify({"ok": False, "error": "任务已在运行中"}), 400 def run(): @@ -1307,16 +1312,67 @@ def api_mission_report(): @app.route("/api/mission/state", methods=["GET"]) def api_mission_state(): - """返回任务状态 + 执行器详情""" + """返回任务状态 + 预生成任务列表""" result = {"state": gs.state} + + # 如果有执行器实例,合并执行器状态 if hasattr(MissionExecutorV3, "_instance") and MissionExecutorV3._instance: ex = MissionExecutorV3._instance result.update(ex.get_status()) - else: - # 空闲时预生成任务列表(基于网格和机器配置) - mc = gs.mission_config - if mc: - result["tasks"] = MissionExecutorV3.pre_generate_tasks(mc) + + # 从配置文件预生成任务列表(不依赖 MissionExecutorV3 类) + try: + base = os.path.dirname(os.path.abspath(__file__)) + with open(os.path.join(base, "data", "mission_config.json")) as jf: + mc = json.load(jf) + machines = [] + try: + with open(os.path.join(base, "data", "machines_config.json")) as jf: + machines = json.load(jf) + except: + pass + + rows = int(mc.get("rows", 1)) + cols = int(mc.get("cols", 1)) + grid = mc.get("grid", []) + + # 如果 grid 为空,从 machines 重建(只取 rows×cols 范围内的机器) + if (not grid or all(not any(rw) if isinstance(rw, list) else True for rw in grid)) and machines: + grid = [[False] * cols for _ in range(rows)] + for m in machines: + r = int(m.get("row", 0)) + c = int(m.get("col", 0)) + if 0 <= r < rows and 0 <= c < cols: + grid[r][c] = True + + # 蛇形路径 + path = [] + for r in range(rows): + if r % 2 == 0: + for c in range(cols): + if r < len(grid) and c < len(grid[r]) and grid[r][c]: + path.append((r, c)) + else: + for c in range(cols - 1, -1, -1): + if r < len(grid) and c < len(grid[r]) and grid[r][c]: + path.append((r, c)) + + tlist = [] + for (r, c) in path: + tlist.append({ + "row": r, "col": c, + "machine_id": "m_{}_{}".format(r, c), + "label": "{}-{}".format(r+1, c+1), + "status": "pending", + "step": "等待", + "qr_value": None, + "photos_front": 0, + "photos_back": 0, + }) + result["tasks"] = tlist + except Exception: + result["tasks"] = [] + return jsonify(result) @app.route("/api/mission/log", methods=["GET"]) diff --git a/agv_app/utils/mission_executor.py b/agv_app/utils/mission_executor.py index 8faf41a..a4a5e0d 100644 --- a/agv_app/utils/mission_executor.py +++ b/agv_app/utils/mission_executor.py @@ -130,6 +130,21 @@ class MissionExecutorV3: grid = mission_config.get("grid", []) positions = mission_config.get("positions", []) + # 如果 grid 为空,从 machines 重建 + if not grid or all(not any(rw) if isinstance(rw, list) else True for rw in grid): + try: + cfg_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "data") + with open(os.path.join(cfg_dir, "machines_config.json")) as jf: + machines = json.load(jf) + grid = [[False] * cols for _ in range(rows)] + for m in machines: + r = int(m.get("row", 0)) + c = int(m.get("col", 0)) + if 0 <= r < rows and 0 <= c < cols: + grid[r][c] = True + except Exception: + grid = [[False] * cols for _ in range(rows)] + # 1. 生成蛇形路径 path = MissionExecutorV3._build_snake_path(rows, cols, grid) if not path: