Files
ros_contorl/devices/sim/gazebo/urdf/arm.sim.ros2_control.xacro
T
arm_dev 25635e21f8 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>
2026-09-23 14:19:39 +08:00

64 lines
3.0 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?xml version="1.0"?>
<!--
=============================================================================
仿真版 ros2_control 硬件描述。
为什么不复用官方 flexiv_description 的 rizon.ros2_control.xacro:
那个宏只认两种硬件插件 —— 要么 mock_components/GenericSystem,
要么 flexiv_hardware/FlexivHardwareInterface(真机 RDK)。
Gazebo 需要第三种:gz_ros2_control/GazeboSimSystem。官方宏里没有这个分支,
而且改官方文件等于分叉上游描述,上游一升级就冲突。所以仿真自己写一份。
两处必须对齐,否则 controller_manager 会报 "no hardware interface found":
1. 关节名 —— 必须是 sim_joint1..sim_joint7(前缀 sim_,见 naming 约定)
2. command/state interface 名字 —— 必须与 gz_ros2_control 实际提供的接口一致
Gazebo 侧:position/velocity 可读可写,effort 只能读。
我们只下 position 指令(应用层走 JTC 位置轨迹),所以 command 只声明 position。
验证插件名的方法(换 Gazebo/ros2_control 版本后建议重跑一遍确认):
strings $CONDA_PREFIX/lib/libgz_ros2_control-system.so | grep GazeboSimSystem
cat $CONDA_PREFIX/share/gz_ros2_control/gz_hardware_plugins.xml
本机实测(gz_ros2_control 0.7.15):硬件名为 gz_ros2_control/GazeboSimSystem。
=============================================================================
-->
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="arm_sim_ros2_control" params="prefix joint_count:=7">
<ros2_control name="GazeboSimSystem" type="system">
<hardware>
<!--
Gazebo 的 ros2_control 硬件插件。它由 Gazebo 侧的系统插件
(arm.sim.gazebo.xacro 里声明的 GazeboSimROS2ControlPlugin)加载,
controller_manager 在 Gazebo 进程内被拉起来。
注意:硬件参数(update_rate 等)不写在这里,而是在 Gazebo 的
<plugin> 标签里配置(见 arm.sim.gazebo.xacro)。写在 <hardware> 下
不会生效,这是 gz_ros2_control 与真机 hardware 的一个区别。
-->
<plugin>gz_ros2_control/GazeboSimSystem</plugin>
</hardware>
<!-- 关节 1..7。全部只给 position 指令 + position/velocity 状态。 -->
<xacro:macro name="arm_sim_joint" params="name">
<joint name="${name}">
<command_interface name="position"/>
<state_interface name="position"/>
<state_interface name="velocity"/>
</joint>
</xacro:macro>
<xacro:arm_sim_joint name="${prefix}joint1"/>
<xacro:arm_sim_joint name="${prefix}joint2"/>
<xacro:arm_sim_joint name="${prefix}joint3"/>
<xacro:arm_sim_joint name="${prefix}joint4"/>
<xacro:arm_sim_joint name="${prefix}joint5"/>
<xacro:arm_sim_joint name="${prefix}joint6"/>
<xacro:arm_sim_joint name="${prefix}joint7"/>
</ros2_control>
</xacro:macro>
</robot>