差别
这里会显示出您选择的修订版和当前版本之间的差别。
后一修订版 | 前一修订版 | ||
机器人:仿真:pybullet:pybullet常用代码:pybullet-启动arx5的双臂模拟 [2025/10/22 05:56] – 创建 ctbots | 机器人:仿真:pybullet:pybullet常用代码:pybullet-启动arx5的双臂模拟 [2025/10/22 06:04] (当前版本) – ctbots | ||
---|---|---|---|
行 1: | 行 1: | ||
====== 单个python文件实现pybullet在arx5上的双臂仿真 ====== | ====== 单个python文件实现pybullet在arx5上的双臂仿真 ====== | ||
+ | |||
+ | 首先看效果图: | ||
+ | |||
+ | {{: | ||
+ | |||
安装python环境 | 安装python环境 | ||
行 31: | 行 36: | ||
URDF文件参考 | URDF文件参考 | ||
- arx5.URDF文件:https:// | - arx5.URDF文件:https:// | ||
- | - apple.URFDF 文件是用AI生成的: | + | - apple.URDF 文件是用AI生成的: |
- | <code apple.urdf | + | < |
<?xml version=" | <?xml version=" | ||
<robot name=" | <robot name=" | ||
行 123: | 行 128: | ||
</ | </ | ||
</ | </ | ||
+ | |||
+ | 最终的模拟启动代码如下(纯CPU的): | ||
+ | |||
+ | <code python run-sim.py> | ||
+ | import pybullet as p | ||
+ | import pybullet_data | ||
+ | import time | ||
+ | import random | ||
+ | import numpy as np | ||
+ | import os | ||
+ | |||
+ | current_py_cwd = os.path.join(os.path.dirname(__file__)) | ||
+ | |||
+ | class GraspingController: | ||
+ | def __init__(self, | ||
+ | self.robot_id = robot_id | ||
+ | self.gripper_link_index = gripper_link_index | ||
+ | self.constraints = [] | ||
+ | |||
+ | def grasp_object(self, | ||
+ | gripper_state = p.getLinkState(self.robot_id, | ||
+ | gripper_pos, | ||
+ | obj_pos, obj_orn = p.getBasePositionAndOrientation(object_id) | ||
+ | constraint_id = p.createConstraint( | ||
+ | parentBodyUniqueId=self.robot_id, | ||
+ | parentLinkIndex=self.gripper_link_index, | ||
+ | childBodyUniqueId=object_id, | ||
+ | childLinkIndex=-1, | ||
+ | jointType=p.JOINT_FIXED, | ||
+ | jointAxis=[0, | ||
+ | parentFramePosition=[0, | ||
+ | childFramePosition=[0, | ||
+ | ) | ||
+ | self.constraints.append(constraint_id) | ||
+ | return constraint_id | ||
+ | |||
+ | def release_object(self, | ||
+ | if constraint_id: | ||
+ | p.removeConstraint(constraint_id) | ||
+ | if constraint_id in self.constraints: | ||
+ | self.constraints.remove(constraint_id) | ||
+ | else: | ||
+ | for constraint in self.constraints: | ||
+ | p.removeConstraint(constraint) | ||
+ | self.constraints = [] | ||
+ | |||
+ | class ARX5Simulation: | ||
+ | def __init__(self): | ||
+ | try: | ||
+ | p.connect(p.GUI, | ||
+ | except: | ||
+ | print(" | ||
+ | print(" | ||
+ | exit(1) | ||
+ | | ||
+ | p.setAdditionalSearchPath(pybullet_data.getDataPath()) | ||
+ | p.configureDebugVisualizer(p.COV_ENABLE_GUI, | ||
+ | p.configureDebugVisualizer(p.COV_ENABLE_RENDERING, | ||
+ | p.configureDebugVisualizer(p.COV_ENABLE_SHADOWS, | ||
+ | | ||
+ | try: | ||
+ | p.configureDebugVisualizer(p.COV_ENABLE_WIREFRAME, | ||
+ | p.resetDebugVisualizerCamera(cameraDistance=1.5, | ||
+ | except: | ||
+ | print(" | ||
+ | |||
+ | p.setGravity(0, | ||
+ | p.setRealTimeSimulation(0) | ||
+ | |||
+ | self.plane_id = p.loadURDF(" | ||
+ | self.object_urdfs = [os.path.join(current_py_cwd, | ||
+ | self.object_id = p.loadURDF(random.choice(self.object_urdfs), | ||
+ | | ||
+ | self.robot_id1 = p.loadURDF(os.path.join(current_py_cwd, | ||
+ | self.robot_id2 = p.loadURDF(os.path.join(current_py_cwd, | ||
+ | |||
+ | self.num_joints1 = p.getNumJoints(self.robot_id1) | ||
+ | self.num_joints2 = p.getNumJoints(self.robot_id2) | ||
+ | print(f" | ||
+ | print(f" | ||
+ | |||
+ | self.ee_index1 = 7 | ||
+ | self.ee_index2 = 7 | ||
+ | |||
+ | self.gripper1 = GraspingController(self.robot_id1, | ||
+ | self.gripper2 = GraspingController(self.robot_id2, | ||
+ | |||
+ | light_position = [random.uniform(-1, | ||
+ | p.addUserDebugParameter(" | ||
+ | p.addUserDebugParameter(" | ||
+ | p.addUserDebugParameter(" | ||
+ | |||
+ | self.target_x1 = p.addUserDebugParameter(" | ||
+ | self.target_y1 = p.addUserDebugParameter(" | ||
+ | self.target_z1 = p.addUserDebugParameter(" | ||
+ | | ||
+ | self.target_x2 = p.addUserDebugParameter(" | ||
+ | self.target_y2 = p.addUserDebugParameter(" | ||
+ | self.target_z2 = p.addUserDebugParameter(" | ||
+ | | ||
+ | self.grasp_mode1 = p.addUserDebugParameter(" | ||
+ | self.grasp_mode2 = p.addUserDebugParameter(" | ||
+ | | ||
+ | self.joint1_params = [] | ||
+ | self.joint2_params = [] | ||
+ | | ||
+ | for i in range(6): | ||
+ | joint_info = p.getJointInfo(self.robot_id1, | ||
+ | joint_lower_limit = joint_info[8] | ||
+ | joint_upper_limit = joint_info[9] | ||
+ | lower = joint_lower_limit if joint_lower_limit != 0.0 else -3.14 | ||
+ | upper = joint_upper_limit if joint_upper_limit != 0.0 else 3.14 | ||
+ | param_id = p.addUserDebugParameter(f" | ||
+ | self.joint1_params.append(param_id) | ||
+ | | ||
+ | for i in range(6): | ||
+ | joint_info = p.getJointInfo(self.robot_id2, | ||
+ | joint_lower_limit = joint_info[8] | ||
+ | joint_upper_limit = joint_info[9] | ||
+ | lower = joint_lower_limit if joint_lower_limit != 0.0 else -3.14 | ||
+ | upper = joint_upper_limit if joint_upper_limit != 0.0 else 3.14 | ||
+ | param_id = p.addUserDebugParameter(f" | ||
+ | self.joint2_params.append(param_id) | ||
+ | |||
+ | self.arm1_constraint = None | ||
+ | self.arm2_constraint = None | ||
+ | self.current_joint_positions1 = [0] * self.num_joints1 | ||
+ | self.current_joint_positions2 = [0] * self.num_joints2 | ||
+ | |||
+ | def compute_ik(self, | ||
+ | if target_orn is None: | ||
+ | target_orn = p.getQuaternionFromEuler([0, | ||
+ | | ||
+ | try: | ||
+ | joint_poses = p.calculateInverseKinematics( | ||
+ | robot_id, | ||
+ | ee_index, | ||
+ | target_pos, | ||
+ | target_orn | ||
+ | ) | ||
+ | return joint_poses | ||
+ | except: | ||
+ | current_poses = [] | ||
+ | for i in range(ee_index): | ||
+ | joint_info = p.getJointState(robot_id, | ||
+ | current_poses.append(joint_info[0]) | ||
+ | return current_poses | ||
+ | |||
+ | def move_arm_to_position(self, | ||
+ | target_orn = p.getQuaternionFromEuler([0, | ||
+ | joint_poses = self.compute_ik(robot_id, | ||
+ | for i in range(min(len(joint_poses), | ||
+ | p.setJointMotorControl2( | ||
+ | bodyUniqueId=robot_id, | ||
+ | jointIndex=i, | ||
+ | controlMode=p.POSITION_CONTROL, | ||
+ | targetPosition=joint_poses[i], | ||
+ | force=500 | ||
+ | ) | ||
+ | |||
+ | def check_grasp_proximity(self, | ||
+ | gripper_state = p.getLinkState(robot_id, | ||
+ | gripper_pos = gripper_state[0] | ||
+ | obj_pos, _ = p.getBasePositionAndOrientation(object_id) | ||
+ | distance = np.linalg.norm(np.array(gripper_pos) - np.array(obj_pos)) | ||
+ | return distance < threshold | ||
+ | |||
+ | def run_simulation(self): | ||
+ | print(" | ||
+ | prev_grasp1 = 0 | ||
+ | prev_grasp2 = 0 | ||
+ | | ||
+ | while True: | ||
+ | target_pos1 = [ | ||
+ | p.readUserDebugParameter(self.target_x1), | ||
+ | p.readUserDebugParameter(self.target_y1), | ||
+ | p.readUserDebugParameter(self.target_z1) | ||
+ | ] | ||
+ | | ||
+ | target_pos2 = [ | ||
+ | p.readUserDebugParameter(self.target_x2), | ||
+ | p.readUserDebugParameter(self.target_y2), | ||
+ | p.readUserDebugParameter(self.target_z2) | ||
+ | ] | ||
+ | | ||
+ | use_position_control = True | ||
+ | for i in range(6): | ||
+ | joint_val1 = p.readUserDebugParameter(self.joint1_params[i]) | ||
+ | joint_val2 = p.readUserDebugParameter(self.joint2_params[i]) | ||
+ | if abs(joint_val1) > 0.01 or abs(joint_val2) > 0.01: | ||
+ | use_position_control = False | ||
+ | break | ||
+ | | ||
+ | if use_position_control: | ||
+ | self.move_arm_to_position(self.robot_id1, | ||
+ | self.move_arm_to_position(self.robot_id2, | ||
+ | else: | ||
+ | for i in range(6): | ||
+ | joint_angle1 = p.readUserDebugParameter(self.joint1_params[i]) | ||
+ | p.setJointMotorControl2( | ||
+ | bodyUniqueId=self.robot_id1, | ||
+ | jointIndex=i, | ||
+ | controlMode=p.POSITION_CONTROL, | ||
+ | targetPosition=joint_angle1, | ||
+ | force=500 | ||
+ | ) | ||
+ | | ||
+ | joint_angle2 = p.readUserDebugParameter(self.joint2_params[i]) | ||
+ | p.setJointMotorControl2( | ||
+ | bodyUniqueId=self.robot_id2, | ||
+ | jointIndex=i, | ||
+ | controlMode=p.POSITION_CONTROL, | ||
+ | targetPosition=joint_angle2, | ||
+ | force=500 | ||
+ | ) | ||
+ | | ||
+ | grasp1 = p.readUserDebugParameter(self.grasp_mode1) | ||
+ | grasp2 = p.readUserDebugParameter(self.grasp_mode2) | ||
+ | | ||
+ | if grasp1 > 0.5 and prev_grasp1 < 0.5: | ||
+ | if self.check_grasp_proximity(self.robot_id1, | ||
+ | if self.arm1_constraint is None: | ||
+ | self.arm1_constraint = self.gripper1.grasp_object(self.object_id) | ||
+ | print(" | ||
+ | else: | ||
+ | print(" | ||
+ | elif grasp1 < 0.5 and prev_grasp1 > 0.5: | ||
+ | if self.arm1_constraint is not None: | ||
+ | self.gripper1.release_object(self.arm1_constraint) | ||
+ | self.arm1_constraint = None | ||
+ | print(" | ||
+ | | ||
+ | if grasp2 > 0.5 and prev_grasp2 < 0.5: | ||
+ | if self.check_grasp_proximity(self.robot_id2, | ||
+ | if self.arm2_constraint is None: | ||
+ | self.arm2_constraint = self.gripper2.grasp_object(self.object_id) | ||
+ | print(" | ||
+ | else: | ||
+ | print(" | ||
+ | elif grasp2 < 0.5 and prev_grasp2 > 0.5: | ||
+ | if self.arm2_constraint is not None: | ||
+ | self.gripper2.release_object(self.arm2_constraint) | ||
+ | self.arm2_constraint = None | ||
+ | print(" | ||
+ | | ||
+ | prev_grasp1 = grasp1 | ||
+ | prev_grasp2 = grasp2 | ||
+ | | ||
+ | p.stepSimulation() | ||
+ | time.sleep(1./ | ||
+ | |||
+ | def shutdown(self): | ||
+ | p.disconnect() | ||
+ | |||
+ | def main(): | ||
+ | sim = ARX5Simulation() | ||
+ | | ||
+ | try: | ||
+ | sim.run_simulation() | ||
+ | except KeyboardInterrupt: | ||
+ | print(" | ||
+ | finally: | ||
+ | sim.shutdown() | ||
+ | |||
+ | if __name__ == " | ||
+ | main() | ||
+ | </ | ||
+ |