☰
gz-sim 的 `gz model` 命令详解:查询运行中仿真里模型的位姿、Link 与 Joint
2026/10/14 20:26:21 网站建设 项目流程
  • 机器人

【免费下载链接】gz-sim

Open source robotics simulator. The latest version of Gazebo.

项目地址:https://gitcode.com/gh_mirrors/gz/gz-sim
点击查看免费下载

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 MatrixLink 惯性张量(3×3)components::Inertial
Parent Link / Child Link关节连接的父/子 Linkcomponents::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 --pose
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]

对应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等:

参数类型依赖说明
--listflag无列出当前世界所有模型
-m, --model <name>选项无选中要查看的模型(触发信息打印)
-p, --poseflag--model只打印模型位姿
-l, --link [name]选项--model打印全部 Link,或指定 Link;可省略参数打印全部
-s, --sensor [name]选项--model且--link打印 Link 上全部传感器,或指定传感器;可省略参数打印全部
-j, --joint [name]选项--model打印全部 Joint,或指定 Joint;可省略参数打印全部
-v, --versionflag无打印当前库版本(GZ_SIM_VERSION_FULL)
--force-version/--versionsflag无由 gz-tools 顶层处理的版本选择
-h, --helpflag无打印帮助

--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.

项目地址:https://gitcode.com/gh_mirrors/gz/gz-sim
点击查看免费下载
上一篇:Blue Hydra设备分类与识别:如何准确识别不同类型的蓝牙设备
下一篇:Appsmith 的 Cursor AI 协作开发规范:.cursor 目录设计、规则体系与工程实践

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询