Motion and how it works in the NUbots codebase.
Ysobel Sims GitHub avatar
Updated 4 Oct 2023

This page details motion modules within the NUbots main codebase, such as the walk engine and the script engine. Information about modules for running and tuning scripts can be found on the Behaviour page.


Actuation is the process of moving the robot's joints. The robot has 20 joints, each with a servo motor. The actuation layer is implemented within the Director system. A Provider for each servo and each limb exists so that only one higher level Provider can take control of a particular servo or limb at a time. If the walk has control of the leg, the kick cannot also take control of the leg. If the kick has a higher priority than the walk, the walk will lose control of the leg and the kick will take control.

SVG diagram of a graph generated from DOT notationdigraph actuation { rankdir=LR "Left Leg IK" -> "Left Leg" -> {"Left Hip Yaw", "Left Hip Roll", "Left Hip Pitch", "Left Knee", "Left Ankle Pitch", "Left Ankle Roll"} "Right Leg IK" -> "Right Leg" -> {"Right Hip Yaw", "Right Hip Roll", "Right Hip Pitch", "Right Knee", "Right Ankle Pitch", "Right Ankle Roll"} "Head IK" -> "Head" -> {"Head Yaw", "Head Pitch"} }Left Leg IKLeft LegLeft Hip YawLeft Hip RollLeft Hip PitchLeft KneeLeft Ankle PitchLeft Ankle RollRight Leg IKRight LegRight Hip YawRight Hip RollRight Hip PitchRight KneeRight Ankle PitchRight Ankle RollHead IKHeadHead YawHead Pitch
Actuation layer. The first level are the Inverse Kinematics Providers, the second level are the Group/Limb Providers, and the third level are the Servo Providers.

The Groups level also includes the Body, Limbs, Legs and Arms Groups. These are more commonly used in the system in the context of Sequences with Scripts.

Sequences contain a list of Group commands that are to be executed sequentially. Once a Director Done is received from every servo in the group, then the frame is completed and the next set of commands in the sequence are requested. This concept is the driving force behind the script system.

Walk Engine

NUbots use an open loop walk based on quintic splines. This walk engine takes care of the mathematics and control involved in taking steps without falling over. The walk engine does not plan where to walk, only how to walk.

The walk engine will trigger when a Walk message is emitted in the Director system. The walk command gives a vector [x, y, z] which represents:

xvelocity in metres per second in the direction of the x axis
yvelocity in metres per second in the direction of the y axis
zyaw in radians per second, positive is counter-clockwise. The 0 point is straight forward.

The robot's behaviour determines the walk vector.

Quintic Spline Walk

The Quintic Walk is an open loop controller based on quintic splines (piecewise fifth degree polynomials). It sets points in each direction for rotation and translation and uses those points to create smooth quintic splines.

The engine has support for kicking using quintic splines. Integration of the kick is a work in progress.

The code used for this walk comes from the RoboCup team Hamburg Bit-Bots, which in turn is from Quentin "Leph" Rouxel and Team Rhoban's walk.


The walk uses the Footstep class to generate the targets for the foot, using the calculated splines.

The SplineContainer class holds multiple Spline objects. As the SplineContainer gets points, they are used to create Splines. These Spline objects are each mapped to names based on what they do. These mappings for the walk and kick are in the table below.

The splines that the SplineContainer holds are instances of a generic Spline class that holds all the information for a mathematical spline. Each piecewise polynomial in the spline is a Polynom object that contains the coefficients for a polynomial.

The specific Spline type we use is a SmoothSpline, extended from the Spline class. Find out more about splines and this specific type of spline on the mathematics page.

The TrajectoryUtils file uses the SplineContainer for walking and kicking. It creates a SplineContainer with the following splines:

IS_DOUBLE_SUPPORTSplines for when the robot is in double support phase, i.e. both feet are on the ground.
IS_LEFT_SUPPORT_FOOTSplines for the support foot.
TRUNK_POS_XThe Cartesian position of the robot's torso in the x-axis.
TRUNK_POS_YThe Cartesian position of the robot's torso in the y-axis.
TRUNK_POS_ZThe Cartesian position of the robot's torso in the z-axis.
TRUNK_AXIS_XThe orientation of the robot's torso in the x-axis.
TRUNK_AXIS_YThe orientation of the robot's torso in the y-axis.
TRUNK_AXIS_ZThe orientation of the robot's torso in the z-axis.
FOOT_POS_XThe Cartesian position of the robot's flying foot in the x-axis.
FOOT_POS_YThe Cartesian position of the robot's flying foot in the y-axis.
FOOT_POS_ZThe Cartesian position of the robot's flying foot in the z-axis.
FOOT_AXIS_XThe orientation of the robot's flying foot in the x-axis.
FOOT_AXIS_YThe orientation of the robot's flying foot in the y-axis.
FOOT_AXIS_ZThe orientation of the robot's flying foot in the z-axis.

The points that make up all these splines are in the WalkEngine.cpp file. The configuration parameters affect some of these points. Values are all in SI units.

Improved Quintic Spline Walk

We currently use a modified version of the original quintic walk. The new version is highly simplified and uses different logic for the timing and placement of the torso and feet. It uses the FootController module to align the feet with the ground.

SVG diagram of a graph generated from DOT notationdigraph walk { "Path Planner" -> "Walk" -> "Foot Controller" -> {"Left IK", "Right IK"} "Servos..." [style=dashed] "Left IK" -> "Left Leg" -> "Servos..." "Right IK" -> "Right Leg" -> "Servos..." }Path PlannerWalkFoot ControllerLeft IKRight IKLeft LegRight LegServos...
The walk pipeline

Kick Engine

The kick engine is based off the improved quintic spline walk engine. Splines are created for the torso and kicking foot movements based on configuration values. It is open loop and has similarities to a scripted kick, with a simplified tuning process and spline interpolation rather than linear interpolation.


Scripts are static motions for the robot. They specify what joint angles to move to and how long the robot should take to get to those joint angles. For example, standing up is a script telling the robot to move its joints to the stand position over one second. There can be many of these position specifications in sequence to make the robot do short movements that may be hard to dynamically implement, such as getting up.

To learn how to tune scripts, see the ScriptTuner guide.


To execute a script, we emit a Director Task message with the appropriate servo Sequence containing the script information. This script information comes from the load_script function in the script utility.

The load_script function takes a YAML file name (eg Stand.yaml), finds and reads the file and creates a servo Sequence representing the script. The Sequence is returned and emitted as a Director Task. The Director Task is then executed by the Director system.


Scripts can be given a start time. If a script has a start time, it will not start execution until that time. The following would execute the Stand script in five seconds.

emit<Task>(load_script<BodySequence>("Stand.yaml", NUClear::clock::now() + std::chrono::seconds(5)));

Script files

The script files are YAML files specifying a duration and list of servo targets, in a format like the following:

- duration: 1000
- id: HEAD_YAW
position: 0
gain: 10
torque: 100
position: 0.5
gain: 10
torque: 100
- id: R_HIP_YAW
position: -0.03
gain: 5
torque: 100

The fields are described in the table below.

durationAn integer in milliseconds.
positionA float representing the angle of the servo in radians.
gainA float representing how much effort the servo will use to get to the target position. Gain is often between 5 and 15.
torqueA float, where 0 represents no torque and 100 represents torque being on. Torque is 100 unless you want that servo relaxed, in which case it will be 0.
idOne of the servo IDs listed in ServoID.h.

Script files can be found in the ScriptEngine module. Scripts can be specific to a robot. More on scripts can be found on the Configuration and Script System page.

NUbots acknowledges the traditional custodians of the lands within our footprint areas: Awabakal, Darkinjung, Biripai, Worimi, Wonnarua, and Eora Nations. We acknowledge that our laboratory is situated on unceded Pambalong land. We pay respect to the wisdom of our Elders past and present.
Copyright © 2023 NUbots - CC-BY-4.0
Deploys by Netlify