Undergraduate thesis · Dalian University of Technology · carried out at UC Irvine · Jan–May 2026

SLAM Walking Robot

Off-the-shelf navigation stacks assume wheels. This chassis walks: it has a large startup dead-zone, it lurches with every gait cycle, and its odometry is unreliable because a walking robot's feet slip on the floor. I built a full 2-D LiDAR SLAM and Nav2 stack on it, and — accounting for that slip — added a frontier rule that prices in what turning costs a walking machine, then measured how wrong the result actually was.

Localization RMSE
0.211 mon the robot · spec ≤ 0.25 m · N = 35 · no IMU
Accumulated heading change
−44%simulated ablation · 1899° → 1056°
Path length
−36%simulated ablation · 20.97 → 13.49 m

Platform

Two motor drivers, stacked

Close view of the robot's electronics deck: the LiDAR on its mast at the back, the Jetson enclosure on the left, and a stack of boards in the middle held down over the chassis plate.
The deck as built — LiDAR on its platform, Jetson at the left, and the driver stack in the middle.

Why the first board had to go

The chassis originally drove its two gearmotors through an L298N — a bipolar Darlington bridge that drops about 2.5 V across its own outputs, so on a 12 V rail the motor sees roughly 9.5 V and the rest leaves as heat, rated 2 A per channel continuous. Two 37D gearmotors driving a six-bar walking linkage — and the friction of that linkage throws up current spikes constantly — do not sit comfortably under that number. It failed in the lab on stall current.

Wiring diagram: the Jetson, a USB-to-TTL adapter and the LD19 LiDAR at the left, the Arduino UNO in the middle, two Cytron SHIELD-MD10 R2 boards to its right with yellow jumper caps marked on their PWM and DIR selector blocks, two encoder gearmotors above, a 1000 microfarad electrolytic on the first driver's power terminals, and the battery at bottom left.
The wiring as I drew it. The drawing flattens one thing: the drivers are side by side for readability, but on the robot they are stacked.

The brown-out was not a serial bug

Every time the motors accelerated or reversed under teleop the Arduino’s USB dropped, the bridge logged Serial write failed, and it fell into a reconnect loop. It reads like a driver problem and is not: motor back-EMF dumped current into the ground return, the Arduino’s ground bounced with it, its USB 5 V went out of spec, and the host concluded the device had been unplugged.

The two fixes

  • A ground lead from the Arduino’s POWER header straight to the pack negative, bypassing two stacked shield connectors
  • A 1000 µF / 35 V electrolytic across board #1’s POWER terminals, to absorb the current peaks

Phase 1

Frontier exploration

130 s of real exploration, at 3×

Real robotThe map it is building, same 130 seconds

The robot is picking its own goals — nobody is driving it. Left and right are the same 130 seconds.

Reading the map. Gray is confirmed free space, dark navy occupied, cyan and pink Nav2’s inflation layers. Green is a frontier — the boundary between known and unknown. The shape opening on the right is a corridor and a stairwell, neither in the map when the run started.

The contribution

The classic frontier rule scores a candidate on distance and information gain. On a wheeled base that is fine — spinning in place is nearly free. On a six-bar walker it is the most expensive thing you can ask for: it slips constantly, which costs a great deal of extra distance, and every slip corrupts the odometry that localization depends on.

So I added an explicit turning penalty to the utility, and ran a controlled 2×2 ablation in simulation — penalty on/off, crossed with ideal vs. walking-mechanism physics — five runs per condition.

Simulated 2×2 ablation · walking physics · 5 seeds
β = 0β = 2.5
Accumulated heading change1899°1056°
Integrated path length20.97 m13.49 m
Coverage75.8%82.4%

Cheaper and more complete at once. −44% turning and −36% path length would be worth little if the robot simply gave up early — coverage going up is what says it did not.


Phase 2

Navigation on the saved map

ROS 2 Humble · slam_toolbox · AMCL · Nav2

Real robotPlanned path and live pose

The goal was set by Prof. McCarthy, at the top-left corner of the room.

What the stack is

slam_toolbox for graph SLAM, AMCL for localization on the saved map, and Nav2 with the Smac global planner, the DWB local controller and a behavior-tree navigator — all re-tuned for a velocity envelope about a third of what the defaults expect (0.31 → 0.10 m/s, 1.9 → 0.60 rad/s), with acceleration limits cut roughly eightfold.

The hard part

Textbook differential-drive kinematics did not describe this machine. Rather than trust the nominal geometry, I measured the four scalars that reconcile the model with the prototype: 15623 ticks per meter (1.57× the geometric value), a 0.3913 m effective wheelbase, a right-encoder correction, and a 120/255 PWM dead-zone below which the robot simply does not move.


Verification

How wrong is it, in meters?

Five trial trajectories overlaid on the occupancy grid, with seven hand-measured floor marks M1 to M7 shown as white crosses and the AMCL position estimates at each.
Five runs through seven taped floor marks. White crosses are hand-measured ground truth; each colored dot is what AMCL believed at that instant.
AMCL position error · 5 trials × 7 marks
Sample pointsN = 35
Mean position error0.199 m
RMSE0.211 m
95th percentile0.311 m
Specification ≤ 0.25 msatisfied

How the 35 samples were taken

The marks are strips of tape on the floor, surveyed once. A trial teleops the robot through all seven; at each one the robot is stopped, localization_rmse.py logs what AMCL believes, and the true (x, y) is measured by hand off the tape. Five trials × seven marks = 35 paired samples.

Why no IMU

Fusing an IMU through an EKF would absorb slip and sharpen heading, and it is the obvious next step. I left it out on purpose: I wanted to know what the LiDAR scan-matcher and the calibration were worth on their own. 0.211 m is that number.


What I actually did

The walking platform is not mine — it is the McCarthy-lab build at UC Irvine of an existing six-bar design. Mine is everything that makes it navigate: the electrical integration, the 20 Hz Arduino firmware, the parameter identification, the ROS 2 and Nav2 stack, the frontier utility and its ablation, and the physical error measurement.

  • Electronics — two 70:1 gearmotors, stacked Cytron MD10 R2 drivers, an Arduino UNO trading velocity commands and encoder deltas with a Jetson Orin Nano at 20 Hz over USB-CDC, behind a 500 ms watchdog
  • Operator interface — the RViz dock on the laptop screen in the opening clip is a custom plugin: emergency stop, phase switching, saved-map loading, pose reset, global speed scale
  • Written up — submitted as the degree thesis at Dalian University of Technology