Roadmaps II: Sensor-Based Roadmaps and Silhouettes
Where the planar GVD stops being a roadmap and what replaces it — the generalized Voronoi graph by intersecting equidistance sheets transversally, its disconnection and the hierarchical patch, a Lyapunov tracing law that lets a robot build the graph from range data alone, Canny's silhouette roadmap and the opportunistic path planner, and the price of exact planning.
Since ∇G(q) is a function of distance gradients, the planner can compute ∇G(q) solely from range sensor information.
In this chapter
Chapter 8 ended on a cliff. In the plane, "equidistant to the two nearest obstacles" is a curve, and the curves form a roadmap. In the same condition is one equation in three unknowns and cuts out a sheet — and a union of sheets is not a roadmap: the problem is only one dimension smaller than before. This chapter climbs down two ways, and they turn out to be one idea. The first way intersects more equations: equidistance to three obstacles in is a curve again, the generalized Voronoi graph, provided the sheets cross cleanly — transversally. The curves need not connect, and patching them, the hierarchical GVG, is the real work. The second way sweeps a slice through the space and tracks the extrema of a function on it: Canny's silhouette curves, recursing wherever the trace breaks. Both obey Chapter 8's Morse vocabulary: critical points are exactly where a roadmap can change connectivity.
The practical surprise is that a robot can build a roadmap without a map. The quantity is something a range sensor measures directly, and so is its gradient; a control law that drives to zero — a Lyapunov function, the book's first stability proof — lets Rusty trace the generalized Voronoi graph with no predictor, no corrector, and no equation of the curve. Exploration is then depth-first search over a graph the robot is still drawing.
The price of exactness closes the chapter. Canny's roadmap is complete and its running time is singly exponential in the dimension; the generalized mover's problem is PSPACE-hard. Both facts are why Part III gives completeness up for speed. Everything on this page runs: the Apartment's graph is built from a simulated range ring and lands on all twenty-six meet points of Chapter 8's exact diagram, the sphere's silhouette is its equator to , and the chapter's one-step Lyapunov example prints to four decimals in both the TypeScript port and the Rust.
The problem: a map nobody drew
Drop Rusty into the Apartment with no floor plan, only its range ring. Twenty seconds into the replay — under three minutes of simulated driving — a graph of the whole floor exists: every room, every doorway, the corridor, drawn by the robot driving along it.
Nothing in that animation knows where a wall is. Each step the robot reads its 360 rays, finds the local minima of the range — the distances to the nearby obstacles and, from their bearings, the gradients — and commands one velocity. The blue curve is Chapter 8's generalized Voronoi diagram; the robot does not compute it, it lives on it, because staying on it is a condition the sensor can check: two of the ranges are equal. The run ends when every curve leaving every meet point has been driven: meet points, boundary points where a curve runs into a corner, edges and m of roadmap after m of driving.
Two questions organize the rest of the chapter. Why does this work — what makes a velocity law converge onto a curve it cannot see? And what happens in three dimensions, where "two readings tie" is a surface and the robot would be wandering on sheets? The first answer is a Lyapunov function. The second is a story about transversality, disconnection, and slices — and it ends in a complexity bound that sends us to sampling.
Building intuition
Driving the graph
Watch the explorer in phases. Access: from wherever it starts, Rusty backs away from the nearest return — gradient ascent of , exactly Chapter 8's Lemma 5.2.1 — until a second return is as short as the first. Trace: now it holds the difference of the two shortest returns at zero while moving perpendicular to the chord between their two closest points. The sparkline under the floor plan is the square of that difference: it spikes when the robot is pushed off the curve (the parabolic edges near door jambs curve faster than the law can follow at a gentle gain) and decays back. Home: when a third return closes in, a meet point is near; the robot switches law and converges on the point where all three tie. Branch: each meet point in the plane has three departing edges. The hollow node's number counts those not yet driven. Backtrack: when a node has none left, the robot drives along edges it already knows to the nearest node that still has one — depth-first search over a graph whose nodes are being discovered by the search itself. Terminate: when no node has an undriven edge, the graph is complete.
The faint blue curves underneath are Chapter 8's exact GVD of the same walls, traced from geometry. The sensor's graph lands on them: every meet point the robot homes onto is three-way equidistant by exact wall geometry to , and all twenty-six exact meet points are found within five centimetres. Two more — in the corridor at and in the bedroom at — are genuine meet points that Chapter 8's lattice-seeded tracer missed, which the same exact test confirms. The headline control is , the stiffness with which the robot is pulled back onto the curve. The misconception this widget kills is the one in the chapter title: you do not need a map to build a roadmap. The roadmap is a sensor quantity.
From sheets to curves
In the plane one equation, , leaves one free direction: a curve. In it leaves two: a sheet. Imagine the Apartment extruded upward into a box-shaped room with a floor and a ceiling. The set of points equally far from the floor and the ceiling is the horizontal plane halfway up; equally far from the floor and the west wall is a tilted plane; and so on. These sheets form Chapter 8's GVD in three dimensions, and it is a perfectly good two-dimensional retract — but a planner searching a two-dimensional set has not gained much.
So intersect more. Points equidistant to the floor, the ceiling and the west wall lie on two sheets at once, and two planes in meet in a line. That is a generalized Voronoi graph edge: think of a ball rolling along the room, touching the floor, the ceiling and one wall at once; its centre traces the edge. Where a fourth obstacle ties, four sheets meet at a point — a meet point. Two conditions must hold for the picture to be right: the sheets must actually cross rather than graze, and the resulting curves must connect. The first is transversality; the second, it turns out, fails.
A slice through a doughnut
Canny's idea comes at the same problem from the other side. Sweep a plane through the configuration space and look at what the plane cuts out: a few closed curves. On each curve mark the extreme points in some fixed direction. As the plane moves those marks move, and their traces are curves — silhouettes — that a planner can follow. On a torus lying flat, a plane sweeping across it first touches the outer rim, cuts one oval, and then, as it reaches the hole, the oval pinches and splits into two. That moment is a critical slice: the silhouette breaks there, and the algorithm repairs it by solving the same problem one dimension down, inside the critical slice. The Silhouette Sweep in the mathematics section plays this out.
The mathematics
| Symbol | Meaning |
|---|---|
| triple-equidistant set; its subset with pairwise distinct gradients; a GVG edge in R³ (eq. 5.3) | |
| codimension (the GVD has codimension 1, the GVG dimension 1); transversal intersection at x | |
| second-order GVG edge and meet point on the sheet F_ij (eq. 5.4); projection onto its tangent space | |
| constraint vector, e.g. [d₁ − d₂, d₁ − d₃]ᵀ; its differential; the pseudoinverse DGᵀ(DG DGᵀ)⁻¹ | |
| tracing gains and unit tangent (eq. 5.5); the Lyapunov function of the tracer | |
| rod two-equidistant face, rod-GVG edge, junction region (§5.4) | |
| the slice at λ and coordinate projections; critical set; the stacked differential of Lemma 5.5.2 | |
| distance restricted to a slice and its minimum over obstacles (eqs. 5.7–5.8) | |
| generalized gradient, convex hull, index set of the closest obstacles | |
| number and maximum degree of the polynomials bounding the obstacles (Canny's bound) |
The generalized Voronoi graph
Note what the definition does not say: is not . Transitivity of equality gives for free, but not , and all three gradients must differ for the preimage theorem to apply. Choset's Table 5.2 compares the two structures in :
| Structure | Dimension | Codimension | Equidistant to | Symbol |
|---|---|---|---|---|
| GVD | ||||
| GVG |
Two lines in the plane each have codimension one; meeting transversally, their intersection has codimension two — a point. Two planes in meet transversally in a line, a plane and a line in a point; two lines in can never meet transversally, because a generic nudge separates them. Two planes in , codimension two each, meet in a point. That arithmetic is the whole content of Table 5.2.
DerivationGVG edges in R³ are one-dimensional
Statement (Choset §5.3.1). With , the set is a one-dimensional manifold, provided the sheets and intersect transversally.
Step 1 — each row is nonzero. On the first row is nonzero by definition (Chapter 8: that is what the extra in means); likewise the second row on .
Step 2 — rank loss means proportional rows. A matrix with nonzero rows loses rank exactly when for some .
Step 3 — proportional rows are a non-transversal crossing. The rows are the normals of the two sheets. Proportional normals mean equal tangent planes, , whose sum is a plane and not : the sheets are tangent there. Under the transversality assumption this does not happen, and if it did, a small perturbation of either sheet would remove it.
Step 4 — the preimage theorem. has full rank two on , so is a regular value there and is a submanifold of dimension , with tangent — the cross product of the two rows.
The numbers. The chapter's synthetic room — a box, Choset's Fig. 5.15 — is explored by the same tracer that runs in the Apartment, with exact plane distances in place of a scan. From one start it finds the four meet points , , , — each four-way equidistant to and of degree four — and eight spokes into the corners, thirteen edges in all. Every edge sample is three-way equidistant to , and the smallest singular value of along the edges is at least , the value on the rectangle's long edges: comfortably transversal everywhere.
Why the GVG falls apart, and the hierarchical GVG
In the room the GVG is connected. Put a box in the middle of the room — Choset's Fig. 5.19 — and it is not. The outer network is unchanged; but around the box there is a second component, a halo: the loop of points equally far from the floor, the ceiling and the box. No edge of the outer network touches it.
DerivationThe GVG is generically disconnected, and the HGVG repairs it
Statement (Choset §5.3.2). In a punctured three-dimensional free space there is in general no one-dimensional deformation retract [Choset ref. 63], so the GVG can be disconnected. The two-dimensional GVD is connected; GVG edges lie on the boundaries of its sheets, ; and a path that keeps while decreasing leads from a period to the missing cycle.
Step 1 — the hole. In the box-in-a-room, the floor–ceiling sheet is the plane halfway up, with a hole where the box is nearer than the floor and the ceiling. The boundary of that hole is the halo: the GVG edge , a cycle.
Step 2 — the trouble is on sheet boundaries. The GVD is a two-dimensional deformation retract of the free space and therefore connected. If the boundary of every sheet were connected, the GVG would be too. The floor–ceiling sheet's boundary is not: its outer rim belongs to the outer network, its hole to the halo.
Step 3 — draw a planar GVG on the sheet. On , look at which obstacles are second closest and where two of them tie. Those are the second-order edges of eq. (5.4) — planar GVG edges drawn on the sheet — and they are one-manifolds by the preimage theorem, because of the gradient conditions on the second line of (5.4).
Step 4 — a period announces a cycle. Around the box the second-order edges whose tied pair includes the box close into a loop: a period. Its common second-closest obstacle, the box, is the clue that a GVG component involving the box exists somewhere inside it.
Step 5 — descend to it. Starting on the period, follow : decrease the distance to the box while staying on the sheet. Since at the start, the path reaches — a GVG edge — unless the projected gradient vanishes first, in which case no such edge exists and the robot returns to the period.
Honesty. Full HGVG connectivity is "tedious and challenging" in Choset's words and is proved in Choset and Burdick [Choset ref. 106]; this book cites it and does not prove it. The HGVG is retract-like, not a retract. The numbers. The check builds Fig. 5.19 with a unit box at the centre of the room. The outer network never touches the box. The explorer, run on the floor–ceiling sheet with the sheet's own nearest-obstacle query, traces nine second-order edges; the four whose tied pair includes the box close into a period around it; descending from the period reaches , and from there the halo traces as a closed GVG cycle m long, three-way equidistant to .
Tracing without a predictor: the Lyapunov law
Chapter 3 traced curves with a discrete predictor–corrector: step along the tangent, then Newton back onto the curve. Choset §5.3.3 replaces both by one velocity,
with in the plane and in (eq. 5.5). On the GVG and the law reduces to : move along the tangent. Off it, the second term pulls back — Choset calls and "spring constants": is the speed along the edge, the stiffness of the return. Both terms need only and , and 's rows are differences of distance gradients — unit vectors pointing back along the shortest rays. That is the epigraph: the planner can compute solely from range sensor information.
The funnel is the chapter's micro-world: two point obstacles at and , whose GVG is the bisector , and Rusty at . The shading is — a trough along the bisector — and the robot slides down its wall while advancing along its floor. The sparkline plots on the curve , which the derivation below says it must follow; slide above zero and the robot climbs out instead. The misconception this widget kills: the controller needs the GVG's equation. It needs and at the point where the robot is, and nothing else.
DerivationThe tracing law is Lyapunov-stable
Statement (Choset §5.3.3, eq. 5.5). Along with , the function satisfies . For it is a Lyapunov function for the GVG wherever is invertible, so the robot converges onto the GVG.
Step 1 — the chain rule. .
Step 2 — the tangent term vanishes. , because lies in the null space of . Moving along the edge does not change to first order.
Step 3 — the pseudoinverse is a right inverse. , so .
Step 4 — the sign. for , with equality only where , on the GVG. In fact exactly along the continuous flow.
Step 5 — the neighborhood. All of this needs . Near the interior of a GVG edge the rows of are independent (Derivation 1), and they stay independent in a neighborhood [Choset ref. 108] — the neighborhood the definition box asks for.
Where it stops holding. The argument needs two things: a fixed set of closest obstacles, so that is smooth, and an invertible . Both fail at meet points. There a further obstacle ties, the identity of the "closest" ones switches, is not even continuous across the switch, and the Lyapunov argument has nothing to say; and wherever two gradients become parallel — a non-transversal point — is singular and the pseudoinverse does not exist. The tracer's guarantee is local, and at meet points a different law, homing, takes over. The sign of is the planner's choice (Choset's footnote 4): the null space is a line and the tracer keeps the direction that continues the previous heading. Sensing : fit a codimension-one plane through the closest points on the closest obstacles; the tangent is its normal. In the plane, is perpendicular to the chord through the two closest points, and the tangent is along the chord's perpendicular — Chapter 8's Fig. 5.13.
The chapter's micro-example, by hand
Take the funnel's opening position: sites , , Rusty at , gains , .
The velocity points left, toward , while advancing along the edge. Look at the correction's -component: exactly , minus Rusty's offset from the bisector. For two point sites the Newton-like step , projected on the line through the sites, is exactly the signed distance to the bisector — not approximately, everywhere — and Exercise 1 asks why. The check pins all of these numbers to and the identity to at twenty seeded points around twenty seeded pairs of sites. Integrating the law with explicit Euler steps of s, never increases, and at it is within of , the continuous-time prediction; after steps of s the robot is on to , having driven up the edge. With , more than triples in s.
Meet-point homing
DerivationHoming is the same law with an empty null space
Statement (Choset §5.3.3). With in the plane (three rows, , in ), is square, , and converges to the meet point.
Step 1 — Derivation 3 with . The computation of never used except to kill it; with it reads unchanged.
Step 2 — only at the meet point. Two independent equations in the plane, three in , cut out isolated points: the meet points, where obstacles tie.
Step 3 — the geometry of the step. Linearize each about : the step goes to the point where the linearized distances agree, the centre of the circle through the three closest points (the sphere through four in ). Choset: "The velocity vector points toward the center of this sphere."
Higher-order laws come from swapping : a second-order edge uses , a second-order meet point . The numbers. On Chapter 8's slab — pegs at and , a wall along — homing from three seeds converges to the meet point with clearance to . For the wall the linearization is exact; for the pegs it is first order, so the aim sharpens with distance: from m away the homing velocity points within of the meet point, from m away within .
Beyond a point robot: the rod
The rod-GVG edges play the role of meet points, but each is a whole curve of orientations: a small rod can spin a full turn while staying three-way equidistant, so is homeomorphic to (Choset's footnote 5). The R-edges inherit adjacency from the plane. The chapter keeps the rod to a definition and a check — Exercise 6 builds it — and the check confirms the first claim: a m rod centred near the Workbench's widest meet point (clearance ) stays three-way equidistant through all orientations sampled, Newton in at fixed converging to , and R-edge placements are sampled from Chapter 8's point-GVD.
Silhouettes: Canny's roadmap
The sweep makes the definitions concrete on three bodies. The sphere has one silhouette, its equator — traced as two curves, the maxima and the minima of — born at and dying at . The torus lying flat (, ) is Choset's Figs. 5.31–5.32: the slice is one closed curve for and two for , so the critical values are (birth and death) and (pinch). Its silhouette is four arcs — the and halves of the outer and inner equators — and they are not connected to one another: four components. The linking curves on the two pinch slices join them into one. The ellipsoid with a bent hole is Fig. 5.25 simplified: an ellipsoid with semi-axes , and and a hole of radius drilled along at , its axis bending as . The bend matters. With a straight hole the wall is a cylinder, is constant along its vertical lines, and the extrema are degenerate — not Morse. Bent, each slice's wall curve is a parabola with one nondegenerate extremum. Choset describes the silhouette as the ellipsoid's equator, the perimeter of the hole and the two curves along its side; the sweep finds it in six pieces, and the linking curves join them into one. That is the misconception the widget kills: the silhouette is not the outline of the body as you see it. It is the critical set of a projection, and it lives where the surface's tangent plane contains the direction.
DerivationSilhouettes are critical sets, and connectivity changes only at critical points
Statement (Choset §5.5.1; Lemmas 5.5.1–5.5.2, the slice lemma, Morse theory [Choset ref. 315]). For , a point is on the silhouette iff loses rank; the silhouette is the union over of the critical points of on each slice; and between adjacent critical values the slice topology does not change, so the silhouette's connectivity can change only at critical slices.
Step 1 — Lagrange. At an extremum of on , every direction tangent to the surface leaves stationary to first order, so has no tangential component: (Lemma 5.5.1).
Step 2 — stacking. For vector-valued constraints and functions the same condition says the rows of are combinations of the rows of on the tangent space — rank loss of the stacked matrix (Lemma 5.5.2). For two real-valued functions, rank loss of a two-row matrix is parallelism, and Lemma 5.5.1 is recovered.
Step 3 — the slice lemma. Fixing and extremizing on the slice is the same as asking that the map restricted to fail to be a submersion: the rows (the slice) and (the extremized coordinate) together with lose rank. So .
Step 4 — the sphere. For the stacked matrix above has determinant , zero exactly on the equator. The check sweeps the unit sphere: every silhouette sample has and there, while at , off the equator, ; the only critical slices are birth and death at .
Step 5 — critical slices are where the roadmap's tangent lies in the slice. At a critical point of restricted to the roadmap, the roadmap's tangent is orthogonal to : it lies in the slice. There the number of silhouette pieces can change, and by Morse theory it can change only there: between adjacent critical values a diffeomorphism carries one slice's intersection with to the next (Choset Fig. 5.33).
The recursion. Each critical slice is a lower-dimensional problem of the same kind: sweep it along , extremize , find its critical slices, recurse, down to dimension one. Accessibility and departability come from treating the slices through and as critical, and connectivity is proved by induction on dimension [Choset refs. 90–92]. The demonstrator in this chapter recurses once: in a surface in a critical slice meets the surface in curves, and those curves are their own roadmap — the linking curves. The numbers. The torus sweep finds its critical values at to , with two slice curves and four extrema just inside and one curve with two extrema just outside, and four silhouette components that the linking curves join into one. The bent-hole ellipsoid has six critical values, at , , , , and . The slice-curve count changes exactly twice, where the hole punches through at and closes at ; the smoothing of the rim (the solid is a smooth maximum of the ellipsoid and the tube, so that Newton has a gradient) adds a "dimple" critical slice just outside each. Midway through the hole the slice is two curves with six extrema. Six silhouette components, one with the linking curves.
Choset's ellipsoid has four critical points, to , because his hole goes down and comes back up, punching through the slice twice on the way in and twice on the way out. Ours goes straight through, so it has two; the honest bookkeeping above is what the sweep finds, not what the figure shows.
The opportunistic path planner and the generalized gradient
Canny's silhouettes extremize a coordinate. Canny and Lin's opportunistic path planner (OPP) extremizes something a robot cares about: the distance to the nearest obstacle, restricted to the slice.
DerivationOPP freeways are ties, characterized by the generalized gradient
Statement (Choset §5.5.2). Slice maxima of trace freeways joined by bridges near interesting critical points. Since is nonsmooth at ties, a maximum is characterized by ; for convex obstacles every freeway point is a tie, hence a GVD point.
Step 1 — smooth between ties. On a slice, wherever is the unique closest obstacle, and it inherits the smoothness of there (Choset Fig. 5.37).
Step 2 — at a tie, the convex hull. Approaching a tie from either side gives the limiting gradients of the tied obstacles; the generalized gradient is their convex hull.
Step 3 — a maximum means no ascent direction. At a slice maximum no direction along the slice increases every active ; by a separating-hyperplane argument that is exactly . On a one-dimensional slice: the active slopes bracket zero.
Step 4 — bridges at merges and splits. Freeways are traces of maxima within a channel; where two channels merge or split — where the slice's normal is parallel to an obstacle's surface normal, the rank loss of again (Choset Fig. 5.35) — maxima appear or vanish, and a bridge along the slice joins them.
Problem 12, for convex obstacles. Each is convex when is (Choset Problem 19), so its restriction to a slice is convex and has no interior maximum; a maximum of must therefore be a tie of two or more obstacles with slopes of both signs — a point of the GVD, for any slice direction. Exercise 2 asks for the general proof. The numbers. In the chapter's tilted room with two convex obstacles, the sweep finds freeway points on freeways; at every one of them the active slopes bracket zero and two or more obstacles tie. The channel count changes at the interesting critical values , and the bridges there and at the bifurcation points connect the four freeways into one roadmap. The room's walls are tilted on purpose: a slice parallel to a wall makes constant along it, every point a degenerate maximum, and the Morse assumption fails — the tilt is the general-position fix.
What exactness costs
Canny's algorithm was the first general roadmap algorithm, and with it came the complexity bound that made roadmap theory a theory: for a configuration space of dimension whose obstacles are bounded by polynomials of degree at most , any path-planning query can be answered in
time [Choset refs. 90–92]. That is singly exponential in , where the earlier general method of Schwartz and Sharir — cylindrical algebraic decomposition — was doubly exponential. It is still enormous. Taking the constant in the as one, and , the base-ten logarithm of the bound is for , for , for and for — a six-joint arm among quadric obstacles: more operations than there are atoms in the observable universe, by over three hundred orders of magnitude. And no algorithm can do fundamentally better in general: Reif showed that the generalized mover's problem — many independently moving parts — is PSPACE-hard (Appendix D). Exact, complete planning in high dimensions is not going to get cheap.
Canny's roadmap is complete, and it has never been a practical planner; the opportunistic planner, which is, gives up nothing of the theory but runs on a sweep that still scales with the volume of the space. The honest reading is that this chapter's exact structures are tools for low dimensions and for understanding: the GVG for a mobile robot that must explore, silhouettes as the reason sweep-based coverage works (Chapter 10), critical points as the place where everything interesting happens. For a six-joint arm, Part III trades completeness for probabilistic completeness and the problem becomes tractable.
The algorithm
- In
- a nearest-obstacle query (a range ring's local minima of ρ with their bearings, or exact geometry); gains α > 0, β < 0; step dt; tolerances meetTol, boundaryTol, nodeTol
- Out
- a graph whose nodes are meet, access and boundary points and whose edges are the driven polylines
- access: drive along until
accessTol; in continue along the two-equidistant sheet, increasing , until a third reading ties. Record an access node with two departure slots - depart: pick an unexplored slot at the current node, step
departStepalong it, start a new edge - trace: apply the Lyapunov law with from the nearest readings and signed to continue the heading; append to the edge; log
- detect: if the -th reading comes within
meetTolof the first — "a sudden change in one of the two closest obstacles" — go to home; ifboundaryTol, close the edge at a boundary point and go to backtrack - home: Newton on , i.e. the homing law with , to
homeTol; if a node lies withinnodeTol, close the edge there and mark the arriving slot explored; otherwise create a meet node with the departure directions (each omits one obstacle, signed so the omitted one falls behind) and close the edge there - branch: if the node has an unexplored slot go to depart; else backtrack
- backtrack: breadth-first search over known edges to the nearest node with an unexplored slot; drive its polylines; go to depart. If no such node exists: done
Rejected ties. A homing that converges somewhere other than a three-way (four-way) tie, or a tie whose gradients coincide, is reported as spurious and tracing resumes after a short cooldown — the "sudden change" detector is a heuristic, and with noisy ranges it fires early, late or twice. Degenerate meet points. When four or more readings tie to within the sensor's resolution — the Apartment's mirrored doorways produce meet points two millimetres apart — the node gets one departure per adjacent pair of closest points around the robot.
- In
- the m (edge) or m + 1 (homing) nearest readings d_i, ∇d_i; gains α, β; the previous heading
- Out
- the commanded velocity q̇ and Γ = ½GᵀG
- , rows
- ; if is singular return "undefined" (a meet point for the edge law, or parallel gradients)
- if : unit vector of — the perpendicular of the row in the plane, the cross product of the rows in — negated if heading ; else
- return and ; along it
- In
- a sheet F_ij (here the floor–ceiling plane z = h/2) with its nearest-obstacle query; a candidate obstacle k
- Out
- a period around k, a link to the GVG cycle, the cycle
- explore the planar GVG of the sheet — the second-order edges — with the exploration algorithm above, using the sheet's own query (obstacles left out)
- collect the second-order edges whose tied pair includes ; if they close into a loop around (angular gaps small), it is a period
- from a point of the period, follow until (stop: a GVG edge) or (stop: no edge; return to the period)
- trace the GVG edge reached; if it closes on itself, it is the missing GVG cycle; link it to the period
- In
- an implicit surface S = f⁻¹(0) in R³ with ∇f; a box; the number of slices
- Out
- silhouette curves, critical slices with their before/after signatures, linking curves; component counts
- for on a grid over the -range: trace every closed curve of with Chapter 3's predictor–corrector, seeded from a lattice and deduplicated
- on each curve, locate the extrema of as the sign changes of (the tangent has no -component there — Lemma 5.5.2), refined by bisection along the chord with Newton projection
- signature of a slice = (number of curves, number of extrema); between grid values with different signatures, bisect on to locate the critical value
- chain the extrema across slices into silhouette curves (nearest neighbour, maxima with maxima)
- recurse once: on each critical slice the roadmap of the one-dimensional intersection is the intersection itself — take the slice curves just either side of as linking curves
- count connected components of the silhouette alone and with the linking curves
- In
- a planar polygonal world in general position; a slice direction
- Out
- freeways, interesting critical values, bridge curves
- for each slice : split the slice into channels; on each, find the strict local maxima of by sampling and golden-section refinement
- at each maximum record the active set and the slopes , and test
- chain maxima across slices into freeways
- locate interesting critical values by bisection where the channel count changes; on the merged side, add the slice segment joining the freeway points of the splitting channels as a bridge
- where a freeway ends in free space (a bifurcation point), bridge it along its last slice to the nearest freeway point in the same channel
- access and departure: slice-constrained gradient ascent of from and
Implementation in Rust
This chapter adds the gvg submodule to Chapter 8's roadmap crate: scan.rs turns a range ring
into the nearest obstacles, tracer.rs is eq. (5.5), explore.rs the five-step exploration,
hgvg.rs the period following, canny.rs the silhouette demonstrator and opp.rs the freeways. The
tracer is written once for any number of readings; const generics carry the sizes, and the
pseudoinverse returns None exactly where the Lyapunov argument stops holding.
use nalgebra::{SMatrix, SVector, Vector2};
/// The k nearest hits in a range ring: distance and unit direction away from each (C §4.3.1).
/// `obstacle_id` is `None` from a scan — the sensor cannot name what it sees, and the law never asks.
pub struct Nearest<const K: usize> {
pub d: [f64; K],
pub grad: [Vector2<f64>; K],
pub obstacle_id: [Option<usize>; K],
}
pub struct Twist { pub v: Vector2<f64> }
pub struct GvgTracer { pub alpha: f64, pub beta: f64 }
/// DG† = DGᵀ (DG DGᵀ)⁻¹ for a full-row-rank differential. `None` where the Gram matrix is singular:
/// two sheet normals parallel (a non-transversal crossing) or, for the edge law, a meet point —
/// exactly where Lyapunov's neighborhood ends and homing has to take over.
pub fn pseudo_inverse<const R: usize, const C: usize>(dg: &SMatrix<f64, R, C>) -> Option<SMatrix<f64, C, R>> {
let gram = dg * dg.transpose();
gram.try_inverse().map(|inv| dg.transpose() * inv)
}
/// G and DG from the first R + 1 readings: rows d₁ − d_j and ∇d₁ − ∇d_j.
fn constraint<const K: usize, const R: usize>(n: &Nearest<K>) -> (SVector<f64, R>, SMatrix<f64, R, 2>) {
let g = SVector::<f64, R>::from_fn(|j, _| n.d[0] - n.d[j + 1]);
let dg = SMatrix::<f64, R, 2>::from_fn(|j, c| n.grad[0][c] - n.grad[j + 1][c]);
(g, dg)
}
impl GvgTracer {
/// Edge tracing, C eq. (5.5): q̇ = α v + β (DG)† G with v ∈ Null(DG), ‖v‖ = 1, signed to keep
/// going the way we were going (Choset's footnote 4). Also returns Γ = ½ GᵀG; Γ̇ = β GᵀG.
pub fn trace_step(&self, n: &Nearest<2>, heading: Vector2<f64>) -> Option<(Twist, f64)> {
let (g, dg) = constraint::<2, 1>(n);
let dg_pinv = pseudo_inverse(&dg)?;
let row = dg.row(0);
let mut v = Vector2::new(-row[1], row[0]).normalize();
if v.dot(&heading) < 0.0 { v = -v; }
let correction = self.beta * (dg_pinv * g);
Some((Twist { v: self.alpha * v + correction }, 0.5 * g.norm_squared()))
}
/// Meet-point homing: DG is square, Null(DG) = {0}, so the law is a Newton-like step
/// β DG⁻¹ G toward the centre of the circle through the three closest points.
pub fn home_step(&self, n: &Nearest<3>) -> Option<(Twist, f64)> {
let (g, dg) = constraint::<3, 2>(n);
let dg_pinv = pseudo_inverse(&dg)?;
Some((Twist { v: self.beta * (dg_pinv * g) }, 0.5 * g.norm_squared()))
}
/// Access (Ch. 8, Lemma 5.2.1): climb ∇d₁ until the second reading ties. Unit speed, so the
/// ascent takes d₂ − d₁ seconds at most from any start in a bounded room.
pub fn access_step(&self, n: &Nearest<2>) -> Twist {
Twist { v: self.alpha * n.grad[0] }
}
}The tracer returns Option rather than a bare (Twist, f64) so that the one place the derivation
fails — a singular — is a value the caller must handle, not a
NaN that drives the robot into a wall. The explorer is a state machine around the tracer, and its
graph is petgraph's.
use petgraph::graph::{NodeIndex, UnGraph};
pub struct MeetNode { pub q: Vector2<f64>, pub clearance: f64, pub departures: Vec<Vector2<f64>>, pub explored: Vec<bool> }
pub struct Edge { pub polyline: Vec<Vector2<f64>>, pub length: f64 }
/// The incrementally built topological map; `frontier` lists (node, slot) pairs not yet driven.
pub struct GvgGraph { pub graph: UnGraph<MeetNode, Edge>, pub frontier: Vec<(NodeIndex, usize)> }
pub enum Event { OnEdge, MeetPoint(NodeIndex), BoundaryPoint, Done }
enum Phase { Access, Depart, Trace, Home, Backtrack(Vec<Vector2<f64>>), Done }
pub struct Explorer<'r> {
pub robot: &'r mut sim::Rusty,
pub tracer: GvgTracer,
pub graph: GvgGraph,
phase: Phase, heading: Vector2<f64>, edge: Vec<Vector2<f64>>, from: NodeIndex,
pub gamma_log: Vec<f64>,
}
impl Explorer<'_> {
/// One tick: scan; access / trace / home by phase; DFS to the next unexplored slot.
pub fn tick(&mut self, dt: f64) -> Event {
let near: Nearest<3> = scan::nearest_from_scan(&self.robot.scan());
match &self.phase {
Phase::Access => {
if near.d[1] - near.d[0] > ACCESS_TOL { self.drive(self.tracer.access_step(&near.first2()), dt); return Event::OnEdge; }
self.from = self.add_node(self.robot.position(), access_departures(&near));
self.phase = Phase::Depart;
Event::OnEdge
}
Phase::Trace => {
// "A sudden change in one of the two closest obstacles": a third reading closes in.
if near.d[2] - near.d[0] < MEET_TOL { self.phase = Phase::Home; return Event::OnEdge; }
if near.d[0] < BOUNDARY_TOL { return self.close_at_boundary(); }
let Some((tw, gamma)) = self.tracer.trace_step(&near.first2(), self.heading) else {
self.phase = Phase::Home; // DG DGᵀ singular: we are at (or past) a meet point
return Event::OnEdge;
};
self.gamma_log.push(gamma);
self.drive(tw, dt);
self.edge.push(self.robot.position());
Event::OnEdge
}
Phase::Home => match newton_home(&mut *self.robot, &self.tracer, HOME_TOL) {
Some(q) => {
let node = self.node_near(q, NODE_TOL).unwrap_or_else(|| self.add_meet_node(q, &near));
self.close_edge(node);
self.next_from(node);
Event::MeetPoint(node)
}
None => { self.phase = Phase::Trace; Event::OnEdge } // spurious tie: carry on
},
Phase::Depart => self.depart(dt),
Phase::Backtrack(_) => self.follow_backtrack(dt),
Phase::Done => Event::Done,
}
}
/// DFS bookkeeping: an unexplored slot here, or BFS over known edges to the nearest node with one.
fn next_from(&mut self, n: NodeIndex) {
self.phase = if self.graph.graph[n].explored.iter().any(|e| !e) { Phase::Depart }
else { match self.path_to_frontier(n) { Some(p) => Phase::Backtrack(p), None => Phase::Done } };
}
}Canny's demonstrator works on implicit surfaces. Each slice is a planar curve-tracing problem, so Chapter 3's tracer does the work; the extrema are the sign changes of one partial derivative.
use nalgebra::{SVector, Vector2};
pub struct Silhouette {
pub curves: Vec<Vec<SVector<f64, 3>>>,
pub critical_points: Vec<SVector<f64, 3>>,
pub linking: Vec<Vec<SVector<f64, 3>>>,
pub depth: usize,
}
struct Slice { lambda: f64, pieces: Vec<Vec<Vector2<f64>>>, extrema: Vec<(SVector<f64, 3>, bool)> }
/// Sweep π₁ slices; π₂-extrema where D(f, π₁₂) = [∇f; e₁; e₂] loses rank, i.e. ∂f/∂q₃ = 0
/// (Lemma 5.5.2); recurse once on the critical slices, where the (curves, extrema) count changes.
pub fn canny(f: &dyn Fn(SVector<f64, 3>) -> f64, grad_f: &dyn Fn(SVector<f64, 3>) -> SVector<f64, 3>,
bounds: [(f64, f64); 3], n_slices: usize) -> Silhouette {
let lambdas: Vec<f64> = (0..=n_slices).map(|k| bounds[0].0 + (bounds[0].1 - bounds[0].0) * k as f64 / n_slices as f64).collect();
let slices: Vec<Slice> = lambdas.iter().map(|&l| slice(f, grad_f, l, bounds)).collect();
let mut sil = Silhouette { curves: chain_extrema(&slices), critical_points: vec![], linking: vec![], depth: 1 };
for w in slices.windows(2) {
if signature(&w[0]) == signature(&w[1]) { continue; }
// Bisect on λ for the critical value; the slice there is pinched, so the linking curves
// are taken just either side — the recursion's roadmap of a one-dimensional set is the set.
let l_star = bisect_signature(f, grad_f, bounds, w[0].lambda, w[1].lambda, 8);
let eps = 0.5 * (w[1].lambda - w[0].lambda);
for l in [l_star - eps, l_star + eps] {
sil.linking.extend(slice(f, grad_f, l, bounds).pieces.into_iter().map(|c| lift(l, &c)));
}
sil.critical_points.push(changed_extremum(&w[0], &w[1], l_star));
sil.depth = 2;
}
sil
}
/// The curves of f(λ, ·) = 0 by Chapter 3's predictor–corrector, and the sign changes of ∂f/∂q₃
/// along each: there the tangent (−f₃, f₂) has no q₂-component, so q₂ is extremal.
fn slice(f: &dyn Fn(SVector<f64, 3>) -> f64, grad_f: &dyn Fn(SVector<f64, 3>) -> SVector<f64, 3>,
lambda: f64, bounds: [(f64, f64); 3]) -> Slice {
let g = |p: Vector2<f64>| f(SVector::<f64, 3>::new(lambda, p.x, p.y));
let dg = |p: Vector2<f64>| { let n = grad_f(SVector::<f64, 3>::new(lambda, p.x, p.y)); Vector2::new(n[1], n[2]) };
let pieces = trace_all_closed(&g, &dg, bounds[1], bounds[2], bugs::TraceParams { step: 0.03, ..Default::default() });
let f3 = |p: &Vector2<f64>| grad_f(SVector::<f64, 3>::new(lambda, p.x, p.y))[2];
let extrema = pieces.iter().flat_map(|c| sign_changes(c, f3).map(|(p, is_max)| (lift_point(lambda, p), is_max))).collect();
Slice { lambda, pieces, extrema }
}The opportunistic planner's one new idea fits in a function: a slice maximum of a nonsmooth minimum is a convex-hull test on first derivatives.
/// 0 ∈ ∂D̃(q*) = Co{∂d̃_i/∂y : i ∈ Z(q*)} on a vertical slice: the active slopes bracket zero.
/// For one active obstacle this is the smooth condition ∂d̃/∂y = 0; at a tie it is a kink maximum.
pub fn generalized_gradient_has_zero(slopes: &[f64], tol: f64) -> bool {
let lo = slopes.iter().cloned().fold(f64::INFINITY, f64::min);
let hi = slopes.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
lo <= tol && hi >= -tol
}
pub struct FreewayPoint { pub q: Point2<f64>, pub d: f64, pub active: Vec<usize>, pub slopes: Vec<f64>, pub channel: usize }
/// Strict local maxima of D̃(·; λ) on each channel of the slice x = λ, golden-section refined.
pub fn slice_maxima(world: &OppWorld, lambda: f64, samples: usize) -> Vec<FreewayPoint> {
channels(world, lambda).iter().enumerate().flat_map(|(ci, &(lo, hi))| {
let d = |y: f64| world.nearest(Point2::new(lambda, y)).d;
strict_maxima(d, lo, hi, samples).into_iter().map(move |y| world.freeway_point(lambda, y, ci))
}).collect()
}The worked example, and its printed output
use nalgebra::Vector2;
use roadmap::gvg::{GvgTracer, Nearest};
/// Two point sites; Nearest in *site* order (site 1 at the origin), as the text labels them.
fn nearest(q: Vector2<f64>, sites: &[Vector2<f64>; 2]) -> Nearest<2> {
let d = sites.map(|c| (q - c).norm());
let grad = sites.map(|c| (q - c).normalize());
Nearest { d, grad, obstacle_id: [Some(0), Some(1)] }
}
fn main() {
let sites = [Vector2::new(0.0, 0.0), Vector2::new(4.0, 0.0)];
let tracer = GvgTracer { alpha: 1.0, beta: -1.0 };
let q = Vector2::new(2.5, 1.0);
let n = nearest(q, &sites);
let g = n.d[0] - n.d[1];
let dg = n.grad[0] - n.grad[1];
let dg_pinv = dg / dg.norm_squared();
let v = Vector2::new(-dg.y, dg.x).normalize();
let (tw, gamma) = tracer.trace_step(&n, Vector2::new(0.0, 1.0)).unwrap();
println!("G = {g:.4} DG = ({:.4}, {:.4}) DG+ = ({:.4}, {:.4}) v = ({:.4}, {:.4})", dg.x, dg.y, dg_pinv.x, dg_pinv.y, v.x, v.y);
println!("correction = ({:.4}, {:.4}) qdot = ({:.4}, {:.4}) Gamma = {gamma:.4} dGamma = {:.4}",
tracer.beta * dg_pinv.x * g, tracer.beta * dg_pinv.y * g, tw.v.x, tw.v.y, tracer.beta * g * g);
// The Lyapunov box: integrate, watch Γ. The edge x = 2 is vertical, so "keep going up" is the
// heading for the whole run.
let heading = Vector2::new(0.0, 1.0);
let (mut q, mut prev) = (q, f64::INFINITY);
for _ in 0..200 {
let (tw, gamma) = tracer.trace_step(&nearest(q, &sites), heading).unwrap();
assert!(gamma <= prev + 1e-12, "Γ must not increase");
prev = gamma;
q += tw.v * 0.05;
}
println!("200 steps of dt = 0.05: Gamma monotone, |x - 2| < 1e-3: {}", (q.x - 2.0).abs() < 1e-3);
}G = 0.8898 DG = (1.7605, -0.1833) DG+ = (0.5619, -0.0585) v = (0.1036, 0.9946)
correction = (-0.5000, 0.0521) qdot = (-0.3964, 1.0467) Gamma = 0.3959 dGamma = -0.7918
200 steps of dt = 0.05: Gamma monotone, |x - 2| < 1e-3: truelyapunov_step_matches_text pins every printed number to , the correction's -component
to to , and the monotone descent of . Two hundred steps of s would not
land the robot: at s the offset has shrunk only by , to about . So the test
integrates to s, where holds, and checks the s value of
against instead. The other two examples print the chapter's
larger numbers:
explore: done after 5779 ticks, 205.0 m driven
27 meet points, 33 boundary points, 62 edges, 103.4 m of roadmap
every homed meet point three-way equidistant by exact geometry to < 1e-6
exact GVD (Chapter 8): 26 meet points, 26 matched within 0.05 m, 2 extra: (6.00, 4.30) (7.85, 6.79)
fifty seeded queries, 29 pass the filter, 29 answered
mean length: GVG 10.88 m shortest (disc, r = 0.22) 6.68 m ratio 1.62 mean, 2.46 worst
mean min clearance: GVG 0.48 m shortest 0.22 m
torus R = 2, r = 0.7: critical lambda -2.700 -1.300 1.300 2.700; silhouette components 4 -> 1
ellipsoid with a bent hole: critical lambda (curves/extrema before -> after)
-2.999 0/0 -> 1/2
-0.122 1/2 -> 1/10
-0.109 1/10 -> 2/6
1.307 2/6 -> 1/6
1.322 1/6 -> 1/2
2.992 1/2 -> 0/0
silhouette components 6 -> 1 with linking curves
sphere r = 1: silhouette |q3| < 1e-6 at every sample; critical lambda -1.000 1.000explored_graph_matches_exact_gvd asserts that every exact meet point is matched within five
centimetres and every homed meet point is a three-way tie by exact geometry; sphere_silhouette_is_equator
asserts (Derivation 5, step 4); torus_pinches_at_r_minus_r and
ellipsoid_critical_slices pin the values above. The TypeScript port in web/lib/roadmap/ runs the
same twelve checks, and every widget on this page is that port.
Three things the port had to learn from the range ring. First, a ring of 360 rays reports the local minima of on its rays, not on the obstacles: the closest point can sit half a degree away, and the homing then converges to a point a centimetre off the true meet point. The port refines each minimum's bearing by golden-section search between its neighbouring rays — Chapter 3's "more rays where they matter" — and the meet points then land on the exact ones to . Second, one wall seen across the seam, or a flat minimum split in two, produces two readings with the same gradient: is singular and the meet detector fires on nothing. Readings within rad and m of each other are merged. Third, transversality says exactly degenerate meet points have probability zero; the Apartment's mirrored doorways produce two meet points two millimetres apart all the same, and the robot cannot tell them apart. Such a node gets one departure per adjacent pair of closest points, which is what the geometry would give if the two points were merged.
Putting it together: the floor plan Rusty drew
The integration lab uses the explored graph as what Chapter 8 said a roadmap is for. Rusty explores the Apartment from room A with the ideal ring, and the graph it draws — meet points, edges — is turned into a roadmap: every polyline sample a node, consecutive samples joined, meet points shared. Getting on is Chapter 8's gradient ascent, the same access the explorer used; the landing point is on the GVD, and the nearest explored sample is never more than cm away, which is the honest measure of how completely the sensor-built graph covers the exact diagram. Riding is Chapter 6's A*. Getting off is the goal's ascent, reversed.
Chapter 8's fifty seeded start–goal pairs — the same generator, the same filter, twenty-nine pairs surviving it — are answered on the explored GVG and on the visibility graph for a m disc. All twenty-nine are answered; the explored graph is one connected component. The GVG paths average m against m for the shortest paths: times as long on average and times in the worst case — the price of riding the middle of every room and doorway. They average m of minimum clearance against m — the shortest path grazes the inflated walls, which is what shortest means. The sensor-built graph's mean path length is within two percent of Chapter 8's grid-GVD paths for the same queries ( m): the robot's map is as good a highway as the geometer's.
The sister book's frontier exploration (Probabilistic Robotics via Rust, Chapter 24) is the probabilistic cousin of this lab: it drives toward the boundary between known and unknown cells of an occupancy grid, while the GVG explorer drives along a topological skeleton and needs no grid at all — but it trusts its range readings, and the GVG Explorer's noise slider shows what that trust costs (Exercise 4). What a range ring actually returns, and how noisy, is the sister book's Chapter 10. Maps that keep a Euclidean distance field (the sister book's Chapter 19 surveys map representations) yield the GVD as the field's ridge, exactly as Chapter 8's brushfire did; and Choset and Nagatani's topological SLAM, which localizes a robot by where it is on the explored GVG, is the direct descendant of this chapter's explorer.
Three pointers close Part II's roadmaps. Chapter 10 takes the critical points of this chapter literally: the boustrophedon decomposition's cell boundaries are the slices through Canny's critical points, found by a robot with Lemma 5.5.2 in its sensor loop. The complexity bound sends us to Chapter 11, where a roadmap is built by throwing darts and the contract of Definition 5.0.2 is restated with probability one. And the capstone, Chapter 23, explores an unknown Apartment again.
Exercises
- Foundation exerciseDifficulty 2 of 3The Newton step lands on the bisector — exactly, and only for points
For two point sites and , prove that the component of along equals the signed distance from to the bisector, for every off the line through the sites (Choset's micro-example has it equal to ). Then repeat the computation numerically for a point site and a segment site (a parabolic edge) and explain what you find: is the step still exact, and if not, what is it?
With sites (0, 0) and (4, 0), Rusty at (3, −1) and β = −1, what is the x-component of the correction β(DG)†G?
- Foundation exerciseDifficulty 3 of 3OPP is a subset of the GVG, for any slice direction
Prove Choset's Problem 12: for any choice of slice direction, every point of the opportunistic path planner's roadmap lies on the GVG. Use the generalized-gradient characterization of slice maxima, and say where convexity of the obstacles enters (Problem 19: is convex when is). Then explain why bridge curves need not lie on the GVG, and whether that matters for the claim.
- Conceptual exerciseDifficulty 1 of 3Predict the landing time, then checkPredict first
In the Lyapunov Funnel with the micro-example's sites, set β = −3 and put Rusty at (3, 0) heading up. With explicit Euler steps of dt = 0.05 s, how many steps until |x − 2| < 0.01? Predict from Γ̇ = βG² before you run anything.
- Conceptual exerciseDifficulty 2 of 3Break the meet-point detector
In the GVG Explorer, raise the range noise step by step until the exploration no longer terminates cleanly — it reports spurious ties, revisits a meet point as a new node, or misses a doorway. From the event log and the meet-point count, decide for one failure whether a meet point was spurious (announced where no third obstacle is near) or missed (driven through), and relate it to Choset's detector, "a sudden change in one of the two closest obstacles". Which tolerance would you widen to fix each kind, and what does widening it break?
- Practical exerciseDifficulty 3 of 3Follow a period to the halo
Implement
follow_periodinhgvg.rsfor the box-in-a-room world of Choset Fig. 5.19, extruded from analytic planes: explore the second-order GVG on the floor–ceiling sheet with the sheet's own nearest-obstacle query, detect the period whose common second-closest obstacle is the box, descend from it, and trace the halo. Assert that the descent stops on a three-way tie of the floor, the ceiling and the box at clearance , and that the halo closes. Then move the box off-centre vertically and explain what happens to the floor–ceiling sheet's hole. - Practical exerciseDifficulty 3 of 3The rod-GVG in the Workbench (stretch)
Implement the rod-GVG of Choset §5.4: for a rod at as segment–polygon distance with
parry2d, its gradient in from the closest pair of points, and traced with the Lyapunov law over (, a matrix). Sample R-edges as rod placements tangent to Chapter 8's planar GVD, and render Choset Fig. 5.22's panels for the Workbench: the rod-GVG edges as swept placements, the R-edges, and the union in . Check that a short rod's is a single closed curve over (footnote 5) and find the rod length at which it splits.
References
- Choset, H., Lynch, K. M., Hutchinson, S., Kantor, G., Burgard, W., Kavraki, L. E., and Thrun, S. (2005) Principles of Robot Motion: Theory, Algorithms, and Implementations. MIT Press.link to Principles of Robot Motion: Theory, Algorithms, and Implementations (opens in a new tab)
Chapter 5, §5.3–5.5, is this chapter's source: the GVG and transversality (Fig. 5.17, Table 5.2), the HGVG and eq. (5.4), the Lyapunov tracing law eq. (5.5) and homing, the rod-HGVG, Canny's roadmap with Lemmas 5.5.1–5.5.2 and the slice lemma, and the OPP with the generalized gradient. Canny's roadmap and complexity bound are from Canny's The Complexity of Robot Motion Planning (MIT Press, 1988) and the OPP from Canny and Lin (1990), Choset's refs. 90–93.
- Choset, H. and Burdick, J. (2000) Sensor-Based Exploration: The Hierarchical Generalized Voronoi Graph. International Journal of Robotics Research 19(2), 96–125.doi:10.1177/02783640022066770 (opens in a new tab)
The HGVG in full: the GVG in R^m, its disconnection, second-order edges and periods, the connectivity argument this chapter cites rather than proves, and the sensor-based exploration procedure.
- Choset, H. and Nagatani, K. (2001) Topological Simultaneous Localization and Mapping (SLAM): Toward Exact Localization Without Explicit Localization. IEEE Transactions on Robotics and Automation 17(2), 125–137.doi:10.1109/70.928558 (opens in a new tab)
The explored GVG used as a topological map for localization: what the integration lab's graph becomes when odometry drifts.
- Schwartz, J. T. and Sharir, M. (1983) On the “Piano Movers” Problem II: General Techniques for Computing Topological Properties of Real Algebraic Manifolds. Advances in Applied Mathematics 4(3), 298–351.doi:10.1016/0196-8858(83)90014-3 (opens in a new tab)
The first general complete algorithm, by cylindrical algebraic decomposition, doubly exponential in the dimension — the bound Canny's roadmap improved to singly exponential.
- Reif, J. H. (1979) Complexity of the Mover's Problem and Generalizations. 20th Annual Symposium on Foundations of Computer Science (FOCS), 421–427.doi:10.1109/SFCS.1979.10 (opens in a new tab)
PSPACE-hardness of the generalized mover's problem: the lower bound that makes 'exact planning is expensive' a theorem rather than an observation (Appendix D).
- Clarke, F. H. (1990) Optimization and Nonsmooth Analysis. SIAM Classics in Applied Mathematics 5 (reprint of the 1983 Wiley edition).doi:10.1137/1.9781611971309 (opens in a new tab)
The generalized gradient as the convex hull of limiting gradients, and the first-order characterization of extrema of nonsmooth functions used for the OPP's slice maxima (Choset's ref. 114).
