Rear-Wheel Drive (RWD) Kinematics

Forward and inverse kinematics for rear-wheel drive robots with front-wheel steering.

Overview

Rear-Wheel Drive (RWD) has driven wheels at the rear and steered wheels at the front, like many trucks and sports cars.

Advantages:

  • Better weight distribution
  • Good for pushing/towing
  • Better acceleration (weight transfer)
  • Simpler drivetrain

Disadvantages:

  • Can oversteer (tail slides out)
  • Less intuitive than FWD
  • Potential for fishtailing
  • Cannot rotate in place

Robot Configuration

1        Front (Steered only)
2              ↑
3         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
4         β”‚ β•±     β•² β”‚  ← Steered wheels (passive)
5         β”‚         β”‚
6         β”‚    β€’    β”‚  ← Center of rotation
7         β”‚         β”‚
8         β”‚ β–      β–  β”‚  ← Rear wheels (driven)
9         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Parameters:

  • $L$: Wheelbase (distance between front and rear axles)
  • $\delta$: Front steering angle
  • $v$: Linear velocity at rear axle
  • $r$: Wheel radius

Interactive RWD Simulator


Forward Kinematics

RWD Equations

For RWD, the velocity reference is at the rear axle:

$$ \omega = \frac{v \sin\delta}{L} $$

$$ R = \frac{L}{\sin\delta} $$

Where:

  • $v$: Velocity at rear axle
  • $\delta$: Front steering angle
  • $L$: Wheelbase

Pose Update

$$ \dot{x} = v \cos\theta $$

$$ \dot{y} = v \sin\theta $$

$$ \dot{\theta} = \omega = \frac{v \sin\delta}{L} $$

Note: Position $(x, y)$ is at the rear axle, not the center!

Python Implementation

 1import numpy as np
 2
 3class RearWheelDrive:
 4    def __init__(self, wheelbase=0.5, wheel_radius=0.1):
 5        """
 6        Args:
 7            wheelbase: Distance between front and rear axles (m)
 8            wheel_radius: Radius of wheels (m)
 9        """
10        self.L = wheelbase
11        self.r = wheel_radius
12        
13        # State: [x, y, theta] at rear axle
14        self.state = np.array([0.0, 0.0, 0.0])
15    
16    def forward_kinematics(self, v, delta, dt):
17        """
18        Update robot pose from velocity and steering angle
19        
20        Args:
21            v: Linear velocity at rear axle (m/s)
22            delta: Front steering angle (rad)
23            dt: Time step (s)
24        
25        Returns:
26            Updated pose [x, y, theta] at rear axle
27        """
28        x, y, theta = self.state
29        
30        # Calculate angular velocity
31        if abs(delta) < 1e-6:
32            omega = 0
33        else:
34            omega = v * np.sin(delta) / self.L
35        
36        # Update pose (rear axle position)
37        x += v * np.cos(theta) * dt
38        y += v * np.sin(theta) * dt
39        theta += omega * dt
40        
41        # Normalize angle
42        theta = np.arctan2(np.sin(theta), np.cos(theta))
43        
44        self.state = np.array([x, y, theta])
45        return self.state.copy()
46    
47    def get_front_position(self):
48        """Get front axle position"""
49        x, y, theta = self.state
50        x_front = x + self.L * np.cos(theta)
51        y_front = y + self.L * np.sin(theta)
52        return x_front, y_front
53    
54    def get_turning_radius(self, delta):
55        """Calculate turning radius for given steering angle"""
56        if abs(delta) < 1e-6:
57            return float('inf')
58        return self.L / np.sin(delta)
59
60# Example
61robot = RearWheelDrive(wheelbase=0.5, wheel_radius=0.1)
62
63# Straight line
64for _ in range(100):
65    robot.forward_kinematics(v=1.0, delta=0, dt=0.01)
66
67print(f"After straight motion (rear axle): {robot.state}")
68print(f"Front axle position: {robot.get_front_position()}")

Inverse Kinematics

From Desired Path to Control Inputs

Given desired turning radius $R$ and velocity $v$:

$$ \delta = \arcsin\left(\frac{L}{R}\right) $$

Implementation

 1def inverse_kinematics(self, v_desired, R_desired):
 2    """
 3    Compute steering angle for desired turning radius
 4    
 5    Args:
 6        v_desired: Desired linear velocity at rear axle (m/s)
 7        R_desired: Desired turning radius (m)
 8    
 9    Returns:
10        (v, delta): velocity and steering angle
11    """
12    if abs(R_desired) > 1000:  # Effectively straight
13        delta = 0
14    else:
15        # Ensure R is achievable
16        if abs(R_desired) < self.L:
17            R_desired = self.L * np.sign(R_desired)
18        
19        delta = np.arcsin(self.L / R_desired)
20    
21    return v_desired, delta
22
23# Add to RearWheelDrive class
24RearWheelDrive.inverse_kinematics = inverse_kinematics
25
26# Example
27robot = RearWheelDrive(wheelbase=0.5)
28v, delta = robot.inverse_kinematics(v_desired=1.0, R_desired=2.0)
29print(f"For R=2m: v={v:.2f} m/s, Ξ΄={np.degrees(delta):.1f}Β°")

RWD vs FWD Comparison

AspectRWDFWD
Reference PointRear axleCenter/Front axle
Kinematics$\omega = \frac{v\sin\delta}{L}$$\omega = \frac{v\tan\delta}{L}$
Turning Radius$R = \frac{L}{\sin\delta}$$R = \frac{L}{\tan\delta}$
StabilityCan oversteerMore stable
ReversingMore challengingEasier
TowingBetterWorse

Oversteer Behavior

Understanding Oversteer

RWD vehicles can oversteer when:

  • Reversing with steering input
  • High speed turns
  • Slippery surfaces
 1def check_oversteer_risk(self, v, delta, friction_coef=0.7):
 2    """
 3    Check for potential oversteer conditions
 4    
 5    Args:
 6        v: Velocity
 7        delta: Steering angle
 8        friction_coef: Surface friction coefficient
 9    
10    Returns:
11        (risk_level, warning)
12    """
13    # Calculate lateral acceleration
14    if abs(delta) < 1e-6:
15        return 'low', None
16    
17    R = self.get_turning_radius(delta)
18    lateral_accel = v**2 / abs(R)
19    max_accel = friction_coef * 9.81
20    
21    risk_ratio = lateral_accel / max_accel
22    
23    if risk_ratio > 0.9:
24        return 'high', 'Severe oversteer risk!'
25    elif risk_ratio > 0.7:
26        return 'medium', 'Moderate oversteer risk'
27    elif risk_ratio > 0.5:
28        return 'low', 'Slight oversteer possible'
29    else:
30        return 'minimal', None
31
32# Add to class
33RearWheelDrive.check_oversteer_risk = check_oversteer_risk

Reversing Control

Special Considerations for Reverse

When reversing, RWD behaves differently:

 1def reverse_control(self, v_reverse, target_x, target_y):
 2    """
 3    Control for reversing (more challenging than forward)
 4    
 5    Args:
 6        v_reverse: Reverse velocity (negative)
 7        target_x, target_y: Target position
 8    
 9    Returns:
10        Steering angle
11    """
12    x, y, theta = self.state
13    
14    # Vector to target
15    dx = target_x - x
16    dy = target_y - y
17    
18    # Desired heading (opposite for reverse)
19    target_theta = np.arctan2(dy, dx) + np.pi
20    
21    # Heading error
22    theta_error = np.arctan2(np.sin(target_theta - theta),
23                             np.cos(target_theta - theta))
24    
25    # Proportional control (reversed sign for reverse motion)
26    delta = -np.clip(theta_error, -np.pi/4, np.pi/4)
27    
28    return delta
29
30# Add to class
31RearWheelDrive.reverse_control = reverse_control

Trailer Towing

RWD is better for towing because the driven wheels push the load:

 1def towing_kinematics(self, v, delta, trailer_length, dt):
 2    """
 3    Kinematics with trailer attached
 4    
 5    Args:
 6        trailer_length: Length from hitch to trailer axle
 7        
 8    Returns:
 9        (robot_pose, trailer_angle)
10    """
11    # Update robot
12    self.forward_kinematics(v, delta, dt)
13    
14    # Trailer angle (simplified model)
15    x, y, theta = self.state
16    
17    # Hitch is at rear axle
18    # Trailer follows with its own angle
19    
20    return self.state, None  # Simplified

Advantages and Applications

Advantages

  • Better towing: Push force more effective
  • Weight distribution: Better for heavy loads
  • Acceleration: Weight transfer to driven wheels
  • Durability: Simpler drivetrain

Applications

  • Towing robots: Pulling carts/trailers
  • Heavy-duty platforms: Construction/industrial
  • Forklift AGVs: Pushing/pulling loads
  • Outdoor robots: Rough terrain with loads

Further Reading

Related Snippets