diff --git a/CLAUDE.md b/CLAUDE.md index ca1c66e..5cc9551 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -398,10 +398,11 @@ self.arm_controller.set_joint_positions(saved_joint_positions) - **Play/Pause** - 控制回放播放 ### 技术特性 -- **自动录制**:执行三阶段任务时自动记录每帧数据 +- **自动录制**:执行三阶段任务时自动记录每帧数据和规划路径 - **智能保存**:文件自动以时间戳命名(`simulation_recording_YYYYMMDD_HHMMSS.json`) -- **无侵入设计**:完全独立模块,对原有功能零影响 -- **数据完整性**:记录完整的机械臂状态、物体位置和系统配置 +- **完整回放**:回放时显示原始规划路径(暗绿色)和任务点标记 +- **精确重现**:机械臂按录制的关节位置精确回放 +- **数据完整性**:记录完整的机械臂状态、物体位置、规划路径和系统配置 ### 数据格式 ```json @@ -419,6 +420,10 @@ self.arm_controller.set_joint_positions(saved_joint_positions) "object_position": [...] } ], + "path_data": { + "planned_path": [[...], [...], ...], + "executed_path": [] + }, "events": [...] } ``` diff --git a/config.json b/config.json index 3feb3f8..0389948 100644 --- a/config.json +++ b/config.json @@ -48,9 +48,9 @@ "task_points": { "point_A": { "position": [ + 0.0, 0.5, - 0.5, - 0.8 + 0.5 ], "description": "取物点,与机械臂同侧" }, @@ -58,14 +58,14 @@ "position": [ 0.5, -0.3, - 0.8 + 0.3 ], "description": "目标点,墙体另一侧" } }, "transport_object": { "initial_position": [ - 0.6, + 1.0, 0.5, 0.5 ], diff --git a/src/gui/main_window.py b/src/gui/main_window.py index 764e62c..4671804 100644 --- a/src/gui/main_window.py +++ b/src/gui/main_window.py @@ -591,6 +591,10 @@ class MainWindow: # 可视化完整路径 self._visualize_path_segment(optimized_path, PATH_COLOR, "Complete Path") + # 记录规划路径到录制数据(如果正在录制) + if self.recorder.is_recording: + self.recorder.record_planned_path(optimized_path) + # 添加任务点标记 self._add_point_markers(object_position, point_a, point_b) @@ -941,7 +945,30 @@ class MainWindow: if self.player.start_playback(): self.play_btn.config(text="Stop", command=self.stop_playback) self.pause_play_btn.config(state=tk.NORMAL) - self.update_status("开始回放录制") + + # 显示录制的路径(如果存在) + planned_path = self.player.get_planned_path() + if planned_path: + # 清除旧的路径可视化 + if hasattr(self, 'path_visualization'): + self.path_visualization.clear_all_paths() + # 显示录制的规划路径 + self._visualize_path_segment(planned_path, [0.2, 0.5, 0.2], "Recorded Path") + + # 重建任务点标记(从录制元数据) + metadata = self.player.get_recording_metadata() + if metadata and 'task_points' in metadata: + task_points = metadata['task_points'] + object_pos = task_points.get('transport_object', {}).get('initial_position') + point_a = task_points.get('point_a') + point_b = task_points.get('point_b') + + if object_pos and point_a and point_b: + self._add_point_markers(object_pos, point_a, point_b) + + self.update_status("开始回放录制(已显示规划路径)") + else: + self.update_status("开始回放录制(无路径数据)") # 开始回放循环 self._playback_loop() diff --git a/src/simulation/playback.py b/src/simulation/playback.py index 78236c5..f3bf497 100644 --- a/src/simulation/playback.py +++ b/src/simulation/playback.py @@ -254,4 +254,12 @@ class SimulationPlayer: if start_time <= event_time <= end_time: events.append(event) - return events \ No newline at end of file + return events + + def get_planned_path(self) -> Optional[List[List[float]]]: + """获取录制的规划路径""" + if not self.recording_data: + return None + + path_data = self.recording_data.get("path_data", {}) + return path_data.get("planned_path", None) \ No newline at end of file