Hello and welcome to another Burf Update. July was a month of the robots telling me I was wrong.
Six bugs found by watching a robot move, one found by listening to it not move — and every single
one of them had passed a test first.
InMoov — a real ROS2 driver
After months of “nothing to report”, the InMoov finally got the attention it deserved. It now has a
proper ROS2 interface: a ros2_control hardware driver in C++ talking to MyRobotLab over the
network. Drag a slider in RViz and the real robot’s head turns.
The interesting part wasn’t the plumbing; it was the mapping. ROS2 thinks in radians, with a joint at
zero when the robot is at rest. The servos think in degrees, 0–180, with a calibrated rest position —
and on a hand-built robot those rest positions are nothing like symmetrical. On mine the left
shoulder rests at 35° and the right at 62°. So the driver reads every servo’s real minimum, maximum
and rest live from the robot at startup. A static table would have been wrong on day one.
Then I started dragging sliders and found six joints moving the wrong way in a single session. The
head panned backwards. The shoulders moved in opposite directions to each other. The elbows
bent backwards in the simulator while the real arm bent correctly — which is the nasty one, because
the robot looks right and you only catch it by watching the 3D model instead of the machine.
Each fix was one line. Finding them was the work, and the only tool that found them was a person
looking at a robot.
Driving the InMoov from a VR headset
The other half of the month: a Meta Quest app that teleoperates it. Put the headset on, move your
arms, and the robot copies you — head, shoulders, biceps, rotation.
The rest-position problem came back harder, because a human shoulder and an InMoov shoulder
share neither a range nor a zero. I enabled the joints one group at a time, because a wrong sign on a
slider is a puzzle and a wrong sign on a life-size arm is a repair.
Two details worth keeping. The head needed an auto-neutral on engage — whatever pose your
head is in when you connect becomes zero, or you inherit a permanent bias and fight it all session.
And there’s a voice recentre command, because you can’t reach a keyboard wearing a headset with
your arms in the air.
Best bug of the lot: the code reading each servo’s limits treated a limit of 0.0 as “not set”. Zero is a
perfectly ordinary minimum. Every servo whose travel started at zero was silently getting a default
instead of the truth.
Sanbot — a real LiDAR, and a brake I couldn’t switch off
The Sanbot’s ROS2 side got honest this month. A real LDS-006 LiDAR over USB drives /scan ,
replacing the depth-camera hack it had been faking scans with. Closed-loop pose, IMU heading at
source, and stepped turning that SLAM can actually follow. Watching a nine-year-old service robot
build a map of my hallway was the most satisfying thing I did all month.
Then one long, doomed campaign. The Sanbot has a firmware proximity brake that stops it near
obstacles — useful, until ROS2 is doing the navigating and the robot halts a metre short of a
waypoint for reasons the planner knows nothing about. I found the switch that disables obstacle
avoidance. I re-asserted it at every startup. I sent an undocumented MCU command that looked
exactly like the one that would hide the front sensors.
It cannot be disabled. The side sensors, yes. The front brake, no — not from software, at any level I
can reach. So I deleted every lever I’d built for it and wrote down that it’s impossible, which is worth
more than the code was.
(All of this ran through a bridge — a Python node on a Linux box relaying between ROS2 and the
robot. That’s since been replaced, but that’s an August story.)
TurtleBot2 — a proper LiDAR too
The Kobuki got the same treatment. It had been limping along on a depth-camera scan and an
unreliable vendor SDK; it now has a real Okdo LD06 LiDAR publishing /scan through a custom
node I wrote against the raw FTDI serial stream. Depth-scan is demoted to a legacy opt-in. Both
robots pinned to /dev/serial/by-id paths, because device numbering changes the moment you
plug something else in.
Burf Platform — waypoints that actually arrive
The Platform’s goto now drives room-to-room rather than just across open floor. Three fixes made
the difference: denoising the occupancy grid before inflating it, treating deep unknown space
differently from the thin rind around walls, and making the stall detector rotation-aware so a robot
turning on the spot isn’t mistaken for a stuck one.
The inflation padding came down from 0.22 to 0.15 as well. Waypoints near furniture were stopping
about a metre short — the goal was being nudged out to the inflation boundary, then the 0.30
accept radius stacked on top of that. Two reasonable numbers making one unreasonable one.
Plan for 2026 — honest scorecard
- Strengthen Burf Robotics — steady. Consultancy delivering.
- Launch Burf Platform as MVP — goto is genuinely usable now. Still no price and no first
customer, which is the real bottleneck. - Continue learning ROS2 — best month yet. A ros2_control driver from scratch, two
custom LiDAR nodes, and SLAM on a robot nobody expected to run it. - InMoov Robots — finally, properly, yes. Driver working, VR teleop working. (Big progress)
- Continue Brilliant learning — ongoing.
- Build my own robot product — paused
What’s next
Finish confirming the remaining joint directions on the InMoov, and finally record a video of the
humanoid being teleoperated from a VR headset. That’s worked since the end of July and there’s
still no footage of it — which, given it’s the best-looking thing in the workshop, is its own kind of
bug.




















