← Back to work
Autonomous Lawn Mower

Autonomous Lawn Mower

Personal robotics project: a fully custom autonomous mowing stack for a differential-drive robot with Livox LiDAR, running onboard on Linux with ROS 2 Jazzy. The goal was reliable coverage of an irregular lawn perimeter including plants along the edge without leaning on Nav2’s generic navigation servers. I designed a layered pipeline: LiDAR localization, 2.5D global costmap fusion, boustrophedon coverage planning, and a C++ path follower with its own state machine (mowing stripes, orthogonal turns, transit connectors, and local obstacle handling). An Android app over Bluetooth drives mission start, pause/resume, zone selection, and live map view. Field runs are logged to CSV telemetry so every stall, ghost obstacle, and corner trim can be traced back to the code.

Role

Software Engineering, Embedded Systems, ROS 2, Mobile (Android)

Sector

Robotics & Autonomous Systems

Year

2025-2026

Standard ROS navigation failed on the real lawn. Stripes drifted, corners were messy, and the robot kept replanning around grass, plants, and fence clutter. Nav2 is built to reach a goal, not to mow a full garden in 17 cm zig-zags.

I rebuilt the stack around coverage. A planner breaks the lawn into ordered segments, mow, turn, transit, perimeter with tight 90° corners instead of wide arcs. A C++ follower executes them at 50 Hz with straight-line tracking, pivot assist on turns, and safe transit to the first stripe.

Perception is tuned for mower height: tall grass is filtered out, real obstacles are fused into a live costmap. At plants along the edge, the path trims in close and cuts a sharp corner instead of detouring around every bush.

Real missions exposed problems no lab test catches: phantom obstacles from grass speckle, pointless detours that left the mower braking for half a minute, deadlocks during first-stripe alignment, and blade control that had to match what the robot was actually doing, not what it planned to do next.

Each issue was traced and fixed from field data, not guesswork. Spin direction latched on entry. Escape routes only triggered when the mower was truly stuck. Ground filtering was widened so grass stays grass. Blade stop logic tied to segment type, so cutting only pauses on real transit, not mid-stripe.

Motion runs end-to-end: navigation commands down to closed-loop wheel control with SimpleFOC, plus serial drivers for the blade and drive motors, so path following and physical motion stay in sync on uneven grass.

Stack: ROS 2 Jazzy · C++ path follower · Python coverage planner · Livox + NDT · SimpleFOC motor control · Kotlin/Compose Android app · Foxglove sim (real stack, dummy mower)

More projects

Open to new opportunities

Get in touch

I'm always open to hearing from new people about their ideas, projects, or potential collaborations.