Stabilizing Gazebo Physics: Solving Jitter and Crashes in ODE
Stop your Gazebo robots from jittering or flying away. Learn how to optimize ODE physics by balancing mass ratios, using collision primitives, and tuning step sizes.
15 Nov 2025, 07:21 UTC

The "Jitter" Problem in Rigid Body Simulation
You have designed a robot in CAD, imported the meshes into Gazebo, and hit play. Instead of a smooth movement, your robot vibrates violently, slides across the floor as if on ice, or simply disappears from the world map. This is rarely a bug in Gazebo itself; it is usually a failure of the underlying physics solver—the Open Dynamics Engine (ODE)—to resolve the mathematical constraints of your model.
The takeaway: Stability in Gazebo depends on simplifying collision geometry and maintaining balanced mass ratios. If the solver cannot find a mathematical equilibrium within a single time step, it introduces "energy" into the system, resulting in the jittering behavior common in poorly configured simulations.
Collision Primitives vs. Visual Meshes
A common mistake is using the same high-polygon STL or Collada file for both the visual representation and the collision properties. The ODE solver must calculate contact points between surfaces; calculating these for a mesh with thousands of triangles is computationally expensive and numerically unstable.
To fix this, use collision primitives—simplified shapes like boxes, spheres, and cylinders. These have closed-form mathematical solutions for collisions, which are faster and more stable than mesh-to-mesh intersections. In your SDF (Simulation Description Format) file, you should separate the <visual> tag from the <collision> tag.
Managing Mass Ratios and Inertia
Numerical instability often stems from extreme differences in mass between two connected links. If a 100kg chassis is connected to a 0.01kg sensor via a joint, the ODE solver may struggle to calculate the forces acting on the lighter object, leading to "explosions" where the sensor flies off into infinity.
Additionally, the inertia tensor—the distribution of mass around an axis—must be physically plausible. Setting inertia values to zero or leaving them undefined can cause the solver to divide by zero or produce NaN (Not a Number) results, crashing the simulation instance.
Example: Optimizing a Linked Arm
Consider a simple robotic arm consisting of two links and a revolute joint. Below is a conceptual SDF configuration that prioritizes stability over visual perfection.
<model name="stable_arm">
<link name="link1">
<inertial>
<mass>1.0</mass>
<inertia>
<ixx>0.1</ixx><iyy>0.1</iyy><izz>0.1</izz>
</inertia>
</inertial>
<collision name="collision1">
<geometry>
<box><size>0.1 0.1 0.5</size></box>
</geometry>
</collision>
<visual name="visual1">
<geometry>
<mesh><uri>model://arm/meshes/link1.dae</uri></mesh>
</geometry>
</visual>
</link>
<joint name="joint1" type="revolute">
<parent>link1</parent>
<child>link2</child>
<axis>
<xyz>0 0 1</xyz>
</axis>
</joint>
</model>
Diagnostic Check
To verify if your physics settings are the cause of instability, run the simulation and monitor the CPU load. If CPU usage spikes during collisions, your collision meshes are too complex. If the model jitters while stationary, check the mass ratio between link1 and link2.
Tuning the World Step Size
If your model is physically sound but still unstable, the problem may be the simulation time step. This is defined in the <physics> section of the world file:
<max_step_size>: The amount of simulated time that passes in one iteration (e.g., 0.001s).<real_time_update_rate>: How many iterations the engine attempts per second of real-world time.
Reducing the max_step_size (e.g., from 0.01 to 0.001) increases precision and stability but requires more computational power. If the real_time_update_rate is set to 1000 and the max_step_size is 0.001, the simulation will run in real-time. If you lower the step size further, the simulation may run slower than real-time.
Limitations and Trade-offs
While simplifying collisions and reducing step sizes improves stability, it introduces a trade-off in fidelity. A bounding box collision may allow a visual mesh to "overlap" slightly with another object, or it may prevent a robot from gripping a specifically shaped object. You must balance the need for mathematical stability against the requirement for precise contact geometry.
Actionable Summary
When your Gazebo model behaves erratically, follow this triage sequence:
- Simplify: Replace all mesh collisions with primitive boxes or cylinders.
- Balance: Ensure no two connected links have a mass ratio exceeding 1:10.
- Validate: Check that all inertia tensors contain non-zero, positive values.
- Refine: Decrease
max_step_sizein the world file to increase solver precision.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.