diff --git a/Snipaste_2025-09-11_18-23-45.jpg b/Snipaste_2025-09-11_18-23-45.jpg new file mode 100644 index 0000000..cce2e44 Binary files /dev/null and b/Snipaste_2025-09-11_18-23-45.jpg differ diff --git a/src/gui/main_window.py b/src/gui/main_window.py index 02338f9..098a69d 100644 --- a/src/gui/main_window.py +++ b/src/gui/main_window.py @@ -256,7 +256,14 @@ class MainWindow: # Clear current environment if self.environment: self.environment.cleanup() - # Note: Robot cleanup is handled by ArmController internally + + # Clear current robot + if self.arm_controller and hasattr(self.arm_controller, 'robot_loader') and self.arm_controller.robot_loader: + if self.arm_controller.robot_loader.robot_id is not None: + try: + p.removeBody(self.arm_controller.robot_loader.robot_id, physicsClientId=self.physics_client) + except: + pass # Robot might already be removed # Create new ConfigLoader with updated configuration self.config_loader = ConfigLoader() diff --git a/src/robot/robot_loader.py b/src/robot/robot_loader.py index 5a40bd6..cb77070 100644 --- a/src/robot/robot_loader.py +++ b/src/robot/robot_loader.py @@ -26,6 +26,14 @@ class RobotLoader: def load_robot(self) -> int: """Load robot URDF model into pybullet simulation""" + # Clear any existing robot + if self.robot_id is not None: + try: + p.removeBody(self.robot_id, physicsClientId=self.physics_client) + except: + pass # Robot might already be removed + self.robot_id = None + model_path = self.robot_config['model_path'] if not os.path.exists(model_path): diff --git a/src/simulation/environment.py b/src/simulation/environment.py index 2f998a7..ec8409b 100644 --- a/src/simulation/environment.py +++ b/src/simulation/environment.py @@ -20,6 +20,7 @@ class Environment: self.transport_object_id: Optional[int] = None self.ground_plane_id: Optional[int] = None self._wall_part_ids: List[int] = [] # 记录所有墙体部件ID + self.task_marker_ids: Dict[str, int] = {} # 存储A/B点标记ID def setup_simulation(self) -> None: """Setup basic simulation environment""" @@ -60,6 +61,15 @@ class Environment: self._wall_part_ids = [] self.wall_id = None + def _clear_task_markers(self) -> None: + """Clear existing task markers""" + for marker_id in self.task_marker_ids.values(): + try: + p.removeBody(marker_id, physicsClientId=self.physics_client) + except: + pass # Marker might already be removed + self.task_marker_ids.clear() + def create_wall_with_hole(self) -> List[int]: """Create wall with hole using: - Top/Bottom: full wall width @@ -258,10 +268,14 @@ class Environment: # Create transport object transport_obj_id = self.create_transport_object() + # Create task point markers + task_markers = self.create_task_markers() + return { 'ground_plane_id': ground_id, 'wall_parts': wall_parts, - 'transport_object_id': transport_obj_id + 'transport_object_id': transport_obj_id, + 'task_markers': task_markers } def get_transport_object_pose(self) -> Tuple[List[float], List[float]]: @@ -335,6 +349,60 @@ class Environment: 'dimensions': self.wall_config['dimensions'] } + def create_task_markers(self) -> Dict[str, int]: + """Create visual markers for task points A and B""" + # Clear existing markers + self._clear_task_markers() + + # Get task points from config + task_points = self.config_loader.get_task_points() + point_a_pos = task_points['point_A']['position'] + point_b_pos = task_points['point_B']['position'] + + # Create point A marker (green sphere) + a_visual = p.createVisualShape( + p.GEOM_SPHERE, + radius=0.05, + rgbaColor=[0.0, 1.0, 0.0, 0.8], # Semi-transparent green + physicsClientId=self.physics_client + ) + a_collision = p.createCollisionShape( + p.GEOM_SPHERE, + radius=0.005, # Very small collision volume to avoid interference + physicsClientId=self.physics_client + ) + a_id = p.createMultiBody( + baseMass=0, # Static object + baseCollisionShapeIndex=a_collision, + baseVisualShapeIndex=a_visual, + basePosition=point_a_pos, + physicsClientId=self.physics_client + ) + self.task_marker_ids['point_A'] = a_id + + # Create point B marker (red sphere) + b_visual = p.createVisualShape( + p.GEOM_SPHERE, + radius=0.05, + rgbaColor=[1.0, 0.0, 0.0, 0.8], # Semi-transparent red + physicsClientId=self.physics_client + ) + b_collision = p.createCollisionShape( + p.GEOM_SPHERE, + radius=0.005, + physicsClientId=self.physics_client + ) + b_id = p.createMultiBody( + baseMass=0, + baseCollisionShapeIndex=b_collision, + baseVisualShapeIndex=b_visual, + basePosition=point_b_pos, + physicsClientId=self.physics_client + ) + self.task_marker_ids['point_B'] = b_id + + return self.task_marker_ids + def reset_environment(self) -> None: """Reset environment to initial state""" if self.transport_object_id is not None: @@ -344,7 +412,10 @@ class Environment: def cleanup(self) -> None: """Clean up environment objects""" - # Clean up wall parts first + # Clean up task markers first + self._clear_task_markers() + + # Clean up wall parts self._clear_wall() objects_to_remove = []