Project Showcase

Zile Liao — robotics software, Freiburg.

Projects below are from a competition robot I develop.

The robot code is not open source: the showcase repository holds short, annotated excerpts of my own work, simplified to show how each piece works.

Vision: AprilTag localizer + field EKF

Replay of a recorded match

Open in Foxglove
Clip: 20 s of a recorded match, the localizer’s debug image beside the estimated field pose and each tag fix.Open the MP4 file · Download the replay (.mcap, 2.0 MB)

The field EKF fuses tag fixes from the localizer with the camera’s visual-inertial odometry (VIO).

The EKF predicts from the VIO odometry at about 400 Hz and corrects with each tag fix. Each fix is weighted by the covariance the localizer computed.

I wrote the EKF in Python first, then ported it to C++ to cut CPU load.

Details: state-estimation, perception-sqpnp

Replay: python state-estimation/replay/replay_field_ekf.py → a Python port of the C++ EKF tracks the recorded field pose to a median of 0.008 mm after the cold start (130 tag updates; 1 of 130 above the 95 % line of NIS, the normalized innovation squared).

Clip: screen recording of the 3D view, with the point cloud and the field’s tag markers, beside the camera image with the localizer’s detections.Open the MP4 file · Download the replay (.mcap, 13.9 MB) · Download the point-cloud replay (.mcap, 22.5 MB)

The AprilTag localizer turns a camera image into the camera’s pose on the field, plus a 6x6 covariance.

With two or more tags in view, all corners are pooled. If the geometry is not observable, the pose is withheld instead of inventing a covariance.

The point cloud is the camera driver’s own output; the localizer started from a teammate’s port, and its pooled multi-tag solve and covariance are mine.

Details: perception-sqpnp

Replay: python perception-sqpnp/replay/replay_localizer.py → re-solving 178 pooled frames from the logged corners, which the node rounded to whole pixels, lands within a median 14.1 mm of the recorded pose; from unrounded corners reprojected from each tag’s logged pose, 0.48 mm.

Foxglove buttons open the clip in a browser viewer.

Shoot on the move

Clip: the competition robot shooting while it drives.Open the MP4 file

A turret that keeps aiming while the robot drives, with shot compensation for the robot’s velocity.

A ball fired from a moving robot keeps the robot’s velocity. The compensation looks ahead and splits the velocity into the part toward the target and the part across it.

I wrote the turret’s aiming cascade and its shot compensation, with contributions from teammates.

Details: control/turret-2026

Replay: python control/turret-2026/replay/replay_shot_solution.py → the turret loop’s aim error and feedforward recompute from the 30 s log to within 0.0010° and 0.0005 V; tracking RMS 0.90° (in this clip the turret held a fixed field heading and shot compensation was off; the compensation law is shown as a counterfactual).

Whole-body control

Whole-body arm control

Open in Foxglove
Clip: the robot driving to its staging pose, then the arm reaching its goal.Open the MP4 file · Download the replay (.mcap, 0.8 MB)

A solver on the coprocessor decides how the whole robot moves.

A phase state machine runs DRIVE, APPROACH, TASK and RETRACT. On entering TASK, the goal is converted into the solver’s frame and frozen, so it stays at one field point.

The goal freeze and the QP moving the chassis were simulation-only.

Details: control/wholebody-2026

Reaching a field-fixed goal from AprilTag localization

Clip: the arm following an AprilTag held at the end of a stick.Open the MP4 file

AprilTag fixes tell the robot where it stands, so the arm’s goal can be fixed on the field.

The arm’s goals are poses fixed on the field, while the whole-body solver works in the robot’s own frame. Before TASK, APPROACH requires the field pose to be fresh.

This demo mode is not excerpted in the showcase repository.

Details: control/wholebody-2026, perception-sqpnp, state-estimation

Auto-tuning

Clip: the auto-tuning routine moving the robot’s arm.Open the MP4 file

A PID tuning bench for an arm joint, steered by a coding agent inside hard limits.

The agent decides which gain to sweep next, over what range, and when to stop. The deterministic sweep stays in code that enforces the limits.

I wrote a ROS 2 node that runs the experiments, and the procedure a coding agent (Claude Code) follows.

Details: llm-tuning-agent