Simulating Physical Systems
A simulator lets you test a robot while a crash can still be reset with one button. You will model motion, sensors, motors and contact, then run the same control software in simulated and physical machines.
A simulation is a test instrument, not a prediction machine. Write down what the model includes, what it leaves out, and which measurement would prove it wrong. A detailed picture does not make weak physics trustworthy.
Work through Control Systems first. Basic algebra is enough. The later steps use ideas from Robotics, Drones and Autonomous Systems, with links back when you need them.
The route through the course
See a simulation as a flip book
Draw a bouncing ball in the corner of a notebook, one drawing per page. Flip the pages with your thumb and the ball moves. A simulation works exactly like that book. It never creates smooth motion. It creates one drawing after another, and each drawing is worked out from the drawing before it.
The stretch of time between two pages is the time step. A short step needs many pages for one second of motion, but each page sits close to its neighbour. A long step needs fewer pages, and the motion turns jumpy and can go badly wrong.
Another picture for the same idea: filling a bottle from a tap. The real world pours as a smooth stream. A simulation pours in cupfuls, one cup per page. Small cups track the stream closely. One huge cup overshoots the mark.
Adding up many small changes, page after page, has an old name: integration. The rule that turns one page into the next is the integration method. Different rules make different mistakes, and Step 3 puts two of them side by side.
Computers never really do continuous motion
Even the smoothest game or film runs page by page. A cinema film shows 24 pictures per second. A physics engine may compute hundreds of pages per drawn frame. The flip book is not a simplification of simulation. It is what simulation is.
Describe a moving system with state
What must be written on a flip-book page so the next page can be drawn? That list of numbers is the state. A cart moving along a rail needs position and velocity. A drone needs position, velocity, orientation and turning rate. The state should contain enough information to work out what happens next.
An input changes that state. For the cart, motor force creates acceleration. During one small time interval, acceleration changes velocity and velocity changes position. Repeating that update produces motion.
State and parameters are different jobs
State changes while the simulation runs. Parameters describe the object or environment and usually stay fixed during one run: mass, wheel radius and motor constant are examples. Keeping the two separate makes logs and tests much easier to read.
Choose a time step that keeps the answer useful
The time step is usually written as dt, short for a small difference in time. It is the cup size from Step 1. A smaller dt follows quick changes more closely but needs more calculations for the same second.
The integration method matters too. Explicit Euler moves the position using the old velocity. Semi-implicit Euler updates velocity first, then moves the position with the new velocity. Both are approximations. Both can fail when dt is too large for the fastest motion in the model.
Fixed steps, variable steps and real-time speed
A physics engine may use a fixed dt even when the picture renders at a variable frame rate. It can take several physics steps before drawing one frame. Faster-than-real-time testing removes the wait between steps, but it should not change dt or the equations.
Find the time step where the answer explodes
Push a playground swing at the same point of every pass and each small push stacks on the one before. The swing climbs on timing, not on strength. A too-large time step pushes a simulated spring in the same way. Each update overshoots slightly, the overshoot feeds the next update, and the motion grows with no real energy source.
A simulation is stable when small errors fade or stay small as the steps go on. It is unstable when every step makes the last error bigger. The border between the two is set by the time step and the fastest motion in the model. Running for longer does not move it.
Now give the model one slow part and one very fast part, like a heavy door on a very stiff hinge spring. You care about the slow door, but the fast spring sets the cup size. A model like this is called stiff. Its fastest piece forces tiny time steps even when the motion you want to watch is slow.
Why the border sits near the fastest cycle
For the explicit spring in this lab, the border sits where the step covers too much of the fastest cycle at once. Stiffer springs cycle faster, so their border moves to smaller dt. Semi-implicit Euler tolerates more, and implicit methods more still, at a higher cost per step. Whatever the method, halve dt and check that the answer settles.
Keep units and coordinate frames explicit
A number such as 3.2 is incomplete until you know its unit and frame. Three metres east in the map frame is not three metres forward in the robot frame. The same point has different coordinates when the axes move or turn.
A transform converts coordinates between frames. For a flat robot, rotate the point by the robot heading, then add the robot position. In three dimensions, use a rotation matrix or quaternion rather than three angles patched together in different orders.
Common frame conventions
ROS commonly uses x forward, y left and z up for a robot body. Camera images often use x right and y down. Flight software may use north-east-down. None is wrong. The bug appears when software changes convention without an explicit transform.
Give each body a shape, mass and inertia
A rigid-body model treats an object as a shape that does not bend. Its mass controls straight-line acceleration. Its moment of inertia controls turning acceleration and depends on where the mass sits, not only how much mass there is.
Simulation files often separate a detailed visual mesh from a simpler collision shape. That is useful. A small set of boxes, cylinders and convex shapes usually makes contact faster and more stable than thousands of tiny triangles.
URDF, SDF and simulator-native models
URDF describes robot links and joints well. SDF also describes worlds, lights, sensors and richer simulator details. Many tools can import both, but extensions differ. Keep the physical parameters in a reviewed source file and generate tool-specific forms when possible.
Model contact, friction and wheel slip
Contact is where two shapes meet without passing through each other. A physics engine detects the overlap, estimates a contact force, and applies friction along the surface. Stiff contact behaves like the stiff spring in Step 4, so it needs small time steps or careful solving.
Coulomb friction gives a useful first model: maximum braking force is the friction coefficient multiplied by the normal force. Real tyres, carpets, dust and wet floors do not keep one fixed coefficient, so stopping distance belongs in a range.
Why contact engines need tolerances
Perfectly hard bodies would need an infinite force to stop overlap instantly. Engines allow a tiny penetration or use a soft constraint, then correct it over several updates. The solver iterations, contact stiffness and dt work together.
Add the faults real sensors have
A perfect sensor gives a controller information it will never have on hardware. Useful models add random noise, a fixed or slowly changing bias, quantisation, delay, limited update rate and missing samples.
Add one fault at a time before combining them. Use a fixed random seed while debugging so the same run produces the same samples. Later, sweep many seeds to check that success was not luck.
Model the measurement pipeline, not only its final noise
A camera has exposure time, rolling or global shutter, image transport, processing and a timestamp. A lidar scans different angles at different times. A useful simulator records when a measurement was made and when the controller received it.
Add limits and delay to actuators
A motor does not jump to a requested speed. It takes time to build current and torque. It may have deadband near zero, a maximum output, and a limit on how fast its command can change. It also grows weaker as the battery voltage falls.
These limits belong inside the plant model, not inside the controller. Otherwise the controller appears to achieve commands that the hardware cannot produce. Log requested output and achieved output as separate signals.
First-order lag is a starting model
A first-order model moves a fixed fraction of the remaining gap each update. It captures one response time. Real motors may also need electrical dynamics, propeller or wheel load, gearbox backlash, thermal limits and a speed-dependent torque curve.
Put the simulator behind the hardware interface
The safest software boundary is simple: control code asks for sensor samples and writes actuator commands. In simulation, an adapter gets those values from the physics engine. On hardware, another adapter talks to drivers. The controller should not know which adapter is active.
Time is part of the boundary. Use timestamps from a clock interface instead of reading wall-clock time throughout the controller. A simulated clock can pause, run faster than real time and replay an exact log.
class RobotIO:
def read(self) -> SensorFrame: ...
def write(self, command: MotorCommand) -> None: ...
def now(self) -> float: ...
def control_tick(io, controller):
sample = io.read()
command = controller.update(sample, io.now())
io.write(command)
Software-in-the-loop is more than a physics picture
Software-in-the-loop, or SIL, runs the production control program against simulated inputs and outputs. If the simulation uses a separate toy controller, it can test physics ideas but it does not test the code that will ship.
Choose a simulator that fits the job
No simulator is best for every question. Start from the behaviour you need to test. That might be a first 3D robot, ROS integration, a flight stack, fast contact dynamics, camera data, embedded firmware or radio signal processing.
Use supported combinations of operating system, middleware and simulator. A newer package is not useful if the flight stack or teaching computers do not support it. Record the versions in the project so another person can reproduce the run.
For current general ROS work, use ROS 2 Lyrical with Gazebo Jetty. For the PX4 v1.17 classroom path, Ubuntu 24.04 with ROS 2 Jazzy and Gazebo Harmonic is the supported pairing. Webots R2025a is a good first 3D simulator. Check the official compatibility pages before starting a new project.
Where Wokwi and GNU Radio fit
Wokwi is useful for firmware logic, digital peripherals and early wiring practice, but its analogue behaviour is limited. Measure power, noise and timing on the real board. GNU Radio 3.10 is the stable line for modelling radio signal chains. GNU Radio 4.0 is still a release candidate in 2026, so do not make it a classroom dependency yet.
Build and test a mobile robot
Begin with a body, two driven wheels, a caster, wheel joints and measured mass properties. Add encoders and one distance sensor. Put walls and one movable obstacle in the world. Only then connect the controller through the interface from Step 10.
Test a straight drive, a turn in place and a stop before planning a full route. These small tests isolate wheel radius, track width, motor direction and friction. If all of them change at once, a wrong path does not tell you which model is wrong.
for case in room_cases:
world.reset(case.seed)
robot.set_pose(case.start)
result = run_controller(case.goal, timeout_s=40)
assert result.clearance_m >= case.minimum_clearance_m
assert result.reached_goal
A practical Webots or Gazebo build order
- Import or write the body and joints.
- Check gravity, mass and collision shapes.
- Command each actuator alone.
- Read each sensor and its timestamp.
- Run fixed motion tests.
- Connect ROS 2 or the project interface.
- Add the planner and scenario runner.
Save a minimal world for component tests and a separate world for missions.
Fly a mission before building the drone
A flight simulator can run the real autopilot program as software-in-the-loop. The physics model supplies IMU, GPS, barometer and other sensor data. The autopilot sends motor commands back. A ground station can connect through the same MAVLink messages used for a real vehicle.
Start with arm, takeoff, hover, land and loss-of-link tests. Next add waypoints, wind and obstacles. Keep the fast attitude controller in the flight stack. A planning or vision model should request bounded positions, velocities or trajectories rather than raw motor values.
SITL and HITL are different tests
In SITL, the autopilot program and physics run on the computer. In hardware-in-the-loop, or HITL, autopilot hardware runs its firmware while simulated sensors and vehicle motion surround it. PX4 HITL support depends on vehicle and simulator combinations, so keep it optional unless your exact setup is documented and maintained.
Turn requirements into repeatable scenarios
A demonstration answers “can it work once?” A scenario test asks a harder one. Does a stated requirement hold across starts, obstacles, weather, sensor conditions and random seeds? Each scenario needs initial conditions, events and an oracle that decides pass or fail.
Write the operational design domain, or ODD, as ranges the runner can sample. For an indoor rover that may include floor friction, aisle width, lighting, people speed and network delay. Keep a small fixed regression set and a larger sampled set.
scenario = {
"start": [1.0, 1.0, 0.0],
"floor_mu": 0.42,
"sensor_delay_ms": 120,
"obstacle_event_s": 4.5,
"seed": 7319,
}
result = run(scenario)
check(result.reached_goal and result.min_clearance_m >= 0.35)
Faster-than-real-time and headless runs
Turn off drawing and run the physics as fast as the computer allows. Parallel workers can test more seeds, but each worker must keep its own world state and random generator. Store software versions and scenario files beside the results.
Inject faults and check the safe response
A fault is a broken or degraded part. A hazard is the harmful situation it might cause. Losing a range sensor is a fault. Driving into a person is a hazard. Fault tests should check the detection, the fallback and the final safe state.
Inject faults at the same interface where they appear on hardware. Freeze a sensor value, delay packets, drop messages, reduce motor authority or corrupt a timestamp. Do not change five things at once until each single fault has a known signature.
Use failure analysis to choose tests
List each component, how it can fail, what the system observes, the possible hazard and the required response. This is the useful core of a failure modes and effects analysis. Turn high-severity rows into repeatable fault scenarios.
Fit the model to measurements
A simulator starts with estimates. Improve them with small physical experiments. Weigh the robot and measure wheel diameter under load. Time a motor step response, coast to a stop, and log sensor delay. This process is called system identification.
Fit parameters on one set of runs and check them on different runs. If the same log is used for both, a complicated model can copy its noise. Plot the residual, which is measured value minus simulated value, and look for a pattern the model still misses.
Identifiability: when two parameters look the same
A heavy robot with a strong motor can accelerate like a light robot with a weak motor. One acceleration trace may not separate mass from motor constant. Measure one directly or design another experiment that changes how the two parameters affect the result.
Randomise the parts that vary
One calibrated model represents one machine on one day. Domain randomisation samples plausible mass, friction, delay, lighting, wind and sensor error on each run. A controller that succeeds across that range is less likely to depend on one exact simulator setting.
Wider is not always better. Impossible combinations waste training and can teach timid behaviour. Use measured ranges, preserve correlations, and keep a held-out set of real runs. Randomisation is a way to cover uncertainty, not a substitute for measurement.
Correlated parameters need joint samples
Battery voltage, motor speed and available torque are related. Rain changes both camera appearance and tyre friction. Sampling each independently can create combinations that cannot happen. Use grouped scenarios or a joint model when the relationship matters.
Probability for Engineering covers joint uncertainty, Monte Carlo convergence, variance reduction and rare-event evidence.
Use synthetic sensor data carefully
A simulator can render camera, depth, segmentation and lidar data with exact labels. This is useful for rare events and viewpoints that are expensive to label by hand. It is also easy to train on clues that exist only in the renderer.
Vary geometry, materials, lighting, weather, motion blur, exposure and occlusion within measured ranges. Keep a real validation set from the target camera. Report results by condition so a good daytime score cannot hide poor performance in glare or low light.
Foundation vision and vision-language models in 2026
A pretrained vision encoder, open-vocabulary detector or vision-language model can reduce the amount of task-specific labelled data. It does not remove the need for target-camera evaluation. Start with prompting or frozen features, then consider a small adapter such as LoRA when the failure slices show a consistent domain gap. Keep geometric checks and confidence limits around any command derived from the model.
Train learned policies without hiding mistakes
Reinforcement learning learns actions from rewards. Imitation learning copies demonstrations. Diffusion policies predict action sequences, and vision-language-action models connect images and instructions to actions. All can be trained or evaluated in simulation, but each can exploit an accidental shortcut.
Give the policy only observations available on the real machine. Keep exact simulator state for the critic, scorer or teacher if the method needs it, but do not leak it into the deployed actor. Evaluate with unseen worlds, seeds and physical logs. Put a deterministic safety layer around every output.
When Isaac Lab or MJX is worth the setup
Use them when a learned controller needs many parallel physics runs. MuJoCo and MJX suit fast dynamics and batch computation. Isaac Lab adds GPU simulation, sensors and training workflows but needs stronger hardware. A small rover state machine does not need either.
Move from SIL to HIL to guarded field tests
Simulation reduces risk but does not certify the physical machine. Use an evidence ladder. Start with unit and model checks, then run production software in SIL. Test timing and drivers on hardware or HIL. After restrained bench tests, enter a small guarded operating domain.
Write release gates before running the tests. A gate has a measured condition and a required result: minimum clearance, maximum stopping distance, deadline misses, fallback latency, battery reserve and allowed interventions. A failed gate sends the project back to the earliest layer that can explain it.
What HIL adds and what it still misses
HIL can expose processor load, driver timing, bus traffic, timestamp mistakes and firmware configuration. It still uses simulated motion and sensors. Mechanical vibration, electromagnetic noise, connector faults, heat, real radio coverage and human behaviour need bench or field evidence.
A practical project record
- Model files, coordinate-frame and unit conventions, and every calibrated parameter.
- Controller, estimator and safety-monitor versions with their interface contracts.
- Fixed regression scenarios, sampled ODD ranges, seeds and result summaries.
- Fault cases, fallback traces and the reason each release gate exists.
- SIL, HIL, bench and field logs linked to the exact configuration that produced them.
Continue with a build
Use this workflow in a project rather than jumping from a lesson widget to an unrestricted machine. The Robotics course supplies the rover motion model. Drones supplies the fast flight-control loops. Autonomous Systems supplies mapping, planning, learned action models and runtime safeguards.