Principles of Robot Autonomy I · Lesson 1 of 15 · Stanford AA274A

How a Robot Sees, Thinks, and Acts

From a remote-controlled toy to a self-driving car: the four-module autonomy stack and the loop that ties it together. This is the map for the entire series.

Prerequisites: Basic vectors + a little Python. That's it.
10
Chapters
6
Simulations
0
Assumed Knowledge

Chapter 0: Automation Isn't Autonomy

A factory welding arm is a marvel. It repeats the same weld, to the same millimeter, ten thousand times a shift, for years. But move the car body two centimeters to the left and the arm welds the air. It has no idea anything changed. It is running a fixed script — a sequence of joint angles recorded once and replayed forever.

Now picture a Waymo at a four-way stop. A cyclist edges into the intersection. A pedestrian hesitates on the curb. A delivery van double-parks ahead. No two seconds of that scene have ever happened before, and no script could enumerate them. Yet the car decides — yields, creeps, reroutes — and keeps deciding, ten times a second, forever.

That is the gap this whole course is about. The welding arm is automated: it executes a pre-planned motion open-loop. The Waymo is autonomous: it senses a world it didn't script, builds an understanding of it, decides what to do, and acts — then senses again to see what its action did. That last clause is the whole secret. Autonomy is a closed loop.

The one-sentence definition. Automation replays a fixed sequence open-loop; autonomy closes the loop — it senses, decides, and adapts, continuously, in a world it did not pre-script. Everything in this series is a piece of that loop.

Stanford's AA274A calls this loop the see-think-act cycle, and it organizes the entire field into four jobs a robot must do over and over: perceive the world, figure out where it is, plan and control motion, and coordinate all of that into coherent behavior. Those four jobs are the autonomy stack, and the 15 lessons in this series are a guided tour of each layer.

Before we name the parts, let's watch the loop itself turn — because once you see it, you can never un-see it inside any robot.

Open Loop vs. Closed Loop

A robot must reach the green goal. The world drifts (wind, slippage) every step. Toggle the loop and press Run. Open-loop replays a fixed plan and blindly drifts off; closed-loop re-senses each step and corrects.

ready

Open-loop, the robot commits to a plan and executes it with its eyes shut; the smallest disturbance compounds, step after step, and it arrives nowhere near the goal. Closed-loop, it looks at where it actually ended up after every step and recomputes — disturbances get corrected before they accumulate. Same actuators, same goal. The difference is the loop.

Automation
record a fixed script → replay open-loop → repeat identically
vs
Autonomy
sense → decide → act → sense again → adapt
What makes a Waymo autonomous rather than merely automated?

Chapter 1: SeeThinkAct — The Cycle That Never Stops

Every autonomous robot runs the same loop, forever, dozens of times a second. It is worth burning into memory because every algorithm you will ever meet in robotics lives at one specific point on this loop.

The loop has three beats — See, Think, Act — wrapped around the real world:

The data changes type as it flows. This is the single most important thing to notice. Raw pixels become extracted features, which become a world model, which becomes a trajectory, which becomes actuator commands. Each arrow in the loop carries a different kind of data. Learning robotics is learning each of these transformations.

Stanford draws this exactly — the "see-think-act" cycle from Lecture 1. Let's make it turn, and watch the data morph as a packet rides around the ring.

The See-Think-Act Loop (live)

Press Run to let a data packet ride the loop. Watch its label change at every edge — that label is the kind of data being passed. The robot in the center nudges forward each full cycle, because acting changed the world.

Speed 1.2x

Notice that nothing waits for anything. The loop never "finishes." There is no end state where the robot is done thinking and starts acting — it is always doing all three, with fresh data, because the world never stops changing. A robot that pauses to think while moving at 30 mph is a robot that has already crashed.

Where does each lesson live on this loop?

Here is the payoff of memorizing the loop: it is a coat-rack for the entire field.

Loop beatData in → outLessons in this series
See / extractpixels, LiDAR → features, detections7–10 (sensors, cameras, SfM, learned perception)
Think / localizefeatures + motion → pose, map11–14 (SLAM, Kalman/EKF, particle filters)
Think / planmap + goal → trajectory3–5 (A*, RRT, trajectory optimization)
Act / controltrajectory → actuator commands2, 6 (kinematics, PID/LQR control)
Coordinateeverything → coherent behavior1, 15 (this lesson; advanced behavior)
In the see-think-act cycle, what kind of data leaves the Think stage and enters Act?

Chapter 2: The Autonomy Stack — Four Modules

"See-think-act" is the rhythm. The autonomy stack is the machinery that produces it. Stanford splits the work into four modules of roughly equal weight — and this series devotes its lessons to each in turn.

1. Perception. Turns raw sensor streams into meaning. In: camera images (a tensor of shape height × width × 3), LiDAR point clouds (sets of 3D points), depth maps. Out: features, detections ("stop sign at pixel 412,88"), segmented regions, extracted lines and corners.

2. Localization & SLAM. Answers "where am I, and what does the world look like?" In: the perception module's features plus the robot's own motion estimate. Out: the robot's pose (position + orientation) and a map.

3. Motion Planning & Control. Decides how to move and makes it happen. Planning: map + goal → a collision-free trajectory. Control: trajectory + current pose → actuator commands that track it despite disturbances.

4. Executive & System Architecture. The conductor. It decides which behavior is active right now (explore? approach? stop? recover?), sequences the other three modules, and handles failures gracefully. Often built as a finite state machine — the subject of the back half of this lesson.

Why "stack"? Because data flows up and decisions flow down, like a software stack. Sensors feed Perception; Perception feeds Localization; the shared world model feeds Planning; Planning feeds Control; Control drives actuators. The Executive sits beside all four, switching what they're doing. Get the interfaces between layers right and you can swap any single module without rewriting the others.

The interfaces — the type of data on each arrow — are the contract that makes a robot buildable by a team. Click each module below to see exactly what it consumes and produces, and which lessons cover it.

The Autonomy Stack — click a module

Tap any band to expand its input/output contract and the lessons that build it. This same four-band diagram reappears at the top of every lesson in the series, with the relevant band lit up — it's your "you are here."

Showing all four modules + the executive frame.

That outer teal frame is the Executive. Notice it touches everything — it doesn't sit in the data flow, it sits around it, deciding which mode each module runs in. We'll formalize the Executive as a finite state machine in Chapter 5. First, two prerequisites every layer assumes: what "state" means (Chapter 3), and how a robot represents the world as a map (Chapter 4).

Localization & SLAM consumes the output of which module, and produces what?

Chapter 3: What Is "State"? — Configuration & Pose

Every module on the stack passes around one quantity above all others: the robot's state. Before we can plan, localize, or control, we have to agree on what numbers describe "where the robot is and how it's oriented." Those numbers are the robot's configuration.

Stanford's Lecture 1 defines it precisely. The generalized coordinates of a robot are the smallest set of numbers that completely specify its configuration. We collect them in a vector written ξ (the Greek letter xi):

ξ = [ξ1, ξ2, …, ξn] ∈ ℝn

Here n is the number of generalized coordinates, n means "an ordered list of n real numbers," and the small (transpose) just means we treat it as a column. For a wheeled robot rolling on a flat floor, three numbers are enough:

ξ = [x, y, θ]

where (x, y) is the position of the robot on the floor and θ (theta) is its heading — the direction it faces, measured as an angle. The pair (position + orientation) has a special name: the robot's pose. A robot that knows its pose knows everything it needs to know about where it is.

Why three numbers, not two? A point on a map needs only (x, y). A robot needs θ too, because a robot can face different directions while standing in the same spot — and, crucially, a wheeled robot can usually only move in the direction it faces. Orientation is part of state because it constrains motion.

Let's make the pose vector concrete. Drag the robot to set (x, y); rotate it to set θ. The readout shows the live configuration vector and the robot's heading vector — the unit vector pointing where it faces:

ev = [cosθ, sinθ]
Pose & Heading

Drag the robot to move it; use the slider to rotate. Toggle the no-slip constraint to see the direction a wheeled robot cannot move (sideways) — a one-line preview of Lesson 2's kinematics.

θ 35°

With the constraint on, try to drag the robot sideways to its heading — it resists, sliding only along the barred line's perpendicular. That is the no-slip constraint: a rolling wheel cannot translate along its axle. Written as an equation, the sideways velocity must be zero:

a(ξ, ξ̇) = ẋ sinθ − ẏ cosθ = 0

Here ξ̇ (xi-dot) means "the rate of change of ξ" — the velocity. Don't worry about deriving this; Lesson 2 builds it from scratch and shows how it produces the famous unicycle and differential-drive models. The point for now: state is three numbers, and the robot's geometry restricts how those numbers can change. That restriction is what makes robot motion planning interesting rather than trivial.

Common confusion. "Configuration," "generalized coordinates," "state," and "pose" are used almost interchangeably for a simple wheeled robot — all of them are (x, y, θ). They diverge for complex robots: a 7-joint arm's configuration is 7 joint angles; a drone's pose lives in 3D with 6 numbers. Always ask: what is the smallest set of numbers that pins this robot down?
For a wheeled robot, why is the configuration written ξ = (x, y, θ) rather than just (x, y)?

Chapter 4: How a Robot Sees the World — Map Representations

A robot that knows its pose still needs to know what's around it: where the walls are, which rooms connect, where the kitchen is. That knowledge is a map. But "map" is not one thing — the same physical environment can be stored four very different ways, each good at a different job. Choosing the wrong representation makes a problem hard that the right one makes trivial.

Here is one apartment, rendered four ways. Flip between them and notice they describe the same world through different lenses:

Map-Type Explorer — one world, four lenses

Switch representations. Press plan path to ask each map for a route to the goal — watch which maps can answer and which can't. For the occupancy grid, the resolution slider trades memory for precision.

Cells 16
Occupancy grid: each cell stores P(occupied).

Occupancy grid (metric). Chop the world into a grid of cells; each cell stores the probability it is occupied — free, occupied, or unknown. Great for precise collision-checking and path planning. Costly in memory (cells grow with area / resolution²). This is the workhorse — Lesson 12 builds it in full.

Topological (graph). Forget metric detail; store places as nodes and connections as edges ("kitchen connects to hallway connects to bedroom"). Tiny memory, instant high-level routing ("3 rooms away"), but no notion of exact distance or shape.

Feature / landmark. Store only a sparse set of distinctive points — corners, blobs — each as a coordinate plus a descriptor that lets you recognize it again. This is what visual SLAM (Lesson 11) and structure-from-motion (Lesson 9) actually keep. Compact, perfect for re-localizing, useless for "is this exact spot free?"

Semantic. Label regions by meaning: "wall," "door," "kitchen," "person." This is what learned perception (Lesson 10) produces. Lets a robot reason about what things are ("don't drive through the person"), not just where mass is.

Worked example: updating one occupancy cell by hand

How does a single grid cell decide it's occupied? Not all at once — it accumulates evidence across measurements. The trick (full story in Lesson 12) is to track belief in log-odds ℓ, because then each new measurement just adds a number instead of multiplying probabilities:

ℓ = log( P(occupied) / P(free) ),    P = 1 / (1 + e−ℓ)

Start at total ignorance: P = 0.5, so ℓ0 = log(0.5/0.5) = 0. A LiDAR "hit" on this cell contributes ℓhit = +0.85; a "miss" (beam passed through) contributes ℓmiss = −0.4. Watch evidence pile up:

StepMeasurementℓ (running sum)P(occupied) = 1/(1+e−ℓ)
0prior (no data)0.000.50
1hit (+0.85)0.850.70
2hit (+0.85)1.700.85
3miss (−0.40)1.300.79

Two hits push the cell to 85% sure it's occupied; one stray miss nudges it back to 79%. The belief is robust to single bad readings because evidence accumulates. That is why we store probabilities, not booleans — sensors are noisy, and a probability lets a cell remember how sure it is. (We add in log-odds because logarithms turn Bayes' multiplication into addition — the same trick reappears in every filter in Lessons 13–14.)

You need turn-by-turn directions between rooms using as little memory as possible, with no need for exact distances. Which map representation fits best?

Chapter 5: The Executive — Finite State Machines

We have Perception, Localization, and Planning–Control. What decides which of these the robot should be doing right now? When a TurtleBot bumps a wall, who says "stop driving forward, start backing up"? That is the job of the Executive, and the oldest, clearest tool for the job is the Finite State Machine (FSM).

Definition (Lecture 19). A finite state machine is a computational model for systems whose output depends on the entire history of their inputs — compressed into a single "state." It is a modeling framework, not an algorithm (like a probability density or a factor graph). It tells you how to describe a behavior, then you implement it however you like.

An FSM is defined by a small, fixed set of pieces. Every symbol here matters, so we define each before using it:

That's the whole model: (S, I, O, n, o, s0). Each tick the executive reads an input, applies n and o, emits a command, and updates its state. Written as a loop, it's almost embarrassingly simple:

read input i
from sensors / clock
o = o(i, s)
command the output
s ← n(i, s)
update the state
↻ at a fixed rate

We draw FSMs as graphs: a circle for each state, an arrow for each transition. We label each arrow with the input that triggers it and the output it produces, written input / output. The current state glows; when an input fires a transition, that arrow flashes and the glow jumps. That picture is the next-state function n and the output function o, drawn.

This is exactly how your TurtleBot's navigator.py works, and how production drone autopilots like PX4 are structured. In ROS, the SMACH library builds these for you, with visualization. But you don't need a library — a class with a state variable and an if/elif block per state is a complete FSM. We'll build one by hand next chapter.

Concept → realization. The FSM is the executive's brain: it never moves a motor itself. It decides which mode the rest of the stack runs in — "in EXPLORE, let the planner roam; in APPROACH, lock onto the goal; in STOP, command zero velocity." The modules do the work; the FSM chooses the work. Keep that separation and your robot's behavior stays debuggable.
An FSM's next state depends on what?

Chapter 6: The Parking Gate — An FSM by Hand

Stanford's canonical FSM example is a parking-gate arm — small enough to trace by hand, real enough to matter. Let's specify it completely, then trace a car through it, then run it live, then build it in code.

The problem. A gate arm guards a parking lot. It can be in four states. A sensor reports whether a car is waiting; another reports whether a car just passed; position sensors report whether the arm is fully up or fully down. The arm can raise, lower, or hold (nop). Desired behavior: when a car arrives, raise the arm; keep it up until the car drives through; then lower it.

States S: down, raising, up, lowering.

Inputs I: car waiting, no car, gate at top, not at top, car passed, gate at bottom.

Outputs O: raise, lower, hold.

Initial state s0: down.

The transition table (the FSM, written out)

This table is the next-state function n and output function o. Each row is one tick: given the state and input, here is the commanded output and the next state.

TickState stInput itOutput o(i,s)Next state n(i,s)
0downno carholddown
1downcar waitingraiseraising
2raisingnot at topraiseraising
3raisinggate at topholdup
4upcar not passedholdup
5upcar passedlowerlowering
6loweringnot at bottomlowerlowering
7loweringgate at bottomholddown

Trace it in words. We start down, holding (tick 0). A car arrives — tick 1 fires n(car waiting, down) = raising and commands raise. The arm rises (ticks 2–3) until the top sensor trips, landing in up. It waits, holding, until the car passes — tick 5 fires n(car passed, up) = lowering and commands lower. The arm descends (6–7) and returns to down. One clean cycle. Notice that raise and lower each fire exactly once.

Now press the sensor buttons yourself and watch the arm move and the graph light up. Try the fault inject toggle — a stuck sensor — to see the FSM hang in a state, which motivates the robustness ideas in Chapter 7.

Parking-Gate FSM (live)

Left: the physical gate. Right: the FSM graph (current state glows). Fire sensor inputs, or press Auto-run to play a full car-through cycle. The trace log records every (state, input → next, output).

state=down (initial)

Building it in code

The FSM is a class with a state variable and one if/elif block per state — the textbook OOP pattern. Verbose first, with every branch matching a table row:

python
class ParkingGateFSM:
    def __init__(self):
        self.state = 'down'          # s0: the initial state

    def step(self, car, gate):
        # one tick: read inputs (car, gate sensors) -> (output, next state)
        out = 'hold'               # default output: do nothing
        if self.state == 'down':
            if car == 'waiting':
                out, self.state = 'raise', 'raising'
        elif self.state == 'raising':
            out = 'raise'
            if gate == 'top':
                out, self.state = 'hold', 'up'
        elif self.state == 'up':
            if car == 'passed':
                out, self.state = 'lower', 'lowering'
        elif self.state == 'lowering':
            out = 'lower'
            if gate == 'bottom':
                out, self.state = 'hold', 'down'
        return out

The compact, table-driven form scales better — the transitions live in a dictionary, so adding a state is data, not code:

python
# (state, input) -> (output, next_state); missing key = hold + stay
TABLE = {
    ('down',    'waiting'): ('raise', 'raising'),
    ('raising', 'top'):     ('hold',  'up'),
    ('up',      'passed'):  ('lower', 'lowering'),
    ('lowering','bottom'):  ('hold',  'down'),
}
def step(state, sym):
    out, nxt = TABLE.get((state, sym), ('hold', state))
    return out, nxt

In the Code Lab below, you'll implement the step method and run a scripted car through the gate, animating the arm as the FSM commands it — and your trace must match the table above. This is the executive layer, in 15 lines.

The gate is in state up and the sensor reports car not passed. What output and next state?

Chapter 7: Taming Complexity — Reduction, Hierarchy, Composition

The parking gate had four states. A real self-driving stack has hundreds — and adding one state can spawn an exponential number of transitions. Stanford warns that designing these "extremely complex state machines... is still one of the most time-consuming, difficult tasks faced by companies." Three tools keep FSMs tractable.

1. State reduction

Two states are equivalent if (a) they produce the same output, and (b) for every input they transition to the same-or-equivalent states. Equivalent states can be merged with no change in behavior. There's a polynomial-time algorithm: put all states in one set, partition by output behavior, then repeatedly split subsets whose members disagree on where they transition, until nothing splits further. A classic sequence-detector for "010 or 110" collapses from 7 states to 4 this way — same behavior, fewer boxes.

Why it matters. Fewer states means fewer transitions to get right, fewer bugs, and a diagram a human can actually read. Reduction is the FSM equivalent of refactoring duplicate code.

2. Hierarchy (super-states)

Even when states aren't equivalent, closely related ones can be grouped into a super-state, with generalized transitions between super-states. Your TurtleBot's "navigate" super-state might contain follow-path, avoid-obstacle, and recover sub-states; from the outside, the rest of the system just sees "navigating." This is how ROS's SMACH library lets you nest machines. Hierarchy turns an unreadable flat graph of 200 states into a handful of nested machines of a dozen each.

3. Composition

Build big machines by wiring small ones together. Three standard patterns:

Cascade
m1's output feeds m2's input (output vocab of m1 = input vocab of m2)
·
Parallel
same input feeds both machines; outputs concatenate
·
Feedback
a machine's output loops back to its own input

In SMACH these are smach.Sequence (cascade), smach.Concurrence (parallel), and smach.Iterator (feedback). The takeaway: complex behavior is composed from simple, individually-verifiable machines — exactly like functions in code.

The honest limit. FSMs are a finite model: they cannot, even in principle, solve problems requiring unbounded memory (the classic example: deciding whether arbitrarily long parentheses are balanced needs a counter an FSM doesn't have — that's a job for a pushdown automaton or Turing machine). For robot behavior coordination, finite is usually exactly right; but knowing the ceiling tells you when to reach for planning or learning instead. Lesson 15 picks up where rigid FSMs run out.
Two FSM states are equivalent (mergeable) when…

Chapter 8: Showcase — A TurtleBot Runs the Full Stack

Time to put every piece together. Below is a TurtleBot in a gridworld it has never seen. It must reach the goal flag. It does not know where the obstacles are — it discovers them by sensing, builds an occupancy grid, plans a path, drives along it, and an FSM executive coordinates the whole thing. Every tick is one full see-think-act cycle, and the panel on the right shows what each module of the stack is doing right now.

This is the entire lesson in one sim. Perception senses neighbor cells (blue). Localization reports the pose (purple). Planning runs a search over the discovered grid to produce a path (warm). Control turns the next waypoint into a move (green). The Executive FSM (teal badge) decides which mode is active: EXPLORE → NAVIGATE → (DETECT → REPLAN) → REACH GOAL.
Full Autonomy Stack — live gridworld

Press Run. The robot explores, hits unknown obstacles, replans, and reaches the goal. Click a cell to drop a new obstacle mid-run and force a live DETECT → REPLAN. Wall off the goal completely and the executive enters BLOCKED — graceful failure, not a crash.

Speed 5

Watch the discovered grid fill in as the robot moves: grey is unknown, dark is sensed-free, red is sensed-occupied. The dotted line is the current plan; when the robot senses a new obstacle on its path, the Planning card flips to REPLAN, a fresh search floods the grid, and a new path appears. The robot never sees the whole map — it acts on its belief, updates the belief by sensing, and re-plans. That is autonomy. That is the loop from Chapter 1, fully realized.

Now break it on purpose: click cells to build a wall between the robot and the goal. The next REPLAN finds no path, the executive transitions to BLOCKED, and the robot stops cleanly instead of driving into the wall. Handling failure gracefully — "how do I get my TurtleBot to back off after a collision?" — is exactly what the executive layer is for.

You just watched all 15 lessons cooperate. The planner (Lessons 3–5), the controller (Lessons 2, 6), the perception that fills the grid (Lessons 7–10), the pose estimate with its little jitter (Lessons 11–14), and the FSM executive (this lesson) — every module you'll study is here in miniature.

Chapter 9: The Map of the Series — Connections & Cheat-Sheet

You now hold the skeleton the whole course hangs on. Here is where each of the next 14 lessons sits on the autonomy stack — your roadmap.

ModuleLessonsWhat you'll build
Control & kinematics2, 6SE(2)/SE(3) transforms, unicycle/diff-drive models, PID & LQR controllers
Planning3, 4, 5A* on a C-space grid, RRT/RRT*, trajectory optimization via differential flatness
Perception7, 8, 9, 10LiDAR/IMU/ICP, pinhole cameras & calibration, SfM & RANSAC, learned/semantic perception
Localization & SLAM11, 12, 13, 14factor-graph SLAM, occupancy mapping & exploration, Kalman/EKF/UKF, particle filters & MCL
Executive & frontier1, 15this lesson; then imitation learning, VLAs, 3D Gaussian Splatting, world models

Cheat-sheet

See-Think-Act: sense → perceive+localize+plan → act → world changes → repeat. Data changes type on every arrow.

Autonomy stack: Perception → Localization&SLAM → (world model) → Planning → Control; Executive coordinates all four.

State: ξ = (x, y, θ) for a wheeled robot — position + heading = pose. Geometry constrains how ξ can change (no-slip).

Maps: occupancy (metric, precise, costly) · topological (graph, tiny, routing) · feature (sparse, re-localize) · semantic (meaning).

FSM: (S, I, O, n, o, s0). Each tick: o = o(i,s), then s ← n(i,s). Tame with reduction, hierarchy, composition.

Related lessons on Engineermaxxing

These existing lessons go deeper on topics we touched:

"What I cannot create, I do not understand." — Richard Feynman.
You can now create the see-think-act loop in code. Next, Lesson 2: the kinematics that turn a control command into actual motion.
On the autonomy stack, where does "A* path planning" (Lesson 3) sit?