当前位置: 首页 > news >正文

【MuJoCo学习笔记】#2 接触动力学 腱系统 执行器 传感器

接触动力学

接触力

# 定义带接触的自由体模型
free_body_MJCF = """
<mujoco><!-- 纹理和材质定义 --><asset><!-- 棋盘格纹理 --><texture name="grid" type="2d" builtin="checker" rgb1=".1 .2 .3"rgb2=".2 .3 .4" width="300" height="300" mark="edge" markrgb=".2 .3 .4"/><material name="grid" texture="grid" texrepeat="2 2" texuniform="true"reflectance=".2"/></asset><worldbody><!-- 跟踪质心的光源 --><light pos="0 0 1" mode="trackcom"/><!-- 地面,带接触参数 --><geom name="ground" type="plane" pos="0 0 -.5" size="2 2 .1" material="grid" solimp=".99 .99 .01" solref=".001 1"/><!-- 自由运动的盒子和球体 --><body name="box_and_sphere" pos="0 0 0"><freejoint/>  <!-- 6自由度 --><!-- 红色盒子,带接触参数 --><geom name="red_box" type="box" size=".1 .1 .1" rgba="1 0 0 1" solimp=".99 .99 .01" solref=".001 1"/><!-- 绿色球体 --><geom name="green_sphere" size=".06" pos=".1 .1 .1" rgba="0 1 0 1"/><!-- 固定相机视角 --><camera name="fixed" pos="0 -.6 .3" xyaxes="1 0 0 0 1 2"/><!-- 跟踪相机视角 --><camera name="track" pos="0 -.6 .3" xyaxes="1 0 0 0 1 2" mode="track"/></body></worldbody>
</mujoco>
"""

元素详解

  • asset
    • texture
      • mark/markrgb:颜色标记,edge 在棋盘格边缘添加标记线
  • worldbody
    • light
      • mode:光源的行为模式,trackcom 跟踪整个系统的质心位置
    • geom
      • solimp:接触参数,旧版本只有前三个参数,指数默认 2,刚度默认 1
        • dmin, dmax:产生接触力的距离阈值 dmax⁡d_{\max}dmaxdmin⁡d_{\min}dmin
        • width:接触力分布的宽度 width\mathrm{width}width
        • exponent:接触力的指数参数 eee
        • stiffness:接触刚度系数 kkk
        • 接触力关于穿透深度 ddd 的函数
          • F(d)=k⋅(d−dmin⁡dmax⁡−dmin⁡)e\displaystyle F(d)=k\cdot\left(\frac{d-d_{\min}}{d_{\max}-d_{\min}}\right)^eF(d)=k(dmaxdminddmin)e
    • camera
      • mode:相机行为模式,track 跟随其父物体 body
# 加载模型
model = mujoco.MjModel.from_xml_string(free_body_MJCF)
data = mujoco.MjData(model)
height = 400
width = 600# 渲染初始状态
with mujoco.Renderer(model, height, width) as renderer:mujoco.mj_forward(model, data)renderer.update_scene(data, "fixed")media.show_image(renderer.render())

# 慢动作渲染,可视化接触点和接触力
n_frames = 200
height = 240
width = 320
frames = []# 创建可视化选项
options = mujoco.MjvOption()
mujoco.mjv_defaultOption(options)
# 启用接触点可视化
options.flags[mujoco.mjtVisFlag.mjVIS_CONTACTPOINT] = True
# 启用接触力可视化
options.flags[mujoco.mjtVisFlag.mjVIS_CONTACTFORCE] = True
# 启用透明模式
options.flags[mujoco.mjtVisFlag.mjVIS_TRANSPARENT] = True# 调整接触可视化元素的比例
model.vis.scale.contactwidth = 0.1   # 接触点宽度
model.vis.scale.contactheight = 0.03 # 接触点高度
model.vis.scale.forcewidth = 0.05    # 力矢量宽度
model.vis.map.force = 0.3             # 力矢量缩放# 设置随机初始旋转速度
mujoco.mj_resetData(model, data)
data.qvel[3:6] = 5*np.random.randn(3)  # 随机角速度# 仿真并录制视频
with mujoco.Renderer(model, height, width) as renderer:for i in range(n_frames):# 1/4倍速仿真while data.time < i/120.0:mujoco.mj_step(model, data)# 使用跟踪相机渲染renderer.update_scene(data, "track", options)frame = renderer.render()frames.append(frame)# 显示慢动作视频
media.show_video(frames, fps=30)

倍速仿真

在遍历总数为 nframe 的视频帧的过程中,原速下每一帧截取的间隔为 1/fps,在 n 倍速下则应为 n/fps,故第 i 帧的时刻为 ni/fps

访问仿真运动数据

上一篇末尾我们提到如何记录分析仿真运动数据,由于这一步代码冗长、重复度高,且 matplotlib 绘图不是该系列的重点,因此这里仅列出访问仿真过程相应数据属性的方法。

目前涉及到 mjData 的部分属性如下:

  • time:时刻
  • 运动学相关
    • qpos:关节的广义位姿。对于单个自由关节(即自由刚体),[0:3] 为位置向量,[3:7] 为姿态四元数。对于更多刚体/关节,我们需要访问 mjModel 中的
      • jnt_qposadr[i]:查询索引为 i 的关节在 qpos 中的起始索引,位姿表示方式由关节类型决定
    • xpos:刚体位置矩阵,第一个索引为刚体 ID,第二个索引为刚体在世界坐标系下的坐标(0=x, 1=y, 2=z
    • geom_xpos:几何体位置矩阵,数据结构与 xpos 对应
    • qvel:刚体和关节的广义速度。对于单个自由刚体, [0:3] 为线速度,[3:6] 为角速度。对于更多刚体/关节,我们需要访问 mjModel 中的
      • body_dofadr[i]/jnt_dofadr[i]:查询索引为 i 的刚体/关节在 qvel 中的起始索引
      • body_dofnum[i]/jnt_dofnum[i]:查询索引为 i 的刚体/关节的自由度数
      • 刚体/关节在 qvel 中的终止索引=起始索引+自由度数
      • 除了自由刚体, qvel 中关节的速度通常是在自身的局部坐标系(取决于关节类型)中,而关节连接的刚体速度通常在父刚体的局部坐标系(父刚体的惯性主轴)中
      • 还可以通过 mjData.joint('name').qvel
    • cvel:刚体的复合速度。只涉及刚体在世界坐标系下的线速度和角速度,按刚体索引排序,即对于索引为 i 的刚体,其速度切片为 [i*6:i*6+6]
    • qacc:刚体和关节的加速度,数据结构与 qvel 对应
    • cacc:刚体的复合加速度,数据结构与 cvel 对应
    • energy:第一个元素为系统动能,第二个元素为系统势能
    • 高级 API:通过 mjData.body("name")mjData.joint("name") 可以直接通过名称而非索引查询来访问刚体和关节的运动学数据
  • 动力学相关
    • ncon:活动接触数
    • contact:活动接触点,对于每个索引的接触点对象有如下属性
      • dist:最小接触距离(负值为最大穿透)
      • pos:接触点世界坐标系位置
      • frame:接触点坐标系(3*3 矩阵)
        • frame[2]:接触法线方向
        • frame[0]:接触切向方向 1
        • frame[1]:接触切向方向 2
      • friction:摩擦系数
      • solref:约束求解器参数
      • solimp:阻抗参数
    • qfrc_constraint:约束广义力,包含所有约束产生的广义力/力矩,数据结构与 qvel 对应

摩擦力

# 演示不同摩擦系数的效果
MJCF = """
<mujoco><asset><!-- 棋盘格纹理 --><texture name="grid" type="2d" builtin="checker" rgb1=".1 .2 .3"rgb2=".2 .3 .4" width="300" height="300" mark="none"/><material name="grid" texture="grid" texrepeat="6 6"texuniform="true" reflectance=".2"/><material name="wall" rgba='.5 .5 .5 1'/></asset><!-- 默认设置 --><default><geom type="box" size=".05 .05 .05" /><joint type="free"/></default><worldbody><light name="light" pos="-.2 0 1"/><!-- 倾斜的地面,低摩擦 --><geom name="ground" type="plane" size=".5 .5 10" material="grid"zaxis="-.3 0 1" friction=".1"/><!-- 侧视相机 --><camera name="y" pos="-.1 -.6 .3" xyaxes="1 0 0 0 1 2"/><!-- 低摩擦盒子 --><body pos="0 0 .1"><joint/><geom/></body><!-- 高摩擦盒子 --><body pos="0 .2 .1"><joint/><geom friction=".33"/></body></worldbody></mujoco>
"""

元素详解

  • friction:摩擦属性,对于各向同性摩擦只需给出一个摩擦系数,而在各向异性摩擦中可以依次给出滑动摩擦(主要方向和次要方向)、扭转摩擦和滚动摩擦(主要方向和次要方向)
n_frames = 60
height = 300
width = 300
frames = []# 加载模型
model = mujoco.MjModel.from_xml_string(MJCF)
data = mujoco.MjData(model)# 仿真并录制视频
with mujoco.Renderer(model, height, width) as renderer:mujoco.mj_resetData(model, data)for i in range(n_frames):while data.time < i/30.0:mujoco.mj_step(model, data)renderer.update_scene(data, "y")frame = renderer.render()frames.append(frame)# 显示摩擦对比
media.show_video(frames, fps=30)

腱系统、执行器和传感器

为了实现更完善的机械系统建模,我们还需要以下元素:

  • 腱系统:虚拟的弹性连接,类似于生物肌腱,用于定义和执行复杂驱动和约束的机制。
  • 执行器:将控制信号转换为物理力的组件。
  • 传感器:从模拟环境中提取各种物理量和数据的接口,相较于直接访问 mjData 可以模拟真实世界传感器的噪声、偏差、延迟、采样频率等。
# 演示腱系统、执行器和传感器
MJCF = """
<mujoco><asset><!-- 棋盘格纹理 --><texture name="grid" type="2d" builtin="checker" rgb1=".1 .2 .3"rgb2=".2 .3 .4" width="300" height="300" mark="none"/><material name="grid" texture="grid" texrepeat="1 1"texuniform="true" reflectance=".2"/></asset><worldbody><light name="light" pos="0 0 1"/><!-- 地面 --><geom name="floor" type="plane" pos="0 0 -.5" size="2 2 .1" material="grid"/><!-- 锚点(腱的固定端) --><site name="anchor" pos="0 0 .3" size=".01"/><!-- 固定相机 --><camera name="fixed" pos="0 -1.3 .5" xyaxes="1 0 0 0 1 2"/><!-- 支柱 --><geom name="pole" type="cylinder" fromto=".3 0 -.5 .3 0 -.1" size=".04"/><!-- 球棒 --><body name="bat" pos=".3 0 -.1"><!-- 铰链关节,带阻尼 --><joint name="swing" type="hinge" damping="1" axis="0 0 1"/><!-- 球棒几何体 --><geom name="bat" type="capsule" fromto="0 0 .04 0 -.3 .04"size=".04" rgba="0 0 1 1"/></body><!-- 目标物体 --><body name="box_and_sphere" pos="0 0 0"><joint name="free" type="free"/><geom name="red_box" type="box" size=".1 .1 .1" rgba="1 0 0 1"/><geom name="green_sphere"  size=".06" pos=".1 .1 .1" rgba="0 1 0 1"/><!-- 挂钩点(腱的移动端) --><site name="hook" pos="-.1 -.1 -.1" size=".01"/><!-- IMU传感器位置 --><site name="IMU"/></body></worldbody><!-- 腱系统:连接锚点和挂钩 --><tendon><spatial name="wire" limited="true" range="0 0.35" width="0.003"><site site="anchor"/><site site="hook"/></spatial></tendon><!-- 执行器:驱动球棒 --><actuator><motor name="my_motor" joint="swing" gear="1"/></actuator><!-- 传感器:加速度计 --><sensor><accelerometer name="accelerometer" site="IMU"/></sensor>
</mujoco>
"""

元素详解

  • site:站点,用于定义特定位置、标记点或附加点的虚拟实体
    • pos:位置,若未给出则默认为所属 body 的局部坐标系原点或世界坐标系原点
    • size:视觉尺寸
  • tendon:腱系统
    • spatial :空间肌腱
      • limited:肌腱长度限制,启用后肌腱长度会被限制在 range 指定的范围内
      • width:肌腱视觉宽度
      • site:肌腱将以第一个 site 为起点,最后一个 site 为终点,可以有任意个途径点
  • actuator:执行器
    • motor:电机执行器,直接对关节施加力或扭矩
      • joint:目标关节
      • gear:传动比,输出力(扭矩)=传动比*控制输入
  • sensor:传感器
    • accelerometer:加速度计传感器
      • site:测量点位置
# 加载模型
model = mujoco.MjModel.from_xml_string(MJCF)
data = mujoco.MjData(model)
height = 480
width = 480# 渲染初始状态
with mujoco.Renderer(model, height, width) as renderer:mujoco.mj_forward(model, data)renderer.update_scene(data, "fixed")media.show_image(renderer.render())

通过 mjDatactrl[i]sensor('name').data 可以实现执行器按索引控制和传感器按名称读取:

# 设置仿真参数
n_frames = 180
height = 240
width = 320
frames = []
fps = 60.0
times = []       # 时间序列
sensordata = []  # 传感器数据# 设置恒定的执行器控制信号
mujoco.mj_resetData(model, data)
data.ctrl = 20  # 施加20牛米的力矩# 仿真并录制视频
with mujoco.Renderer(model, height, width) as renderer:for i in range(n_frames):# 仿真到下一帧时间while data.time < i/fps:mujoco.mj_step(model, data)times.append(data.time)# 记录加速度计数据sensordata.append(data.sensor('accelerometer').data.copy())# 渲染帧renderer.update_scene(data, "fixed")frame = renderer.render()frames.append(frame)# 显示球棒击打过程
media.show_video(frames, fps=fps)

http://www.dtcms.com/a/398142.html

相关文章:

  • 北京 旅游攻略
  • python+django/flask+springboot个性化旅游推荐系统(数据可视化) 景点推荐 路线匹配 用户画像建模 智能搜索筛选 图文展示系统
  • 智慧校园信息门户网站建设一站式做网站哪家好
  • 携程HR面(准备)
  • Qt 框架知识体系
  • 如何重新编译HyperLPR原生库以消除16k对齐警告
  • [QT]常用控件属性一
  • QT 编写应力分析软件
  • INTLAB区间工具箱在区间分析算法中的应用与实现
  • 北京网页设计新趋势黄石市seo关键词优化怎么做
  • 【Linux】拆解 Linux 容器化核心:Namespace 隔离 + cgroups 资源控制,附 LXC 容器生命周期实战
  • VSCode IDE环境的python 显示:Import “rclpy“ could not be resolvedPylancer
  • 吴镇宇做的电影教学网站石家庄最新消息今天
  • MySQL笔记8
  • 【C++无数组矩阵对角线平均值保留2位小数】2022-11-18
  • 阿里巴巴网站费用怎么做分录烟台企业展厅设计
  • ZooKeeper与Kafka分布式协调系统实战指南:从基础原理到集群部署
  • lesson66:JavaScript BOM与DOM全解析:从基础到现代前端实践引言:前端开发的两大基石
  • UNIAPP如何自定义全局方法?
  • 040 线程控制
  • 前端开发利器:nvm、npm与pnpm全面解析与TypeScript/JavaScript选择指南
  • 电影网站如何做seo哪家网站建设公司好
  • LeetCode 刷题【90. 子集 II】
  • Spring Boot启动报错:Failed to configure a DataSource 全面解析与解决方案
  • MongoDB源码delete分析观察者getOpObserver()->onDelete
  • 企业网站模板htmlwordpress cos 配置
  • ACL 2025 Time-LlaMA 大语言模型高效适配时间序列预测
  • 2025开发者云服务器评测:AWS, Vercel, Railway该如何选?
  • 金融数据库--下载全市场股票日线行情数据
  • HTML `<meter>` 标签:原生度量衡指示器,直观展示百分比、评分等量化数据