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
| Aspect | RWD | FWD |
|---|---|---|
| Reference Point | Rear axle | Center/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}$ |
| Stability | Can oversteer | More stable |
| Reversing | More challenging | Easier |
| Towing | Better | Worse |
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
- Denavit-Hartenberg (DH) Parameters
Denavit-Hartenberg convention for systematically describing robot manipulator β¦ - DH Parameter Examples and Common Configurations
Practical examples of DH parameter configurations for common robot manipulators β¦ - Four-Wheel Independent Drive Kinematics
Forward and inverse kinematics for four-wheel independent drive robots with β¦ - Front-Wheel Drive (FWD) Kinematics
Forward and inverse kinematics for front-wheel drive robots with Ackermann β¦ - Jacobian Matrices for Forward and Inverse Kinematics
Jacobian matrices relate joint velocities to end-effector velocities, essential β¦ - Mecanum Wheel Kinematics
Forward and inverse kinematics for mecanum wheel robots, enabling β¦ - Two-Wheel Balancing Robot Kinematics and Control
Kinematics and control for two-wheel self-balancing robots (inverted pendulum on β¦ - Two-Wheel Differential Drive Robot Kinematics
Forward and inverse kinematics for two-wheel differential drive robots, the most β¦