Inspiration

Legged robots are great at rough terrain until one leg gets caught on a cable, a crack, or a rock. Then the whole robot stops, and a person has to walk over and free it. We wanted a robot dog that could handle that moment on its own, which is crucial in semi-autonomous search-and-rescue. It should notice which leg is stuck, try to free it, and if that fails, drop the leg and keep going. That's where Seeker Dog came from: a quadruped with legs that snap on and off with magnets, a brain that knows when to let one go, and a means of finding survivors through bluetooth.

What it does

  • Locates nearby bluetooth devices by broadcasting an initial signal and listening for responses from passive devices (i.e. cellphones of missing people). Radial distance is estimated using RSSI (Return Signal Strength Indicator).
  • Walks and turns on four motor-driven legs. Turning uses a target angle: the robot rotates for $$t = \frac{\theta}{\omega} \; seconds, \quad where \; \omega = 45^\circ/\text{s}$$, then walks straight.
  • Finds the stuck leg. A machine-learning model watches motor current, IMU and distance-sensor data 50 times a second and gives each leg its own probability of being stuck.
  • Frees itself. It rocks the stuck leg back and forth. If the leg is still stuck after a few tries, it detaches that leg and keeps walking on the other three.
  • Stays balanced. Two legs can come off at once, but only as a diagonal pair (front-left + rear-right, or front-right + rear-left), so the robot can still stand.
  • Takes plain-English commands. "Walk forward," "turn left 90 degrees" and "is anything stuck?" go to a local Qwen model, which turns them into robot actions.

How we built it

Hardware. We designed the body in Onshape: an octagonal hub, a top deck for the electronics, four detachable leg arms, and rotating spokes ("whegs"). Disc magnets in the hub and arms hold the legs on, and each arm has a pocket for an N20 gear motor. An ESP32-C3 runs the motors and sensors.

Robot ↔ laptop. The ESP32-C3 streams sensor data over Wi-Fi as JSON over UDP at 50 Hz. The laptop sends back commands plus a heartbeat every 100 ms. If no heartbeat arrives for 300 ms, the motors shut off.

The model. The model works on half-second windows of data ($$50\text{ Hz} \times 0.5\text{ s} = 25$$ samples). For each window we compute the mean, standard deviation, min, max and change of every signal. The most useful features compare each leg with its siblings. For motor current c_i on leg i:

$$ r_i = c_i - \frac{1}{|A|}\sum_{j \in A} c_j $$

Here $A$ is the set of legs that are still attached, so a detached leg doesn't skew the average. A stuck leg's motor strains, so its current stands out even when the whole robot is working hard. A multi-label random forest (scikit-learn) outputs a separate probability $p_i$ for each leg, so it can flag two stuck legs at once.

Deciding when to act. Dropping a good leg is worse than staying stuck a moment longer. We gave the two mistakes costs $$C_{\text{false}} = 3 \; and \; C_{\text{stuck}} = 1$$. Acting is worth it when the expected cost of waiting is higher than the expected cost of acting:

$$ p \cdot C_{\text{stuck}} > (1-p) \cdot C_{\text{false}} \;\Longrightarrow\; p > \frac{C_{\text{false}}}{C_{\text{false}} + C_{\text{stuck}}} = 0.75 $$

The robot acts only after three windows in a row above 0.75. It counts the leg as freed only when p drops below 0.5. That gap (hysteresis) stops it from flip-flopping when a reading hovers near the line.

Interface. A Python dashboard shows the dog live: each leg's stuck probability, what the robot is doing, buttons, and a chat box for Qwen. Qwen runs locally through Ollama and calls tools like walk, turn, unstick_leg and detach_leg.

Challenges we faced

  • No encoders. Our N20 motors can't report their position, so the robot can't directly see that a leg stopped moving. We had to infer it from indirect signals: a stalled motor draws much more current, and the body tilts and twists toward the stuck corner.
  • The ESP32-C3's limits. It has only 6 PWM channels and one core. Normally four motors need eight PWM pins. We used one PWM pin plus one direction pin per motor: in reverse, we drive the PWM at (1-d) so the motor still gets duty d.
  • More than one stuck leg. Our first model could only name one stuck leg, and it fell apart when two jammed or a leg was already off. Switching to one prediction per leg fixed it.
  • Balance rules. Letting any two legs fall off would tip the robot over, so the diagonal-pair rule is enforced everywhere: in the firmware, the ML decision logic and the Qwen tools.
  • Networking at a hackathon. Campus Wi-Fi blocks devices from talking to each other, so we ran everything over a phone hotspot.

What we learned

  • How to frame a robotics problem as supervised learning: windowing time-series data, building features that compare legs with each other, and splitting by trial rather than by window so the scores aren't inflated.
  • That a decision rule matters as much as the model. Cost-based thresholds and hysteresis made the robot behave sensibly instead of jittering.
  • How to connect a local LLM to real hardware safely, with tool calls, heartbeats and hard limits the model can't override.
  • How tight hardware limits (pins, PWM channels, no encoders) shape the software design.

What's next

  • Train on more real-world data across different floors and snag types.
  • Add per-leg IMUs and current sensors so the robot can find the stuck leg more sharply.
  • Let the robot reattach a dropped leg on its own.
  • Supplementary Navigation and Communication capacity (Cellular capability and GPS Module; i.e. for Terrain Mapping)
  • Coordination with similar robotic devices (i.e. drones)

Built With

Share this project:

Updates

Submission history