Research / Traction & Stability
Control & State EstimationStaying upright on a wet slope
Wet grass on a grade is the worst surface a ground robot meets: low, shifting friction over ground that deforms underfoot, with a tip-over waiting at the edge of the envelope. Here is how a mower estimates its own grip and keeps its wheels — and itself — under control.
A mower can localize to the centimetre, plan a perfect boustrophedon path, and still end up sliding sideways down a dewy bank with its wheels spinning uselessly — or, worse, lying on its side in the ditch. Knowing where you are is only half of autonomy. The other half is knowing whether the ground will let you go where you intend, and whether the next metre of travel will keep the machine on its wheels. On dry pavement those questions are trivial. On wet grass pitched at fifteen degrees they are the whole problem.
This article works through how a ground robot estimates and controls its grip on a deformable, slippery surface, and how it keeps from tipping over. We build from the contact physics up to a working traction-control loop and a tip-over margin the planner can respect, with the equations and pseudocode you would actually implement. As with everything in NLR's research program, the machinery is domain-agnostic: the disturbance-estimation core that keeps a mower tracking through a slip event is the same one that holds a drone on station in a gust.
01Why wet grass on a slope is hard
Three difficulties stack on top of one another, and each makes the others worse.
- Friction is low and variable. A film of water and crushed plant cells between rubber and turf can drop the available traction coefficient from the ~0.8 of dry grass to 0.3 or less — and it changes metre to metre with shade, thatch, soil moisture, and how recently the mower's own wheels packed the ground. You cannot assume a number; you have to estimate it live.
- The surface deforms. Turf is not a rigid floor. Wheels sink, shear the top layer, and ride on a soil that yields. The contact is governed by terramechanics — soil mechanics under a wheel — not the clean Coulomb friction of a textbook block on a ramp. Thrust comes from shearing soil, not just from pressing on it.
- Gravity is trying to tip you over. On a grade, the centre of gravity hangs out past the downhill wheels. Add a slip-induced sideways slide, a hidden rut, or a hard turn, and the machine can pass from sliding to rolling. Rollover is the failure that does real damage, and it is the constraint that ultimately bounds where the robot is allowed to drive.
The throughline is that grip is a latent quantity — you never measure it directly, you infer it from how the robot moves relative to how you commanded it to move — and stability is a geometric constraint that the controller and planner must keep slack.
You cannot command traction you do not have. The job of a traction system is to estimate the grip the terrain is actually offering right now, keep the wheels operating in the part of the slip curve where that grip is greatest, and never let the commanded motion push the machine past its tip-over margin.
02A little terramechanics
The classical account of how a wheel develops force on deformable ground is terramechanics, codified in Wong's Theory of Ground Vehicles.1 Two stresses act in the contact patch: a normal pressure that holds the wheel up and a shear stress that drives it forward. The shear stress the soil can sustain follows the Mohr–Coulomb failure law,
$$ \tau(j) = \big(c + \sigma \tan\phi\big)\Big(1 - e^{-j/K}\Big), $$where \(c\) is soil cohesion, \(\phi\) the internal friction angle, \(\sigma\) the normal stress, \(j\) the shear displacement at that point of the contact, and \(K\) a shear-deformation modulus that sets how quickly thrust builds up with slip. Integrating \(\tau\) over the contact patch and subtracting the resistance from compacting and bulldozing soil gives the net drawbar pull — the usable tractive force the wheel delivers to move the robot.
You will not solve that integral on a mower in real time, and you should not try. The point of the model is qualitative and it is decisive: thrust grows with shear displacement, and shear displacement grows with slip. A wheel develops grip only by slipping a little. That single fact is why the right control variable is not torque or speed in isolation, but the slip ratio.
03Slip ratio and the traction curve
Define the slip ratio of a driven wheel by comparing the speed of its rim, \(\omega r\) (angular rate times effective radius), with the true forward ground speed \(v\) of its hub:
$$ i \;=\; \frac{\omega r - v}{\omega r}, \qquad i \in [0,1]\ \text{(driving)}. $$At \(i=0\) the wheel rolls perfectly: rim speed equals ground speed, no shearing, no thrust. At \(i=1\) the wheel spins in place (\(v=0\)) — maximum shearing, the machine going nowhere. Equivalently, the achieved ground speed is \(v = \omega r\,(1-i)\), so slip is a direct tax on how far each wheel revolution carries you. For a braking wheel the sign convention flips and slip is referenced to \(v\) instead, but the driving case is what a mower lives in.
Plot the developed traction coefficient \(\mu\) (tractive force divided by wheel load) against slip and you get the slip–traction curve, the central object of this whole field. Traction rises steeply from zero, reaches a peak \(\mu_{\max}\) at a modest slip \(i^\*\) — typically 0.1–0.2 on firm ground, often higher and flatter on loose or wet soil — and then falls away as the contact transitions from gripping to sliding. Everything to the right of the peak is wasted: more wheel speed, less forward motion, more torn turf.
04Estimating slip and the friction it implies
Slip is computable the moment you have two velocities: the wheel's rim speed and the hub's true ground speed. The rim speed is easy — wheel encoders give \(\omega\), and \(r\) is known (with a small correction for sinkage). The hard part is the true ground speed \(v\), because the wheel encoders themselves are corrupted by the very slip you are trying to measure. You need an independent velocity reference that does not pass through the driven wheels:
- GNSS Doppler / RTK velocity — a carrier-phase receiver reports ground velocity directly and accurately when it has a fix, and Doppler velocity is far more robust to multipath than position.
- Visual or visual-inertial odometry — the camera measures how the world flows past, giving body velocity that owes nothing to the wheels; it is the fallback under canopy where GNSS drops.
- A non-driven encoder or radar — a trailing castor or a Doppler ground-speed radar gives \(v\) with no slip of its own.
With \(\omega r\) from the wheels and \(v\) from one of those, slip falls straight out of the definition. And once you can observe both the slip and the tractive force you are commanding (estimated from motor current, since torque is roughly proportional to current), you can locate yourself on the slip–traction curve and read off an estimate of the available grip. Iagnemma, Kang, Shibly and Dubowsky showed that a simplified terramechanics model can be fit online by linear least squares to recover terrain parameters — effectively the cohesion and friction terms — from exactly these onboard signals.2 A pragmatic, lower-order version that NLR runs alongside the full estimator is a recursive estimate of the lumped traction coefficient
$$ \hat\mu_t \;=\; \frac{F_{x,t}}{F_{z,t}}\,, \qquad \hat\mu_t \leftarrow (1-\alpha)\,\hat\mu_{t-1} + \alpha\,\hat\mu_t, $$where \(F_{x}\) is the tractive force inferred from motor current, \(F_{z}\) the wheel's share of vehicle weight (resolved for the slope), and \(\alpha\) a forgetting factor. When measured slip climbs while \(\hat\mu\) stalls or drops, you are past the peak and the terrain has told you its limit — without any prior soil map.
Pseudocode — per-wheel slip & traction estimation
# Inputs per wheel, per tick (dt):
# omega : wheel angular rate from encoder [rad/s]
# r : effective rolling radius [m]
# v_grnd : TRUE ground speed (GNSS/VIO/radar) [m/s]
# i_motor : motor current -> torque -> Fx [A]
# Fz : normal load on this wheel [N]
def estimate_slip(omega, r, v_grnd, i_motor, Fz, mu_prev, ALPHA=0.2):
rim = omega * r
if abs(rim) < EPS: # wheel stopped: undefined
return 0.0, mu_prev
slip = (rim - v_grnd) / rim # i = (wr - v)/(wr)
slip = clamp(slip, -1.0, 1.0)
Fx = torque_const * i_motor / r # tractive force estimate
mu_inst = Fx / max(Fz, EPS) # instantaneous coeff.
mu = (1 - ALPHA)*mu_prev + ALPHA*mu_inst # low-pass
# slip high but traction not rising -> past the peak
past_peak = (slip > SLIP_HINT) and (mu <= mu_prev + MU_EPS)
return slip, mu, past_peak
05Reading the terrain: proprioceptive and visual
Estimating grip from motion is reactive — you learn the terrain by driving onto it. To anticipate, the robot classifies what it is on (and what is ahead) from two complementary channels.
Proprioceptive sensing feels the terrain through the robot's own body. Motor current carries the load and slip signature; the IMU and wheel structure pick up vibration whose spectrum is characteristic of the surface — smooth on packed soil, broadband and rough on gravel or matted grass. Brooks and Iagnemma demonstrated that the power spectral density of wheel-induced vibration, fed to a trained classifier, reliably separates terrain classes from onboard signals alone.3 The appeal is that proprioception measures the property you actually care about — how the ground responds to this robot — rather than how it looks.
Exteroceptive sensing looks ahead with cameras (and, where fitted, lidar). Vision predicts terrain class and geometry before the wheels arrive, flagging the dark wet patch, the slope break, the standing water. Its weakness is that appearance is an imperfect proxy for grip: lush green can be firm or a bog. The strong pattern, which NLR follows, is self-supervised fusion — let the reliable-but-late proprioceptive classifier label the terrain the robot just crossed, and use those labels to train the camera to recognize the same terrain at a distance. The robot teaches its eyes using its wheels.
Proprioception answers "what am I on, and how is it gripping?" (accurate, but only underfoot and after contact). Vision answers "what is coming?" (early, but only a guess at grip). Slip estimation turns the wheels themselves into a friction sensor. A robust robot runs all three and lets the slower, surer signals supervise the faster, riskier ones.
06The thing that actually hurts: rollover
Slipping wastes energy and tears turf; tipping over ends the mission and can hurt someone. So stability gets its own hard constraint. Consider the robot at rest on a lateral incline of angle \(\theta\), with centre of gravity height \(h\) above the contact plane and wheel track (or, for the downhill edge, half-track) such that the horizontal distance from the CoG to the downhill tip-over axis is \(d\). It begins to roll when the gravity vector falls outside the support polygon — when the overturning moment overcomes the restoring one:
$$ \underbrace{m g \sin\theta \cdot h}_{\text{overturning}} \;\ge\; \underbrace{m g \cos\theta \cdot d}_{\text{restoring}} \quad\Longrightarrow\quad \tan\theta \;\ge\; \frac{d}{h}. $$So the static rollover condition is simply \(\tan\theta_{\mathrm{crit}} = d/h\): the machine stays upright while \(\tan\theta < d/h\). For a symmetric vehicle of track width \(t\), \(d = t/2\) and the familiar static stability factor is \(\mathrm{SSF} = t/(2h)\) — wide and low is stable, tall and narrow is not. This is why mower platforms carry their batteries and motors as low as the wheels allow.
Static is the optimistic case. In motion you must subtract the destabilizing effects that eat the margin: lateral acceleration in a turn, the centrifugal demand \(v^2/R\) on a curve of radius \(R\), a downhill slide from slip that loads the lower wheels, and the sudden jolt of dropping into a rut. A practical dynamic stability margin tightens the static limit with these terms and a safety factor \(\gamma>1\):
$$ \tan\theta \;+\; \frac{a_{\text{lat}}}{g} \;\le\; \frac{1}{\gamma}\,\frac{d}{h}, \qquad a_{\text{lat}} = \frac{v^2}{R}. $$The controller treats the left-hand side as a live scalar — the fraction of the tip-over budget currently spent — and refuses commands that would drive it past the limit. Force-angle and zero-moment-point formulations make this rigorous for uneven ground and articulated suspensions,4 but the budget framing is what a field controller enforces every tick.
07Traction control by slip regulation
With slip observable and a target known, traction control is a regulation problem: drive each wheel's measured slip toward a setpoint \(i^\*\) placed just left of the curve's peak, where grip is maximal and still rising. When a wheel exceeds \(i^\*\) — it has broken loose and is spinning up — the controller reduces torque to that wheel until it bites again; when slip is below target, it can apply more. This is the ground-vehicle analogue of an ABS/TCS loop, and Iagnemma and Dubowsky showed that slip-regulating traction control measurably improves mobility for wheeled robots in rough terrain compared with naive velocity tracking.5
The setpoint itself should adapt: because the peak sits at higher slip on wet, loose ground than on firm ground, the estimator from §04 nudges \(i^\*\) toward wherever \(\hat\mu\) is presently maximized (a light extremum-seeking or a lookup keyed on the terrain class from §05). A simple, robust implementation is per-wheel PI on the slip error with a torque clamp, plus a fall-back to slow the whole platform when every wheel is saturating — the unambiguous signal that the terrain simply will not support the requested speed.
Pseudocode — per-wheel slip-regulating traction control
# Regulate measured slip to a target just left of the mu-peak.
# Runs per wheel; a supervisor scales v_cmd if all wheels saturate.
def traction_control(slip, mu, state, dt, i_star=0.12):
# adapt target toward where traction is maximized
i_star = adapt_target(i_star, mu, state) # extremum-seeking
err = i_star - slip # want slip == i_star
state.integ = clamp(state.integ + err*dt, -I_MAX, I_MAX)
d_torque = KP*err + KI*state.integ # PI on slip error
torque = clamp(state.torque + d_torque, 0, TORQUE_MAX)
# if the wheel is spinning up (slip past target), back off fast
if slip > i_star + SLIP_MARGIN:
torque = min(torque, BACKOFF * state.torque) # cut torque
state.torque = torque
saturated = (slip > i_star + SLIP_MARGIN)
return torque, saturated
# --- supervisor: stability + global speed governor ---
def supervise(wheels, theta, v, R, d, h, gamma=1.5):
budget = tan(theta) + (v*v / max(R, EPS)) / G # tip-over budget used
if budget >= (1/gamma) * (d / h): # rollover guard
return "SLOW_OR_REROUTE" # shed speed / turn radius
if all(w.saturated for w in wheels): # terrain won't hold v
return "REDUCE_SPEED"
return "OK"
08Folding slip into the estimator
Slip is not only something to control — it is a bias that corrupts localization. A robot dead-reckoning from wheel encoders on slippery grass will believe it has travelled farther than it has, because the encoders count rotations the ground did not honor. The clean fix is to make slip part of what the state estimator estimates. Augment the Extended Kalman Filter's state with a slip (or wheel-radius-effective) parameter \(\beta\) so the filter tracks pose and the multiplicative error between commanded and realized motion:
$$ \tilde x_t = \begin{bmatrix} p_x \\ p_y \\ \theta \\ \beta \end{bmatrix}, \qquad p_{x,t} = p_{x,t-1} + (1-\beta_{t-1})\,\omega r\,\Delta t\,\cos\theta_{t-1}, $$with \(\theta\) and \(p_y\) advancing analogously, and \(\beta\) modeled as a slowly varying random walk, \(\beta_t = \beta_{t-1} + \nu_t\). Now an absolute velocity or position update — from GNSS Doppler or VIO, the same drift-free references used to compute slip in the first place — corrects not just where the robot is but how much its wheels are slipping. The slip estimate and the pose estimate become mutually consistent, and the planner inherits a calibrated, terrain-aware odometry instead of one that quietly over-reports progress on every wet pass.
The bookkeeping is the standard EKF predict/correct recursion — \(\bar\Sigma_t = G_t\Sigma_{t-1}G_t^\top + R_t\) on prediction, a gated Kalman update on correction — now carrying the extra state. Inflate \(\beta\)'s process noise when proprioception reports rough or slipping terrain so the filter stays responsive exactly when slip is changing fastest.
09Planning around the steep wet cells
The cheapest slip event is the one you never drive into. Estimation and control are the inner loops; the outer loop is traversability-aware planning. NLR carries the lawn as a cost map whose cells are scored by slope (from the elevation map), estimated grip (from the proprioceptive history of earlier passes and the vision classifier), and surface wetness. The tip-over condition from §06 becomes a hard gate — any cell whose grade exceeds the platform's slope limit, derated for the current friction estimate, is impassable — while marginal cells carry a soft penalty that the planner pays only when it must.
The practical behaviours fall out naturally: traverse slopes along the contour rather than straight up the fall line, where a slide turns into a roll; avoid the shaded bank early in the morning when dew has not burned off; and slow into any cell where the slip history is poor. Because a mower revisits the same property continually, every pass refines the map — the robot learns which corner of which yard is treacherous after rain and routes around it before it ever spins a wheel.
10How this transfers to drones
Strip away the soil and the wheels and what remains is general: a robot estimating an unmodeled external force that is fighting its commanded motion, and acting to reject it before it loses control. That is precisely the problem an aerial robot solves against the wind.
Slip is to a mower what wind is to a drone — an unmodeled disturbance that pushes the vehicle off the motion you commanded, and that you must estimate to reject. The same tools port directly. A disturbance observer infers the external force (gust, ground effect, payload swing) from the gap between commanded and measured acceleration, exactly as slip is inferred from the gap between commanded and true ground velocity. Augmenting the state with a disturbance term — wind velocity for a drone, slip bias for a mower — is the identical trick from §08. And adaptive / robust control that retunes as the disturbance changes is the airborne sibling of the adaptive slip setpoint in §07: an adaptive controller raises its rejection authority into a gust the way the traction loop shifts its target into looser soil. The stability constraint even rhymes — a mower must keep the gravity vector inside its wheels; a multirotor must keep its thrust and tilt inside an envelope or it departs controlled flight. Learn to estimate and reject slip on the ground and you have learned to estimate and reject wind in the air.
This is the throughline of NLR's research program: the disturbance changes — slip, wind, a dragging payload — but the estimate-and-reject problem is one problem. Solve it well on a wet slope and you have solved it for the gust.
Sources & further reading
- Wong, J. Y. Theory of Ground Vehicles (5th ed.). John Wiley & Sons, 2022. The standard reference for terramechanics, the Mohr–Coulomb shear model, and drawbar pull as a function of slip.
- Iagnemma, K., Kang, S., Shibly, H., & Dubowsky, S. "Online Terrain Parameter Estimation for Wheeled Mobile Robots With Application to Planetary Rovers." IEEE Transactions on Robotics, 20(5), 921–927, 2004. doi:10.1109/TRO.2004.829462
- Brooks, C. A., & Iagnemma, K. "Vibration-Based Terrain Classification for Planetary Exploration Rovers." IEEE Transactions on Robotics, 21(6), 1185–1191, 2005. Origin of the proprioceptive (vibration PSD) terrain-classification approach.
- Papadopoulos, E., & Rey, D. A. "A New Measure of Tipover Stability Margin for Mobile Manipulators." IEEE International Conference on Robotics and Automation (ICRA), 1996. The force-angle stability margin for rollover on uneven ground.
- Iagnemma, K., & Dubowsky, S. "Traction Control of Wheeled Robotic Vehicles in Rough Terrain with Application to Planetary Rovers." The International Journal of Robotics Research, 23(10–11), 1029–1040, 2004. doi:10.1177/0278364904047392