Physics and Collisions
Understanding physics and collision properties is crucial for creating realistic digital twins. This section covers the principles of physics simulation and collision detection in both Gazebo and Unity environments.
Physics Simulation Fundamentals
Physics simulation in robotics environments involves modeling real-world physical behaviors:
- Rigid Body Dynamics: Movement and interaction of solid objects
- Collision Detection: Identifying when objects intersect
- Contact Response: Calculating forces when objects touch
- Constraints: Joints and connections between parts
Physics in Gazebo
Physics Engines
Gazebo supports multiple physics engines:
- ODE (Open Dynamics Engine): Default, good balance of speed and accuracy
- Bullet: Fast and robust, good for complex interactions
- Simbody: Highly accurate, suitable for biomechanics
- DART: Advanced constraint handling
Physics Configuration
In world files, configure physics properties:
<physics type="ode">
<max_step_size>0.001</max_step_size> <!-- Time step for simulation -->
<real_time_factor>1</real_time_factor> <!-- Simulation speed vs real time -->
<real_time_update_rate>1000</real_time_update_rate> <!-- Hz -->
<!-- Gravity -->
<gravity>0 0 -9.8</gravity>
<!-- ODE-specific parameters -->
<ode>
<solver>
<type>quick</type> <!-- or "pgs" -->
<iters>10</iters>
<sor>1.3</sor>
</solver>
<constraints>
<cfm>0</cfm>
<erp>0.2</erp>
<contact_max_correcting_vel>100</contact_max_correcting_vel>
<contact_surface_layer>0.001</contact_surface_layer>
</constraints>
</ode>
</physics>
Material Properties
Define material properties for realistic interactions:
<link name="link_with_materials">
<collision name="collision">
<geometry>
<box><size>0.1 0.1 0.1</size></box>
</geometry>
<surface>
<friction>
<ode>
<mu>0.5</mu> <!-- Static friction coefficient -->
<mu2>0.5</mu2> <!-- Secondary friction coefficient -->
<slip1>0.0</slip1> <!-- Primary slip coefficient -->
<slip2>0.0</slip2> <!-- Secondary slip coefficient -->
</ode>
</friction>
<bounce>
<restitution_coefficient>0.1</restitution_coefficient>
<threshold>100000</threshold>
</bounce>
<contact>
<ode>
<max_vel>100</max_vel>
<min_depth>0.001</min_depth>
</ode>
</contact>
</surface>
</collision>
</link>
Inertial Properties
Proper inertial properties are essential for realistic simulation:
<inertial>
<mass>1.0</mass>
<inertia>
<ixx>0.0833333</ixx>
<ixy>0.0</ixy>
<ixz>0.0</ixz>
<iyy>0.0833333</iyy>
<iyz>0.0</iyz>
<izz>0.0833333</izz>
</inertia>
</inertial>
For a box with mass m and dimensions (x, y, z):
- ixx = m*(y² + z²)/12
- iyy = m*(x² + z²)/12
- izz = m*(x² + y²)/12
Collision Detection in Gazebo
Collision Geometries
Gazebo supports various collision geometries:
- Box: Rectangular prism
- Cylinder: Cylindrical shape
- Sphere: Spherical shape
- Mesh: Complex shapes from 3D models
- Plane: Infinite flat surface
<collision name="collision_box">
<geometry>
<box><size>0.1 0.2 0.3</size></box>
</geometry>
</collision>
<collision name="collision_cylinder">
<geometry>
<cylinder>
<radius>0.05</radius>
<length>0.1</length>
</cylinder>
</geometry>
</collision>
<collision name="collision_sphere">
<geometry>
<sphere><radius>0.05</radius></sphere>
</geometry>
</collision>
Collision Filtering
Use collision groups and masks to control which objects can collide:
<collision name="collision_with_filter">
<surface>
<contact>
<collide_without_contact>false</collide_without_contact>
</contact>
</surface>
</collision>
Physics in Unity
Physics Engine
Unity uses NVIDIA PhysX for physics simulation, which provides:
- Advanced collision detection
- Realistic contact response
- Vehicle dynamics
- Cloth simulation
- Soft body dynamics
Rigidbody Configuration
Each physical object needs a Rigidbody component:
using UnityEngine;
public class PhysicsObject : MonoBehaviour
{
[Header("Physics Properties")]
public float mass = 1.0f;
public Vector3 centerOfMass = Vector3.zero;
public Vector3 inertiaTensor = Vector3.one;
public float drag = 0.0f;
public float angularDrag = 0.05f;
[Header("Collision Properties")]
public bool useGravity = true;
public bool isKinematic = false;
private Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
if (rb != null)
{
rb.mass = mass;
rb.centerOfMass = centerOfMass;
rb.inertiaTensor = inertiaTensor;
rb.drag = drag;
rb.angularDrag = angularDrag;
rb.useGravity = useGravity;
rb.isKinematic = isKinematic;
}
}
}
Collider Configuration
Unity supports various collider types:
// Box Collider
[RequireComponent(typeof(Rigidbody))]
public class BoxColliderSetup : MonoBehaviour
{
[SerializeField] private Vector3 size = Vector3.one;
[SerializeField] private Vector3 center = Vector3.zero;
[SerializeField] private bool isTrigger = false;
void Start()
{
BoxCollider boxCollider = gameObject.AddComponent<BoxCollider>();
boxCollider.size = size;
boxCollider.center = center;
boxCollider.isTrigger = isTrigger;
}
}
// Mesh Collider
[RequireComponent(typeof(Rigidbody))]
public class MeshColliderSetup : MonoBehaviour
{
[SerializeField] private bool convex = false;
[SerializeField] private bool inflateMesh = false;
void Start()
{
MeshCollider meshCollider = gameObject.AddComponent<MeshCollider>();
meshCollider.convex = convex;
meshCollider.inflateMesh = inflateMesh;
// Use the mesh from a MeshFilter component
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter != null)
{
meshCollider.sharedMesh = meshFilter.sharedMesh;
}
}
}
Joint Configuration
Unity provides various joint types for connecting rigidbodies:
// Hinge Joint Example
public class HingeJointSetup : MonoBehaviour
{
[SerializeField] private float motorForce = 10f;
[SerializeField] private float targetVelocity = 0f;
[SerializeField] private bool useMotor = false;
void Start()
{
HingeJoint hinge = GetComponent<HingeJoint>();
// Configure motor
JointMotor motor = hinge.motor;
motor.force = motorForce;
motor.targetVelocity = targetVelocity;
motor.freeSpin = false;
hinge.motor = motor;
hinge.useMotor = useMotor;
// Configure limits
JointLimits limits = hinge.limits;
limits.min = -90f; // Minimum angle in degrees
limits.max = 90f; // Maximum angle in degrees
hinge.limits = limits;
hinge.useLimits = true;
}
}
Physics Materials
Create realistic surface interactions:
// Create a physics material in code
public class PhysicsMaterialSetup : MonoBehaviour
{
[SerializeField] private float staticFriction = 0.5f;
[SerializeField] private float dynamicFriction = 0.4f;
[SerializeField] private float bounciness = 0.1f;
[SerializeField] private PhysicMaterialCombine frictionCombine = PhysicMaterialCombine.Average;
[SerializeField] private PhysicMaterialCombine bounceCombine = PhysicMaterialCombine.Average;
void Start()
{
PhysicMaterial material = new PhysicMaterial("CustomMaterial");
material.staticFriction = staticFriction;
material.dynamicFriction = dynamicFriction;
material.bounciness = bounciness;
material.frictionCombine = frictionCombine;
material.bounceCombine = bounceCombine;
Collider col = GetComponent<Collider>();
if (col != null)
{
col.material = material;
}
}
}
Collision Events
Unity Collision Detection
Handle collision events in Unity:
using UnityEngine;
public class CollisionHandler : MonoBehaviour
{
void OnCollisionEnter(Collision collision)
{
Debug.Log($"Collision with {collision.gameObject.name}");
foreach (ContactPoint contact in collision.contacts)
{
Debug.DrawRay(contact.point, contact.normal, Color.white);
Debug.Log($"Contact point: {contact.point}");
Debug.Log($"Contact force: {collision.impulse}");
}
}
void OnCollisionStay(Collision collision)
{
// Called each frame while colliding
foreach (ContactPoint contact in collision.contacts)
{
Debug.Log($"Contact force: {contact.force}");
}
}
void OnCollisionExit(Collision collision)
{
Debug.Log($"Collision ended with {collision.gameObject.name}");
}
// Trigger events (for isTrigger colliders)
void OnTriggerEnter(Collider other)
{
Debug.Log($"Trigger entered: {other.name}");
}
}
Advanced Physics Concepts
Continuous Collision Detection
For fast-moving objects to prevent tunneling:
void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
if (rb != null)
{
// Use continuous collision detection for fast objects
rb.collisionDetectionMode = CollisionDetectionMode.Continuous;
}
}
Layer-based Collision Matrix
Control which layers can collide with each other in Unity:
- Edit → Project Settings → Physics
- Configure the collision matrix for different layers
Force Application
Apply forces to simulate realistic interactions:
public class ForceApplication : MonoBehaviour
{
[SerializeField] private float forceMagnitude = 10f;
[SerializeField] private ForceMode forceMode = ForceMode.Force;
public void ApplyForce(Vector3 direction)
{
Rigidbody rb = GetComponent<Rigidbody>();
if (rb != null)
{
rb.AddForce(direction * forceMagnitude, forceMode);
}
}
public void ApplyTorque(Vector3 torque)
{
Rigidbody rb = GetComponent<Rigidbody>();
if (rb != null)
{
rb.AddTorque(torque * forceMagnitude, forceMode);
}
}
}
Performance Considerations
Gazebo Optimization
- Use simpler collision geometries when possible
- Adjust physics update rates for performance vs accuracy
- Use fixed joints instead of complex constraint systems
- Limit the number of active objects in simulation
Unity Optimization
- Use convex mesh colliders for dynamic objects
- Use compound colliders for complex shapes
- Adjust solver iteration counts for performance
- Use object pooling for frequently created/destroyed objects
Debugging Physics
Visualization Tools
- Enable physics visualization in both Gazebo and Unity
- Use debug drawing to visualize collision shapes
- Monitor simulation statistics and performance metrics
Common Issues
- Tunneling: Objects passing through each other (fix with CCD)
- Jittering: Unstable contact points (fix with proper mass ratios)
- Penetration: Objects sinking into each other (fix with proper solver settings)
Best Practices
- Use realistic mass properties (don't make everything 1kg)
- Configure friction coefficients based on real materials
- Test with extreme values to ensure stability
- Balance accuracy with performance requirements
- Validate simulation results against real-world data when possible
Exercise
Create a simulation scene with multiple objects of different materials and masses. Implement collision detection that triggers different behaviors based on collision forces. Test the scene with different physics configurations to observe the effects on stability and realism.