Tutorial · Beginner · 22 min

The Obstacle-Avoidance Algorithm: Sense, Scan, Decide, Turn

The decision loop behind an obstacle-avoiding robot: a stop threshold, a servo scan, and a state machine that turns toward open space without getting stuck.

Published

Once a robot can read a clean distance and scan for the open direction, one piece remains: the logic that decides what to do. This is the brain of an obstacle-avoiding robot—a short loop that drives forward, notices when something is too close, looks around, and turns toward space. It is simpler than it sounds, and getting it right is mostly about not getting stuck.

Reactive, not planned

This robot has no map. It reacts to what is in front of it right now: sense, decide, act, repeat. That is reactive navigation, and it is the right first approach—cheap, robust, and enough to wander a cluttered room without hitting anything. It is not the same as path planning, where a robot uses a map to choose a route ahead of time (that is A* on an occupancy grid territory). Reactive avoidance is the foundation; planning comes later.

The stop threshold

Everything hinges on one number: how close is too close? Pick a distance at which the robot stops and reconsiders. Too small and it clips obstacles before it can react; too large and it stops at everything and creeps nervously. The right value depends on speed—a faster robot must react sooner, because it covers more ground before it can stop. For a small robot at a gentle pace, 15–25 cm is a sensible start.

The state machine

The cleanest way to express the behaviour is a finite-state machine: a few named states with clear rules for moving between them. It replaces a tangle of nested ifs with something you can read and debug. (For the general pattern, see finite-state machines for robot behavior.)

State machine diagram with four states: DRIVE (go forward), SCAN (sweep the servo), TURN (toward opening), and REVERSE (back off). Arrows show DRIVE to SCAN on 'distance below stop threshold', SCAN to TURN on 'open side found', TURN back to DRIVE on 'clear, resume', and a REVERSE branch from SCAN on 'all sides blocked' that loops back to re-scan.
Four states and the conditions between them: drive until something is close, scan, turn toward the opening, and reverse only when every direction is blocked. Download SVG
enum State { DRIVE, SCAN, TURN, REVERSE };
State state = DRIVE;
const int STOP_CM = 20;

void loop() {
  switch (state) {
    case DRIVE:
      driveForward();
      if (medianCm() < STOP_CM) { stopMotors(); state = SCAN; }
      break;

    case SCAN: {
      int a = bestAngle();            // servo sweep from the scan tutorial
      long open = distanceAt(a);
      if (open < STOP_CM)      state = REVERSE;   // nowhere to go
      else { turnToward(a); state = TURN; }
      break;
    }

    case TURN:
      if (turnComplete()) state = DRIVE;          // opening cleared, resume
      break;

    case REVERSE:
      backUp(400);                                // ms
      state = SCAN;                               // then look again
      break;
  }
}

Choosing the turn direction

The scan already did the hard part: it returns the most open bearing. Turn that way. The turnToward(angle) call maps “open to the left” to a left pivot and “open to the right” to a right pivot, using differential drive—one wheel forward, the other back, to spin roughly in place.

Avoiding oscillation and dead ends

Two failure modes trap naive robots, and both have simple fixes:

  • Flip-flopping between left and right at a corner where both look similar. Add a minimum turn duration so the robot commits to a turn instead of re-deciding every loop.
  • Wedging into a dead end where every direction is blocked. That is what the REVERSE state is for: back off, then re-scan. A small stuck-counter—reverse harder if you have scanned several times without progress—breaks the worst traps.

Tuning: speed versus reaction distance

Two knobs decide whether the robot feels smooth or panicky: driving speed and stop threshold. Raise the speed and you must raise the threshold to keep the stopping distance safe. The fastest way to find a good pair is to change them where a mistake costs nothing—the obstacle avoidance simulator—and only then transfer the values to hardware.

Explore the graph

Part of these builds

Projects and learning paths that include this tutorial.

Further reading

References