- 机器人
【免费下载链接】gz-sim
Open source robotics simulator. The latest version of Gazebo.
gz model是 Gazebo Sim(gz-sim)提供的命令行工具,用于在正在运行的仿真中查询模型(model)的位姿、Link(含质量与惯性张量)以及 Joint(含父子 Link 与关节类型)等信息。本篇以仓库自带的diff_drive示例世界为实验场景,完整走通--list、-m、--pose、--link、--joint等命令的实际用法与输出字段,并基于 src/cmd/model_main.cc 与 src/cmd/ModelCommandAPI.cc 的源码,解释命令背后"服务调用 → 状态快照 → ECM 组装"的实现链路,以及文档未展开的--sensor传感器查询能力。读完后,你可以独立地在任意运行中的 Gazebo 场景里按模型名、Link 名、Joint 名、传感器名精确提取结构化状态,并将其用于调试、日志比对或自动化脚本。
一、gz model命令概览
gz model命令用于获取某个正在运行的 Gazebo 仿真中各模型的信息。对每一个模型,你可以获取:
- Pose(位姿):模型在仿真中的当前位姿;
- Links:每个 Link 的位姿、质量(mass)与惯性张量(inertial matrix),以及挂载在 Link 上的传感器;
- Joints:每个 Joint 的父 Link、子 Link 与关节类型。
需要特别强调的是:该命令依赖一个正在运行的仿真服务端。它通过服务调用向正在运行的 server 请求世界名与状态快照,本地并不维护任何模型数据。一旦没有可用的仿真进程,命令会在服务调用超时后报错退出(详见后文"无仿真进程时的行为")。
从命令行结构看,gz model是一个由 CLI11(经gz-utils::cli)解析参数的独立可执行程序,入口在 model_main.cc。它把用户输入解析成一个ModelOptions结构体,再分发到cmdModelList()或cmdModelInfo()两个核心函数(见 ModelCommandAPI.hh)。
二、准备一个运行中的仿真:加载diff_drive世界
要试用该命令,先需要一个正在运行的仿真。仓库自带的差分驱动示例世界位于 examples/worlds/diff_drive.sdf,其中定义了ground_plane、vehicle_blue、vehicle_green三个模型,并挂载了gz-sim-diff-drive-system等系统插件。
在一个终端中加载该世界:
gz sim diff_drive.sdf该 SDF 使用
<physics name="1ms">配置 1 ms 最大步长、实时因子 1.0,并启用Physics、UserCommands、SceneBroadcaster三个系统插件。vehicle_blue的初始位姿为<pose>0 2 0.325 0 -0 0</pose>,vehicle_green为<pose>0 -2 0.325 0 -0 0</pose>——这解释了后文输出中两个车模分别位于 y=±2 处的原因。
等待 Gazebo 启动完成(服务端就绪、开始步进)后,即可在新终端中使用gz model。下面逐条演示。
三、列出当前世界中的模型:gz model --list
打开一个新终端,执行:
gz model --list预期打印出当前世界中所有顶层模型:
Requesting state for world [diff_drive]... Available models: - ground_plane - vehicle_blue - vehicle_green第一行Requesting state for world [diff_drive]...来自源码中populateECM()的提示(ModelCommandAPI.cc),说明命令已经取到世界名并正在拉取状态。随后cmdModelList()会遍历世界下所有Model组件的实体并打印其名字(ModelCommandAPI.cc)。
拿到模型名后,就可以用-m查询具体属性。
四、查询模型完整信息:gz model -m <model_name>
-m, --model用于选中要查看的模型。不带--pose/--link/--joint等限定参数时,cmdModelInfo()会把printAll置为true,一次性输出模型的位姿、全部 Link 与全部 Joint(见 ModelCommandAPI.cc)。
例如查询vehicle_blue:
gz model -m vehicle_blue输出(节选自 tutorials/model_command.md,字段含义见下表):
Requesting state for world [diff_drive]... Model: [8] - Name: vehicle_blue - Pose [ XYZ (m) ] [ RPY (rad) ]: [0.000000 | 2.000000 | 0.325000] [0.000000 | 0.000000 | 0.000000] - Link [9] - Name: chassis - Parent: vehicle_blue [8] - Mass (kg): [1.143950] - Inertial Pose [ XYZ (m) ] [ RPY (rad) ]: [0.000000 0.000000 0.000000] [0.000000 -0.000000 0.000000] - Inertial Matrix (kg⋅m^2): [0.126164 | 0.000000 | 0.000000] [0.000000 | 0.416519 | 0.000000] [0.000000 | 0.000000 | 0.481014] - Pose [ XYZ (m) ] [ RPY (rad) ]: [-0.151427 | 0.000000 | 0.175000] [0.000000 | 0.000000 | 0.000000] - Link [12] - Name: left_wheel - Parent: vehicle_blue [8] - Mass (kg): [2.000000] - Inertial Pose: [0.000000 | 0.000000 | 0.000000] - Inertial Matrix (kg⋅m^2): [0.145833 | 0.000000 | 0.000000] [0.000000 | 0.145833 | 0.000000] [0.000000 | 0.000000 | 0.125000] - Pose [ XYZ (m) ] [ RPY (rad) ]: [0.554283 | 0.625029 | -0.025000] [-1.570700 | 0.000000 | 0.000000] ...(right_wheel、caster 等 Link 依此类推) - Joint [21] - Name: left_wheel_joint - Parent: vehicle_blue [8] - Type: revolute - Parent Link: chassis - Child Link: left_wheel - Pose [ XYZ (m) ] [ RPY (rad) ]: [0.000000 | 0.000000 | 0.000000] [0.000000 | 0.000000 | 0.000000] - Axis position [ XYZ ]: [0 | 0 | 1] ...(right_wheel_joint、caster_wheel 依此类推)输出字段与 SDF 的对应关系:
| 输出字段 | 含义 | 来源 |
|---|---|---|
Model: [8] | 模型实体 ID(Entity),方括号内为运行时句柄 | components::Name/ Entity |
Pose [ XYZ ] [ RPY ] | 模型位姿(平移 + 姿态) | components::Pose |
Mass (kg) | Link 质量 | components::Inertial |
Inertial Matrix | Link 惯性张量(3×3) | components::Inertial |
Parent Link / Child Link | 关节连接的父/子 Link | components::ParentLinkName/ChildLinkName |
Type: revolute / ball ... | 关节类型 | components::JointType |
Axis position [ XYZ ] | 关节旋转轴单位向量 | components::JointAxis |
这些 Link 的质量、惯性、位姿数值与 examples/worlds/diff_drive.sdf 中<inertial>段声明完全一致——例如chassis的<mass>1.14395</mass>、<ixx>0.126164</ixx>等。可以据此核对"仿真加载后的物理属性是否与模型文件定义一致"。
五、只查模型位姿:gz model -m <model_name> --pose
-p, --pose是布尔标志(需与--model搭配),只输出模型的位姿部分:
gz model -m vehicle_blue --poseRequesting state for world [diff_drive]... Model: [8] - Name: vehicle_blue - Pose [ XYZ (m) ] [ RPY (rad) ]: [0.000000 2.000000 0.325000] [0.000000 0.000000 0.000000]对应cmdModelInfo()中if (printAll || _pose) printModelInfo(...)的分支(ModelCommandAPI.cc),printModelInfo()仅打印名称与位姿(ModelCommandAPI.cc)。适合在自动化脚本里只取位姿、避免解析大段 Link/Joint 文本。
六、查询 Link:gz model -m <model_name> --link [link_name]
-l, --link需要与--model搭配,参数可选:
- 不带参数:打印该模型下全部Link;
- 带 Link 名:只打印指定 Link。
# 全部 Link gz model -m vehicle_blue --link # 单个 Link gz model -m vehicle_blue --link caster单个 Link(caster)的输出:
Requesting state for world [diff_drive]... - Link [18] - Name: caster - Parent: vehicle_blue [8] - Mass (kg): [1.000000] - Inertial Pose: [0.000000 | 0.000000 | 0.000000] - Inertial Matrix (kg⋅m^2): [0.100000 | 0.000000 | 0.000000] [0.000000 | 0.100000 | 0.000000] [0.000000 | 0.000000 | 0.100000] - Pose [ XYZ (m) ] [ RPY (rad) ]: [-0.957138 | 0.000000 | -0.125000] [0.000000 | -0.000000 | 0.000000]从源码看,printLinks()遍历模型下所有带Link组件的子实体;当_linkName非空且不等于当前 Link 名时continue跳过(ModelCommandAPI.cc)。值得注意的是:在 Link 的打印块里,还会顺带输出挂载在该 Link 上的传感器——这也是下文--sensor能工作的基础。
七、查询 Joint:gz model -m <model_name> --joint [joint_name]
-j, --joint同样需与--model搭配,参数可选,语义与--link一致(全量 / 单个)。
# 全部 Joint gz model -m vehicle_blue --joint # 单个 Joint gz model -m vehicle_blue --joint caster_wheel单个 Joint(caster_wheel,类型为 ball)的当前输出(取自 ModelCommandAPI_TEST.cc 的断言):
Requesting state for world [diff_drive]... - Joint [23] - Name: caster_wheel - Parent: vehicle_blue [8] - Type: ball - Parent Link: chassis [9] - Child Link: caster [18] - Pose [ XYZ (m) ] [ RPY (rad) ]: [0.000000 0.000000 0.000000] [0.000000 0.000000 0.000000]对于 revolute 关节(如left_wheel_joint),还会额外打印Axis unit vector [ XYZ ](来自components::JointAxis),ball/fixed 等无轴关节则不打印轴向量。printJoints()内部维护了一张"关节类型 → 字符串"的映射表,覆盖revolute、ball、continuous、fixed、gearbox、prismatic、revolute2、screw、universal九种(ModelCommandAPI.cc)。
版本提示:tutorials/model_command.md 截取的输出较早期,Joint 部分标注为
Axis position、且父子 Link 不带实体 ID;当前源码与测试断言的标签为Axis unit vector [ XYZ ],且Parent Link / Child Link会附带实体 ID(如chassis [9])。两者信息一致,仅渲染格式随版本略有差异。
八、完整参数一览
汇总 model_main.cc 中addModelFlags()注册的参数。除教程已覆盖的几项外,还有--sensor、--version等:
| 参数 | 类型 | 依赖 | 说明 |
|---|---|---|---|
--list | flag | 无 | 列出当前世界所有模型 |
-m, --model <name> | 选项 | 无 | 选中要查看的模型(触发信息打印) |
-p, --pose | flag | --model | 只打印模型位姿 |
-l, --link [name] | 选项 | --model | 打印全部 Link,或指定 Link;可省略参数打印全部 |
-s, --sensor [name] | 选项 | --model且--link | 打印 Link 上全部传感器,或指定传感器;可省略参数打印全部 |
-j, --joint [name] | 选项 | --model | 打印全部 Joint,或指定 Joint;可省略参数打印全部 |
-v, --version | flag | 无 | 打印当前库版本(GZ_SIM_VERSION_FULL) |
--force-version/--versions | flag | 无 | 由 gz-tools 顶层处理的版本选择 |
-h, --help | flag | 无 | 打印帮助 |
--sensor在 CLI11 中通过->needs(modelCmd)->needs(linkCmd)强制要求同时提供--model和--link(model_main.cc)。它属于"教程未展开、但源码已支持"的能力:
# 打印 air_pressure_model 的 link 上名为 air_pressure_sensor 的传感器 gz model -m air_pressure_model -l link -s air_pressure_sensor测试用例 ModelCommandAPI_TEST.cc 给出了 air pressure 传感器的示例输出,包含Reference altitude (m)与Pressure noise(均值、偏差、标准差等)字段;同理还有 altimeter、gpu lidar、magnetometer、rgbd camera 等传感器类型,分别由printAirPressure/printAltimeter/printGpuLidar/printMagnetometer/printRgbdCamera/printCamera/printImu处理(ModelCommandAPI.cc)。每个打印函数会先检查实体是否持有对应的传感器组件(如components::Camera),不匹配则直接返回,因此可以放心地"全量试探"。
九、深入源码:gz model如何拿到数据
理解了"命令 → 服务 → 快照 → 打印"的链路,就能解释所有报错与输出。
9.1 取世界名:/gazebo/worlds
getWorldName()创建一个 transport 节点,以 5 秒超时阻塞调用/gazebo/worlds服务,取回StringMsg_V的首个元素作为世界名;超时或失败则返回空串并打印相应错误(ModelCommandAPI.cc)。
9.2 拉取状态快照并灌入 ECM:/world/<name>/state
populateECM()用取到的世界名拼出服务地址/world/<world>/state,阻塞请求一个msgs::SerializedStepMap,成功后调用ecm.SetState(res.state()),把整步状态"回放"进一个本地的EntityComponentManager(ModelCommandAPI.cc)。这正是命令行能脱离 GUI、纯靠服务通信读取状态的关键:它本地重建了一份 ECM 副本,后续所有查询都在这份副本上进行。
9.3 列表与详情
cmdModelList():先用components::World()找到世界实体,再用ParentEntity(world) + Model()找出所有顶层模型,按实体 ID 排序后打印(ModelCommandAPI.cc)。cmdModelInfo():根据是否携带--pose/--link/--joint/--sensor决定printAll;模型不存在时打印No model named <...> was found(ModelCommandAPI.cc)。
9.4 命令与仿真的隔离
单元测试 ModelCommandAPI_TEST.cc 在SetUp()中为每个测试生成唯一的GZ_PARTITION(UUID),用以隔离多个并行 server 的通信命名空间。这提示:当机器上同时跑多个 Gazebo 实例时,应通过GZ_PARTITION区分,gz model会连接到同一 partition 内的服务端。
十、无仿真进程时的行为
这是排查"命令报错"的关键。测试 ModelCommandAPI_TEST.cc 专门验证了"没有 server 在跑"时的输出:
Service call to [/gazebo/worlds] timed out Command failed when trying to get the world name of the running simulation.原因正是 9.1/9.2 节所述的两次服务调用:/gazebo/worlds超时后,getWorldName()返回空串,populateECM()随即打印Command failed when trying to get the world name...并退出。因此,如果你看到这条提示,优先确认gz sim <world>是否已启动、以及GZ_PARTITION是否一致。
十一、构建、测试与脚本分发的说明
- 可执行程序名为
gz-sim-model,由model_main.cc+ModelCommandAPI.cc构建,链接gz-utils::cli与 gz-sim 主库(src/cmd/CMakeLists.txt)。 - 顶层
gz model经由 Ruby 脚本cmdmodel.rb(由 cmdmodel.rb.in 配置生成)与 model.yaml.in 描述的子命令元信息分发到对应可执行程序;model.yaml声明library_name: gz-sim-gz、子命令model: Print information about models.。 - bash 补全脚本 model.bash_completion.sh 提供
--list、-m/--model、-p/--pose、-l/--link、-j/--joint、-h/--help、--force-version、--versions等候选项;测试ModelHelpVsCompletionFlags会校验补全脚本中的每个 flag 都能出现在--help输出里(ModelCommandAPI_TEST.cc)。 - 相关单元测试仅在存在有效显示(
VALID_DISPLAY AND VALID_DRI_DISPLAY)时才纳入构建(src/cmd/CMakeLists.txt),测试使用的静态世界为 test/worlds/static_diff_drive_vehicle.sdf,含ground_plane与vehicle_blue两个模型。
小结
gz model --list列出世界中的模型;gz model -m <name>一次性打印位姿 + 全部 Link + 全部 Joint。--pose/--link [name]/--joint [name]/--sensor [name]用于按需过滤,参数可省略以打印对应类别的全部项;--sensor必须同时给出--model与--link。- 底层链路为:
/gazebo/worlds取世界名 →/world/<name>/state拉取状态快照 → 本地ECM.SetState()重建副本 → 按组件(Name/Pose/Inertial/Joint/Sensor 等)查询并格式化打印。 - 排查要点:无仿真进程会报
Service call to [/gazebo/worlds] timed out;多实例并行时用GZ_PARTITION隔离。
以上信息均可在当前仓库中复现:命令定义见 src/cmd/model_main.cc、业务逻辑见 src/cmd/ModelCommandAPI.cc、行为断言见 src/cmd/ModelCommandAPI_TEST.cc、示例世界见 examples/worlds/diff_drive.sdf。
- 机器人
【免费下载链接】gz-sim
Open source robotics simulator. The latest version of Gazebo.
相关推荐
gz-sim(Gazebo Sim)机器人仿真器:特性全览、命令行实战与仓库源码结构解析
gz sim(Gazebo Sim)机器人仿真器:特性全览、命令行实战与仓库源码结构解析 本文以 gz sim 仓库根目录的 README.md https:/
机器人gz-sim 调试指南:使用 GDB 调试 Gazebo 命令行工具与仿真服务端/GUI
gz sim 调试指南:使用 GDB 调试 Gazebo 命令行工具与仿真服务端/GUI Gazebo(gz sim)的命令行入口 gz 建立在 Ruby 脚本
机器人gz-sim 迁移指南:从 Gazebo-classic 的 Actor API 到 gz::sim 的实体组件模型
gz sim 迁移指南:从 Gazebo classic 的 Actor API 到 gz::sim 的实体组件模型 导读 本文是面向 Gazebo class
机器人
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考