Gazebo model — Bouncing Ball
A runnable gz-sim package generated from this bond graph: the SDFormat model with real inertia tensors, joint damping, Coulomb friction and spring stiffness, a world carrying the gravity the graph assumes, and the same mechanism as URDF for ROS 2 and RViz. The numbers here are the ones the 3D geometry view animates, so a Gazebo run can be compared against the in-app simulation.
Launch
- Check the SDF
gz sdf -k Bouncing_Ball/model.sdf
Validate the model against the SDFormat spec before running it.
- Run in Gazebo
GZ_SIM_RESOURCE_PATH=$PWD gz sim -r -v4 bondgraph_world.sdf
Launch gz-sim with the generated world. The resource path lets `model://` find the package folder.
- Watch joint states
gz topic -e -t /world/bondgraph_world/model/Bouncing_Ball/joint_state
Stream joint positions and velocities so they can be compared against the bond graph run.
- ROS 2
ros2 launch ros_gz_sim gz_sim.launch.py gz_args:="-r bondgraph_world.sdf"
Same world through ros_gz_sim, when the model is part of a ROS 2 stack.
Files
The mechanism: links, inertia tensors, joints and dynamics.
<?xml version="1.0" ?>
<!-- Generated by BondGraph Studio (https://xn--lda.se) — SDFormat for Gazebo -->
<!-- Gravity 9.81 m/s² along -Z, inferred from gravity. -->
<sdf version="1.9">
<model name="Bouncing_Ball">
<self_collide>false</self_collide>
<link name="base_link">
<gravity>false</gravity>
<inertial>
<mass>1</mass>
<inertia><ixx>0.001</ixx><ixy>0</ixy><ixz>0</ixz><iyy>0.001</iyy><iyz>0</iyz><izz>0.001</izz></inertia>
</inertial>
</link>
<joint name="base_link_world_joint" type="fixed">
<parent>world</parent>
<child>base_link</child>
</joint>
<link name="mass">
<pose relative_to="mass_joint">0 0 0 0 0 0</pose>
<gravity>true</gravity>
<inertial>
<pose>0 0 0 0 0 0</pose>
<mass>1</mass>
<inertia>
<ixx>0.00166667</ixx><ixy>0</ixy><ixz>0</ixz>
<iyy>0.00166667</iyy><iyz>0</iyz><izz>0.00166667</izz>
</inertia>
</inertial>
<visual name="mass_visual">
<pose>0 0 0 0 0 0</pose>
<geometry>
<box><size>0.1 0.1 0.1</size></box>
</geometry>
<material>
<ambient>0.85 0.55 0.2 1</ambient>
<diffuse>0.85 0.55 0.2 1</diffuse>
</material>
</visual>
<collision name="mass_collision">
<pose>0 0 0 0 0 0</pose>
<geometry>
<box><size>0.1 0.1 0.1</size></box>
</geometry>
<surface>
<friction>
<ode><mu>1</mu><mu2>1</mu2></ode>
</friction>
</surface>
</collision>
</link>
<joint name="mass_joint" type="prismatic">
<pose relative_to="base_link">0 0 0 0 0 0</pose>
<parent>base_link</parent>
<child>mass</child>
<axis>
<xyz>0 0 1</xyz>
<limit>
<lower>-1</lower>
<upper>1</upper>
<effort>1000</effort>
<velocity>100</velocity>
</limit>
<dynamics>
<damping>0</damping>
<friction>0</friction>
<spring_stiffness>1e-9</spring_stiffness>
<spring_reference>0</spring_reference>
</dynamics>
</axis>
</joint>
</model>
</sdf>Physics parity
Gravity 9.81 m/s² along -Z, inferred from gravity.
| Joint | Type | 3D-view variable | Mass | Damping | Friction | Spring |
|---|---|---|---|---|---|---|
| mass_joint | prismatic | q_height | 1 | 0 | 0 | 1e-9 |
- Gravity in the world file (0 0 -9.81 m/s²) is the gravity the bond graph run assumed — if you change it, the two will diverge.
- Link masses and inertia tensors in model.sdf match the Physics panel of the geometry view exactly; both come from the same exporter.
- Joint damping, Coulomb friction and spring stiffness come from the R and C elements on each DOF — a mismatch means a hint or parameter changed after export.
- Contact is the one thing the bond graph does not model: impacts in Gazebo follow the surface friction and restitution in model.sdf, not the graph.
- Echo /world/bondgraph_world/model/Bouncing_Ball/joint_state while the world runs and plot it against the simulation results to compare trajectories.
Agents can generate this same package over the MCP API with the export_gazebo_model tool.