This section explains how the TNY-360 turns a movement request into coordinated leg and motor movements.
The locomotion system works in layers. High-level code asks the body to move, the gait planner decides how the feet should move, the kinematics engine calculates joint angles, and the joints finally send those targets to the motors.
The main objects form a hierarchy that follows the physical structure of the robot:
Body
├── Front-left Leg
│ ├── Hip roll Joint
│ ├── Hip pitch Joint
│ └── Knee pitch Joint
├── Back-left Leg
├── Back-right Leg
├── Front-right Leg
├── Left ear Joint
└── Right ear Joint
The body contains four legs and two additional joints for the ears. Each leg has three joints:
The firmware identifies the legs in this order:
A movement request is expressed at the body level. For example, a controller can ask the robot to move forwards, sideways, or rotate around its vertical axis.
The DecisionLoop receives this request and produces a control intent. The real-time locomotion pipeline then combines that intent with the current body posture, the gait planner, leg overrides, and joint overrides.
At this stage, the robot is still working with Cartesian positions: the desired position of each foot relative to the body.
The GaitPlanner turns a body velocity into a periodic movement for the four feet. It tracks a main gait phase between 0 and 1, then applies a phase offset to each leg.
Each leg alternates between two phases:
The planner uses a smooth trajectory during the swing phase. The step height controls how far the foot is lifted, while the stance depth controls how far it is pushed into the ground reference.
The main gait settings are:
| Setting | Meaning |
|---|---|
| Step frequency | Number of gait cycles per second. |
| Duty factor | Portion of the cycle spent in the stance phase. |
| Step height | Height of the foot during the swing phase. |
| Stance depth | Downward offset applied during the stance phase. |
| Leg spread | Default distance of the feet from the body center. |
The current firmware defines three gait types:
0.75, so that enough legs remain on the ground;The gait names and available options can evolve with the firmware. The current implementation does not define Jump as an active gait type.
A lower duty factor keeps the feet in the air for more of the cycle and can make the robot less stable. In particular, the Creep gait expects a duty factor of at least 0.75.
When the requested velocity is zero, the planner stops advancing the gait and returns the feet to their default positions.
The KinematicsEngine converts the desired Cartesian position of each foot into three joint angles. This is called inverse kinematics: instead of asking where the foot will be for known angles, the firmware calculates the angles required to reach a target foot position.
The calculation uses the physical geometry of the robot, including:
The engine first computes the inverse kinematics of each leg, then assembles the four results into a complete BodyJointState. If a target cannot be converted into a valid configuration, the control pipeline reports an error instead of producing a normal joint command.
BodyCartesianState
├── body position
├── body rotation
└── four target foot positions
↓
KinematicsEngine
↓
BodyJointState
├── four sets of hip/knee angles
└── ear joint angles
The ControlLoop runs on Core 1, the Reflex core, at 200 Hz. This deterministic loop is responsible for repeatedly reading the robot state, calculating the next command, and sending it to the hardware.
At each iteration, it performs the following operations:
The separate DecisionLoop runs on Core 0, the Brain core, at 30 Hz. It does not directly drive the motors. Instead, it prepares control intentions that the Reflex core consumes at the higher control frequency.
The control loop checks the timestamp of the latest intent received from the Brain. If no fresh intent has been received for 500 ms, the watchdog forces the requested body velocity to zero.
This provides a basic safety response if the Brain core becomes overloaded, stops responding, or loses the ability to update the shared control intent.
The locomotion pipeline does not only control horizontal walking. The body state also contains:
The control loop can combine these requests with stabilization feedback from the IMU. In the current implementation, a temporary roll and pitch stabilization step adjusts the body pose before inverse kinematics is calculated.
This means that the final position sent to the legs can differ from the original user request: the firmware may add a correction to help the robot remain balanced.
Each Joint stores more than a target angle. It also tracks:
The joint uses this state to apply a command through its MotorController. The firmware can also enable or disable joints and clamp their maximum angular velocity.
The estimated position is intentionally different from raw feedback: the firmware combines sensor feedback and the joint model to obtain a more useful state estimate. This is important when feedback has latency or temporary noise.
The locomotion system supports overrides at several levels:
An override can be:
This layered approach is useful for animations, direct joint control, and higher-level behaviors, while keeping the normal gait and kinematics pipeline available underneath.