Pybullet导入URDF文件——并创建约束

Pybullet导入URDF文件——并创建约束

问题描述

一般地,在Pybullet中导入URDF文件,受到碰撞会产生移动 ;要想将导入的URDF文件固定,类似静态障碍物一样,需要对其另外创建约束

导入URDF文件

pybullet.loadURDF(path,position,orientation,flags=0):向物理服务器发送信息,加载URDF文件;返回创建模型的ID

  • path:URDF文件路径
  • position:世界坐标系X、Y、Z三维坐标
  • orientation:四元数
  • useFixedBase:True or False,是否使Base连杆保持固定;注意不是使其整体不动的意思,使其整体不动,需要createConstraint创建约束
  • flags:某些标志

创建约束

pybullet.createConstraint(parentBodyUniqueId, parentLinkIndex, childBodyUniqueId, childLinkIndex, jointType, jointAxis, parentFramePosition, childFramePosition):对两个连杆的关节进行约束

注:关节和连杆的关系如下:
在这里插入图片描述

各参数意义(Pybullet官方):

  • parentBodyUniqueId:父实体索引,loadURDF得到
  • parentLinkIndex:父实体的连杆索引,getNumJoints得到其关节数量,然后利用getLinkState依次输出各关节信息
  • childBodyUniqueId:子实体索引
  • childLinkIndex:子实体的连杆索引
  • jointType:关节的约束类型,如固定等(JOINT_PRISMATIC, JOINT_FIXED, JOINT_POINT2POINT, JOINT_GEAR)
  • jointAxis:在子连杆坐标系表示的关节轴
  • parentFramePosition:关节坐标系相对于父实体质心坐标系的位置(如果父实体为地面,那么则为子实体质心坐标系)
  • childFramePosition:关节坐标系相对于子实体质心坐标系的位置(getJointInfo函数返回的第15个值)
  • 其他参数省略(非必选参数)

创建一个约束:

floor_id = p.loadURDF('plane.urdf')
box_id = p.loadURDF(fileName='cube_no_rotation.urdf',basePosition=[2,2,0],baseOrientation=p.getQuaternionFromEuler([0, 0, 0]),useFixedBase=True)
p.createConstraint(floor_id, -1, box_id, 0, p.JOINT_FIXED, [0, 0, 0], [2, 2, 0], [0, 0, 0])  # 添加约束

注:有时候URDF文件并非只有一个关节,只固定一个还是会使其运动,所以需要尽可能得使多个关节固定,才能保证最后加载的物体不会移动。

完整代码见:

import pybullet as p
import pybullet_data
import os
# p.connect(p.DIRECT)
p.connect(p.GUI)
p.resetSimulation()
p.setGravity(0,0,-9.8)
p.setTimeStep(1./60)
p.setRealTimeSimulation(0)
p.setAdditionalSearchPath(pybullet_data.getDataPath())

# 加载模型
floor_id = p.loadURDF('plane.urdf')
box_id = p.loadURDF(fileName='cube_no_rotation.urdf',basePosition=[2,2,0],baseOrientation=p.getQuaternionFromEuler([0, 0, 0]),useFixedBase=True)
# 需要改一下自己的路径
robot_id1 = p.loadURDF(fileName='/home/xxx/urdf_and_meshes/robomaster.urdf',basePosition=[-3,2,1],baseOrientation=p.getQuaternionFromEuler([0, 0, 0]))
robot_id2 = p.loadURDF(fileName='/home/xxx/urdf_and_meshes/robomaster.urdf',basePosition=[2,-3,1],baseOrientation=p.getQuaternionFromEuler([0, 0, 0]))

numJoints = p.getNumJoints(box_id)
print("机器人关节的数量:", numJoints)

for index in range(numJoints):
    pos = p.getLinkState(box_id,index)
    print('rbox_id index is:',pos)

print("机器人关节的信息:")
for joint_index in range(numJoints):
    joint_info = p.getJointInfo(box_id, joint_index)
    # [0]关节索引:{joint_info[0]}
    # [1]关节名称:{joint_info[1]}
    # [2]关节类型:{joint_info[2]}
    # [3]此主体的位置状态变量中的第一个位置索引:{joint_info[3]}
    # [4]在这个物体的速度状态变量中的第一个速度索引:{joint_info[4]}
    # [5]保留参数:{joint_info[5]}
    # [6]关节阻尼大小:{joint_info[6]}
    # [7]关节摩擦系数:{joint_info[7]}
    # [8]滑动或旋转关节的位置下限:{joint_info[8]}
    # [9]滑动或旋转关节的位置上限:{joint_info[9]}
    # [10]关节最大力矩:{joint_info[10]}
    # [11]关节最大速度:{joint_info[11]}
    # [12]连杆名称:{joint_info[12]}
    # [13]在当前连杆坐标系中表示的移动或转动的关节轴(忽略JOINT_FIXED固定关节):{joint_info[13]}
    # [14]在父连杆坐标系中表示的关节位置:{joint_info[14]}
    # [15]在父连杆坐标系中表示的关节姿态(四元数x、y、z、w):{joint_info[15]}
    # [16]父连杆的索引,若是base连杆则返回-1:{joint_info[16]}

# 打印可使用关节
joints_indexes = [i for i in range(numJoints) if p.getJointInfo(box_id, i)[2] != p.JOINT_FIXED]  # 可以使用的关节索引
print([p.getJointInfo(box_id, i) for i in joints_indexes])

# 注意因为有四个关节,所以要有四个约束;否则最终还是会移动
cid1 = p.createConstraint(floor_id, -1, box_id, 0, p.JOINT_FIXED, [0, 0, 0], [2, 2, 0], [0, 0, 0])  # 添加约束
cid2 = p.createConstraint(floor_id, -1, box_id, 1, p.JOINT_FIXED, [0, 0, 0], [2, 2, 0], [0, 0, 0])  # 添加约束
cid3 = p.createConstraint(floor_id, -1, box_id, 2, p.JOINT_FIXED, [0, 0, 0], [2, 2, 0], [0, 0, 0])  # 添加约束
cid4 = p.createConstraint(floor_id, -1, box_id, 3, p.JOINT_FIXED, [0, 0, 0], [2, 2, 0], [0, 0, 0])  # 添加约束

while True:
    p.stepSimulation()
    # 验证小车装上之后,障碍物是否会移动
    p.resetBaseVelocity(objectUniqueId=robot_id1,
                        linearVelocity=[0.1, 0, 0],
                        angularVelocity=[0, 0, 0],
                        )
    p.resetBaseVelocity(objectUniqueId=robot_id2,
                        linearVelocity=[0, 0.1, 0],
                        angularVelocity=[0, 0, 0],
                        )

PS:

也可以利用createMultiBody函数创建不能移动的障碍物,只需要在创建createCollisionShapecreateVisualShape的时候将第一个参数改为GEOM_BOX

box_id = p.createCollisionShape(p.GEOM_BOX, halfExtents=[1+0.05, 1+0.05, 1])# 创建碰撞箱模型
box_visual_id = p.createVisualShape(p.GEOM_BOX,halfExtents=[1, 1, 1],rgbaColor=(0.1, 0.5, 0.1, 1))# 创建视觉模型
OBSTACLES_IDS[index] = p.createMultiBody(baseMass=0,baseCollisionShapeIndex=box_id,baseVisualShapeIndex=box_visual_id,basePosition=[1, 2, 0])

参考:
PyBullet仿真软件常用API函数
闭链机构的问题

### 四足机器人强化学习训练过程完整教程 #### 1. 环境搭建 为了实现四足机器人的强化学习控制,首先需要构建合适的开发环境。通常情况下,在 Docker 中安装 ROS 是一种高效的方式[^1]。这一步骤可以确保开发环境中所有的依赖项都被正确管理。 接着,需完成 NVIDIA Isaac Gym 的安装与配置。Isaac Gym 提供了一个高性能的物理仿真平台,能够支持大规模行化的强化学习训练任务。具体操作包括下载官方 SDK 按照文档说明进行编译和集成。 ```bash # 安装Docker sudo apt-get update && sudo apt-get install docker.io # 启动Docker服务 sudo systemctl start docker # 运行ROS容器镜像 docker run -it --net=host ros:noetic bash ``` #### 2. 模型设计与仿真 在建立好基础框架之后,应定义四足机器人的动力学参数以及关节控制器特性。这些数据可以通过 URDF 文件描述,导入至 Gazebo 或 PyBullet 等工具中验证其行为表现是否合理。 对于更复杂的动作规划需求,则可借助 Humanoid-Gym 库来扩展功能集[^2]。尽管此项目专注于双足行走研究领域,但它所包含的一些通用技术同样适用于多腿结构的设计思路: - **状态空间表示**:选取恰当的状态变量集合(如位置、速度等),以便后续策略网络能有效捕捉动态变化规律; - **奖励函数设定**:依据实际应用场景定制目标导向型指标体系,鼓励期望的行为模式发生概率最大化; #### 3. 强化学习算法应用 基于上述准备工作完成后即可引入主流 RL 方法论开展实验探索活动。例如 PPO (Proximal Policy Optimization),它凭借稳定性强、收敛速度快等特点成为当前热门选项之一。 在此过程中需要注意的是,由于现实世界中的硬件约束条件往往难以完全复制到虚拟场景里去,因此还需要采取额外措施减少两者之间的差异影响程度——即所谓的 Sim-to-Real Gap 问题解决办法。“Walk These Ways” 方案正是为此目的而提出的创新解决方案,通过对不同地面材质特性的建模分析进一步提升迁移效果质量水平。 #### 4. 部署测试 最后阶段涉及将经过充分调优后的神经网络模型移植回实体设备上执行在线推理计算工作流。期间可能还会遇到诸如延迟补偿机制调整之类的细枝末节挑战事项待克服处理完毕才算真正意义上的全流程闭环结束标志点到达时刻到来之际庆祝一番也是理所当然之事啦! ```python import torch from isaacgym import gymapi def load_model(path): model = torch.load(path) return model.eval() model_path = 'trained_policy.pth' policy = load_model(model_path) # Initialize simulation environment... env = setup_isaac_env() observation = env.reset() while True: action = policy(torch.tensor(observation)) observation, reward, done, _ = env.step(action.detach().numpy()) if done: break ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值