P5c-2:仿真世界 + 机器人描述 + 控制器配置,并解决两处官方描述与 Gazebo 的不兼容
这一步解决的是"官方 Flexiv 描述能不能喂给 Gazebo"的问题。结论是**不能直接用**,
有两处不兼容,且都只有 Gazebo 会暴露 —— RViz/MoveIt 完全正常,所以此前从未发现。
问题一:7 轴本体的质量/惯量是"孤儿标签"
rizon_arm.xacro 调 get_inertias 时没写 <inertial> 包裹,而那个宏只吐
<origin>/<mass>/<inertia> 三个碎片。RViz/MoveIt 忽略不认识的子元素所以看着
没事;sdformat 判定 "link has no <inertial> block",然后把 **link 和它的父
关节一起丢掉**。症状极具误导性:机械臂凭空消失或只剩夹爪,报错只有一句
"link[sim_link1] is not modeled in sdf"。
问题二:夹爪有零质量 link,导致 sdformat 惯性叠加出 NaN
grav_macro.xacro 给六个纯坐标系 dummy link 写了 mass=0、惯量全 0。
sdformat 对 fixed 关节会把子 link 惯性叠加到父 link,叠加要除以总质量 →
质量 0 就出 NaN。而报错指向的是**父** link:
Pose values must be finite. link[sim_left_finger_mount]/inertial/pose
完全看不出根因在子 link 的质量上。
修法:启动时归一化(不走改上游文件的路,因为上游由 fetch_flexiv.sh 获取、改了会被
覆盖;而且换别的臂时大概率有别的坑,在启动时统一过一道更可持续)
- 孤儿三件套 → 只重新分组已有元素,一个数字都不改
- 零质量 → 补 1e-4 kg(与夹爪其他配件同量级,0.1g 对动力学无影响),
惯量全 0 时补极小对角值避免张量退化
不发明物理数据,也不掩盖真问题:上游真没给质量时这里什么都不会包。
16 项单测,含"已有 <inertial> 不能被二次包裹"(早期用全局正则踩过,
sdformat 报 "Inertial element must have a mass element")与幂等性。
新增/改动
- devices/sim/gazebo/urdf/:arm.sim.urdf.xacro(主)、.ros2_control(gz 硬件)、
.gazebo(系统插件/材质/接触刚度)、.sensors(D405 + 双指触觉)
- devices/sim/gazebo/worlds/assembly.world:1ms 步长 + 150 次接触迭代(力信号
要干净才谈得上"切向力突变"判据)、工作台、world 级渲染插件、D435
- devices/sim/gazebo/config/controllers.yaml:控制器名 rizon_arm_controller
**故意与真机一致** —— 隔离的是关节/TF 层(sim_ 前缀),不是应用层依赖的接口
- src/arm_sim_gazebo/:新包,含 urdf_normalize(库 + CLI)与单测
一处设计纠正:D435 从 URDF 挪进 world。原本挂在 URDF 的 world link 上,结果
整台相机转 SDF 时凭空消失(sdformat 丢弃无质量根 link 时连带丢了整棵子树,
且退出码 0、不报错)。眼在手外的相机物理上就属于场景,放 world 才对;
渲染插件也一并归 world 级,避免"插件在模型里、相机在世界里"的错配。
验证(不是只看退出码)
- 带夹爪全量:sdformat 退出码 0、0 报错、15 link / 15 joint / 26 frame
- 传感器 d405_rgbd + tactile_left/right 均在;控制器插件与参数路径正确
- 世界文件 sdformat 通过
- 包在 ros_gz_sim 环境构建通过,CLI 实跑结果与库调用一致
- 未注册 gazebo_sim_launcher 入口点:模块还没写,注册了构建能过但一运行就
ImportError,不如老实缺着(manifest 里如实标注为未实现)
注:实测确认 gz_ros2_control 的硬件/接口声明**不在 SDF 里**,插件是从
/robot_description 话题读 URDF 的 <ros2_control> —— 所以启动器必须先起
robot_state_publisher 且发布归一化后的同一份 URDF,否则控制器注册的关节名
会和 Gazebo 里的对不上。这条已写进 P5c-3 的实现要求。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,238 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
=============================================================================
|
||||
devices/sim/gazebo/worlds/assembly.world
|
||||
通止规装配场景。
|
||||
|
||||
由 site.yaml 的 sim.world 指向(留空则用 Gazebo 默认空世界):
|
||||
sim:
|
||||
world: "devices/sim/gazebo/worlds/assembly.world"
|
||||
|
||||
============================================================================
|
||||
物理引擎参数为什么这么调
|
||||
============================================================================
|
||||
装配任务的难点全在"接触"上:下压到碰、旋拧时切向力突变。这些判据能不能在
|
||||
仿真里复现,几乎完全由物理步长和接触求解器决定:
|
||||
max_step_size 1ms 步长太大时穿透会累积,接触力变成一坨噪声,
|
||||
柔顺下压的"突变检测"就废了。1ms 是精度与速度的折中。
|
||||
real_time_factor 仿真时间/真实时间的上限。设 1.0 表示最多实时;
|
||||
调低能让物理更稳(掉步少),调试接触时可设 0.5。
|
||||
solver_iters 接触求解迭代次数。插入/旋拧这种持续接触场景,
|
||||
默认 50 会"软",接触力抖动大;提到 150 明显更干净,
|
||||
代价是 CPU。若机器吃力,先降 real_time_factor,
|
||||
不要降 solver_iters —— 降了力信号就没法用了。
|
||||
=============================================================================
|
||||
-->
|
||||
<sdf version="1.9">
|
||||
<world name="assembly">
|
||||
|
||||
<!-- = 物理 -->
|
||||
<physics name="1ms" type="ignored">
|
||||
<max_step_size>0.001</max_step_size>
|
||||
<real_time_factor>1.0</real_time_factor>
|
||||
<real_time_update_rate>1000</real_time_update_rate>
|
||||
<!--
|
||||
物理引擎 = DART(Fortress 默认),碰撞检测器用 bullet。
|
||||
说明:引擎配置直接写在 <physics> 下(dart 子元素),不要写成
|
||||
<ignition::physics> —— SDF 的元素名里不允许出现 "::",
|
||||
sdformat 会直接报 XML not well-formed。"::" 只出现在插件名的
|
||||
属性值里(如 name="ignition::gazebo::systems::Sensors"),那是合法的。
|
||||
-->
|
||||
<dart>
|
||||
<collision_detector>bullet</collision_detector>
|
||||
</dart>
|
||||
<solver>
|
||||
<type>quick</type>
|
||||
<iters>150</iters>
|
||||
<sor>1.3</sor>
|
||||
</solver>
|
||||
<constraints>
|
||||
<cfm>0.0</cfm>
|
||||
<erp>0.2</erp>
|
||||
<contact_max_correcting_vel>0.1</contact_max_correcting_vel>
|
||||
<contact_surface_layer>0.001</contact_surface_layer>
|
||||
</constraints>
|
||||
</physics>
|
||||
|
||||
<!-- = 光照 -->
|
||||
<light type="directional" name="sun">
|
||||
<cast_shadows>true</cast_shadows>
|
||||
<pose>0 0 10 0 0 0</pose>
|
||||
<diffuse>0.8 0.8 0.8 1</diffuse>
|
||||
<specular>0.2 0.2 0.2 1</specular>
|
||||
<attenuation>
|
||||
<range>1000</range>
|
||||
<constant>0.9</constant>
|
||||
<linear>0.01</linear>
|
||||
<quadratic>0.001</quadratic>
|
||||
</attenuation>
|
||||
<direction>-0.5 0.1 -0.9</direction>
|
||||
</light>
|
||||
|
||||
<!-- = 地面 -->
|
||||
<model name="ground_plane">
|
||||
<static>true</static>
|
||||
<link name="link">
|
||||
<collision name="collision">
|
||||
<geometry>
|
||||
<plane><normal>0 0 1</normal><size>10 10</size></plane>
|
||||
</geometry>
|
||||
<surface>
|
||||
<friction>
|
||||
<ode><mu>0.8</mu><mu2>0.8</mu2></ode>
|
||||
</friction>
|
||||
</surface>
|
||||
</collision>
|
||||
<visual name="visual">
|
||||
<geometry>
|
||||
<plane><normal>0 0 1</normal><size>10 10</size></plane>
|
||||
</geometry>
|
||||
<material>
|
||||
<ambient>0.7 0.7 0.7 1</ambient>
|
||||
<diffuse>0.7 0.7 0.7 1</diffuse>
|
||||
</material>
|
||||
</visual>
|
||||
</link>
|
||||
</model>
|
||||
|
||||
<!-- =========================================================================
|
||||
工件台
|
||||
=========================================================================
|
||||
高度 0.75m 是常见工作台高度。工件就放在台面上(P5c-6 里会加),
|
||||
台面高度决定机械臂要不要伸到底 —— 先在仿真里确认工作空间够得着,
|
||||
再上真机试,能省掉很多次现场调试。
|
||||
|
||||
台面做成 static:台子本身不该被机械臂推着走。
|
||||
摩擦系数给足(0.8),否则柔顺下压时工件会被顶得滑动,
|
||||
仿真里看到"工件跑了"会让人误以为是跟踪算法的问题。
|
||||
========================================================================= -->
|
||||
<model name="work_table">
|
||||
<static>true</static>
|
||||
<pose>0.55 0 0 0 0 0</pose>
|
||||
<link name="top">
|
||||
<pose>0 0 0.375 0 0 0</pose>
|
||||
<collision name="collision">
|
||||
<geometry><box><size>0.8 1.2 0.05</size></box></geometry>
|
||||
<surface>
|
||||
<friction>
|
||||
<ode><mu>0.8</mu><mu2>0.8</mu2></ode>
|
||||
</friction>
|
||||
<contact>
|
||||
<ode>
|
||||
<kp>1e7</kp>
|
||||
<kd>1e4</kd>
|
||||
<max_vel>0.01</max_vel>
|
||||
<min_depth>0.001</min_depth>
|
||||
</ode>
|
||||
</contact>
|
||||
</surface>
|
||||
</collision>
|
||||
<visual name="visual">
|
||||
<geometry><box><size>0.8 1.2 0.05</size></box></geometry>
|
||||
<material>
|
||||
<ambient>0.45 0.4 0.35 1</ambient>
|
||||
<diffuse>0.55 0.5 0.42 1</diffuse>
|
||||
</material>
|
||||
</visual>
|
||||
</link>
|
||||
<!-- 四条腿,纯视觉:碰撞只保留台面,省掉不必要的接触计算 -->
|
||||
<link name="legs">
|
||||
<pose>0 0 0.175 0 0 0</pose>
|
||||
<visual name="visual">
|
||||
<geometry><box><size>0.7 1.1 0.35</size></box></geometry>
|
||||
<material>
|
||||
<ambient>0.3 0.3 0.3 1</ambient>
|
||||
<diffuse>0.35 0.35 0.35 1</diffuse>
|
||||
</material>
|
||||
</visual>
|
||||
</link>
|
||||
</model>
|
||||
|
||||
<!-- =========================================================================
|
||||
通止规起始位(留给人工/机械手放置用的标记区)
|
||||
=========================================================================
|
||||
真机上通止规是被人放到夹爪里的(P6 里有"提示用户放置"的交互)。
|
||||
仿真里这里放一个视觉标记,方便对着它调整"返回极值角是否到位"。
|
||||
真正会被夹爪抓取的通止规模型在 P5c-6 里加到这个位置。
|
||||
========================================================================= -->
|
||||
<model name="gauge_marker">
|
||||
<static>true</static>
|
||||
<pose>0.15 0.35 0.755 0 0 0</pose>
|
||||
<link name="link">
|
||||
<visual name="visual">
|
||||
<geometry><cylinder><radius>0.04</radius><length>0.004</length></cylinder></geometry>
|
||||
<material>
|
||||
<ambient>0.1 0.6 0.9 1</ambient>
|
||||
<diffuse>0.1 0.6 0.9 1</diffuse>
|
||||
</material>
|
||||
</visual>
|
||||
</link>
|
||||
</model>
|
||||
|
||||
<!-- =========================================================================
|
||||
传感器渲染系统插件(必须,且必须在 world 级)
|
||||
=========================================================================
|
||||
没有它,所有 <sensor> 标签被静默忽略 —— 退出码 0、不报错、话题永远
|
||||
没数据。排查"相机不出图"时,第一件事就是确认这个插件真的加载了:
|
||||
ign gazebo -v 3 ... 2>&1 | grep -i sensors
|
||||
|
||||
render_engine 用 ogre2:本机装了 libignition-rendering6-ogre2.so,
|
||||
且只有 ogre2 支持深度相机(老的 ogre 拿不到深度)。
|
||||
注:无头环境(没有显示器)下 ogre2 通常仍可用(走 EGL/软件渲染),
|
||||
但若报渲染相关错误,先试 `export LIBGL_ALWAYS_SOFTWARE=1`。
|
||||
========================================================================= -->
|
||||
<plugin filename="libignition-gazebo6-sensors-system.so"
|
||||
name="ignition::gazebo::systems::Sensors">
|
||||
<render_engine>ogre2</render_engine>
|
||||
</plugin>
|
||||
|
||||
<!-- =========================================================================
|
||||
RealSense D435 —— 眼在手外(俯视工作台)
|
||||
=========================================================================
|
||||
放在 world 而不是机械臂 URDF 里,因为这个相机在物理上就属于场景:
|
||||
它装在工作台支架上,不跟着机械臂动。
|
||||
(早期把它挂在 URDF 的 world link 上,结果转 SDF 时整台相机消失 ——
|
||||
sdformat 丢弃无质量根 link 时连带丢了整棵子树,且不报错。)
|
||||
|
||||
位姿:pitch≈50° 俯视,yaw=180° 让光轴转向机械臂一侧。
|
||||
视野必须完整覆盖台面 —— 粗定位失败要回退到这个视角,看不全工件就等于
|
||||
没有兜底方案。验收方法:
|
||||
ros2 topic hz /d435/color/image_raw # 有数
|
||||
rqt_image_view /d435/color/image_raw # 工件三个孔都在画面内
|
||||
========================================================================= -->
|
||||
<model name="d435">
|
||||
<static>true</static>
|
||||
<pose>-0.45 0.0 1.35 0.0 0.872665 3.14159</pose>
|
||||
<link name="link">
|
||||
<visual name="body">
|
||||
<geometry><box><size>0.09 0.025 0.025</size></box></geometry>
|
||||
<material>
|
||||
<ambient>0.15 0.15 0.15 1</ambient>
|
||||
<diffuse>0.2 0.2 0.2 1</diffuse>
|
||||
</material>
|
||||
</visual>
|
||||
<sensor name="d435_rgbd" type="rgbd_camera">
|
||||
<update_rate>30</update_rate>
|
||||
<always_on>true</always_on>
|
||||
<visualize>false</visualize>
|
||||
<camera name="d435">
|
||||
<!-- D435 视场较宽(约 87°×58°),粗定位需要比 D405 更宽的视野 -->
|
||||
<horizontal_fov>1.5184</horizontal_fov>
|
||||
<image>
|
||||
<width>640</width>
|
||||
<height>480</height>
|
||||
<format>R8G8B8</format>
|
||||
</image>
|
||||
<clip><near>0.1</near><far>10.0</far></clip>
|
||||
<depth_camera>
|
||||
<clip><near>0.1</near><far>10.0</far></clip>
|
||||
</depth_camera>
|
||||
</camera>
|
||||
<!-- 话题名对齐真机 ros_realsense,应用层两边通用 -->
|
||||
<topic>/d435</topic>
|
||||
</sensor>
|
||||
</link>
|
||||
</model>
|
||||
|
||||
</world>
|
||||
</sdf>
|
||||
Reference in New Issue
Block a user