P5c-3 仿真启动器跑通:Gazebo + spawn + 两个控制器 active
端到端验收(headless,本机无显示器):
ign 加载 Physics/UserCommands/SceneBroadcaster/Sensors + gz_ros2_control
机械臂 spawn 进 assembly 世界,7 个 sim_joint 全在 /joint_states
joint_state_broadcaster 与 rizon_arm_controller 双双 active
world → sim_tcp 可查,且末端位姿 3 秒内不变(重力下站住)
网格解析报错 0 条
新增:
scripts/run_sim_gz.sh 此前**不存在**,却被 install_sim_env.sh
与 build_sim.sh 的提示语引用
arm_sim_gazebo/robot_description.py 展开 + 归一化,launch 与 CLI 共用一份
arm_sim_gazebo/gazebo_sim_launcher.py 薄壳:准备描述后转发给 launch 文件
launch/gazebo_sim.launch.py 起 gz → 发归一化 URDF → spawn → 拉控制器
test/test_robot_description.py 含"仓库里这份 world 必须过守卫"的测试
接线过程中实测踩到并修掉的三个坑,共同特征是**每一步看起来都成功**:
1) urdf_normalize 在 Python 路径下静默失效(我自己引入的,最严重)
xacro 的输出格式在不同环境里不一样:真机环境的 CLI 缩进成多行,而仿真环境
走 xacro.process_file().toxml() 时全挤在一行。归一化的正则要求标签之间必须有
\n,于是**仿真路径下它什么都没做**(报告"包裹 0 处"),而 CLI 路径下正常 ——
之前那次"已修好"的验证走的就是 CLI,所以看起来过了。
后果是 Gazebo 会丢掉整条机械臂,正是这个归一化本来要防的事。
已改成对空白格式零假设,并加回归测试锁住。
2) world 里声明了 <plugin> 会把默认系统挤掉
只要 world 声明任何一个 <plugin>,Gazebo 就不再加载 server.config 的
Physics/UserCommands/SceneBroadcaster。缺 UserCommands →
/world/<名>/create 服务不存在 → ros_gz_sim create 调服务超时后回退发 topic、
没人收 → **模型从未进入 Gazebo**,而 create 节点仍打印
"OK creation of entity",控制器则永远卡在 "waiting for service"。
已在这三个系统在 assembly.world 里显式声明,并加纯文本守卫
check_base_plugins(),让"加了插件忘了补基础系统"在启动前就被指出。
3) gz 的插件与资源搜索路径缺 $CONDA_PREFIX/lib
gz_ros2_control 报 "Failed to load system plugin
[libgz_ros2_control-system.so] : couldn't find shared library",而 ldd 全齐、
库就在 $CONDA_PREFIX/lib 下。原因是 gz 的 SystemLoader 先在搜索路径里找文件,
找不到就直接放弃,不去 dlopen 裸文件名(所以 conda 二进制的 RPATH 兜不住);
而 ros_gz_sim 只把 LD_LIBRARY_PATH 拼进搜索路径,conda 激活并不往那里加。
同一原因导致 mesh 的 model:// 也解析不了(视觉报错很吵,但更要紧的是
**碰撞网格也加载不出来**,会让后续装配的接触判据失效)。
由于 gz_sim.launch.py 用 `from os import environ` 在生成 launch 描述时就读
进程环境,这些变量**必须在 ros2 launch 之前**设好,因此放在 sim_env.sh ——
在 launch 文件里用 SetEnvironmentVariable 补是无效的,会被它自己算的那份
字典覆盖。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -169,6 +169,41 @@
|
||||
</link>
|
||||
</model>
|
||||
|
||||
<!-- =========================================================================
|
||||
基础系统插件 —— 必须显式声明,否则整个仿真静默失效
|
||||
=========================================================================
|
||||
⚠️ 实测(本机 RoboStack/conda 的 Fortress 6.16):
|
||||
|
||||
world 文件里**只要声明了任何一个 <plugin>**,Gazebo 就不再加载
|
||||
server.config 里的默认系统列表(Physics / UserCommands /
|
||||
SceneBroadcaster)。声明一个 Sensors,就会把这三个挤掉。
|
||||
|
||||
后果极其隐蔽,因为每一步看起来都"成功":
|
||||
- 仿真照常启动、/clock 照常以 ~1000Hz 推进、物理也在算
|
||||
- 但没有 UserCommands → /world/assembly/create 服务不存在
|
||||
→ ros_gz_sim create 调服务超时,回退到发 topic,**没人收**
|
||||
→ 机械臂其实从未进入 Gazebo
|
||||
- create 节点仍然打印 "OK creation of entity",**看起来成功了**
|
||||
- 模型不存在 → gz_ros2_control 插件不会加载 → 没有 controller_manager
|
||||
→ 两个 spawner 永远卡在 "waiting for service"
|
||||
- 而且没有 SceneBroadcaster → /world/assembly/state 也没有
|
||||
→ `ign model -l` 也会超时
|
||||
|
||||
验证办法(应当同时看到 4 个系统:
|
||||
Physics / UserCommands / SceneBroadcaster / Sensors):
|
||||
ign gazebo -r -s -v 4 <world> 2>&1 | grep "Loaded system"
|
||||
或直接看服务在不在:
|
||||
ign service -l | grep -E "world/assembly/(create|state)"
|
||||
|
||||
⚠️ 因此:以后往这个 world 里加任何 <plugin>,都不要删掉下面这三个。
|
||||
========================================================================= -->
|
||||
<plugin filename="libignition-gazebo6-physics-system.so"
|
||||
name="ignition::gazebo::systems::Physics"/>
|
||||
<plugin filename="libignition-gazebo6-user-commands-system.so"
|
||||
name="ignition::gazebo::systems::UserCommands"/>
|
||||
<plugin filename="libignition-gazebo6-scene-broadcaster-system.so"
|
||||
name="ignition::gazebo::systems::SceneBroadcaster"/>
|
||||
|
||||
<!-- =========================================================================
|
||||
传感器渲染系统插件(必须,且必须在 world 级)
|
||||
=========================================================================
|
||||
|
||||
Reference in New Issue
Block a user