Coordinate Systems
Coordinate frame definitions for the AV2.
Overview
The AV2 uses several coordinate systems. Understanding these frames and their transformations is essential for correct operation.
Frame Summary
Frame |
X-axis |
Y-axis |
Z-axis |
|---|---|---|---|
Vehicle |
Forward |
Left |
Up |
World (UTM) |
East |
North |
Up |
LIDAR |
Forward |
Left |
Up |
Camera |
Right |
Down |
Forward |
Grid |
Forward |
Left |
N/A (2D) |
Vehicle Frame
The primary reference frame for the vehicle, following ISO 8855 convention.
Definition
Origin: Center of rear axle, at ground level
X-axis: Points forward (positive ahead)
Y-axis: Points left (positive to left)
Z-axis: Points up (positive upward)
Z (up)
│
│
│
Y (left) │
◄───────┼───────► -Y (right)
│
│
│
▼ -Z (down)
(top view)
Y (left)
│
│
▼
─────────────────────
│ │
│ │
│ X │──────► X (forward)
│ (origin) │
│ ● │
─────────────────────
Usage
Sensor mounting positions
Point cloud output (after transformation)
Control commands (steering angle, velocity)
World Frame (UTM)
The global reference frame for navigation.
Definition
Origin: UTM zone reference point
X-axis: East (positive eastward)
Y-axis: North (positive northward)
Z-axis: Up (positive upward)
This is an East-North-Up (ENU) coordinate system.
UTM Projection
GPS coordinates (WGS84 latitude/longitude) are converted to UTM meters:
from pyproj import Transformer
# WGS84 to UTM Zone 11N (Southern California)
transformer = Transformer.from_crs("EPSG:4326", "EPSG:32611")
lat, lon = 34.0577, -117.8215 # Cal Poly Pomona
east, north = transformer.transform(lat, lon)
# Result: east=427859.2, north=3769432.1 meters
Vehicle Heading
Heading (yaw) is measured from North, clockwise positive:
0° = Facing North
90° = Facing East
180° = Facing South
270° = Facing West
North (0°)
│
│
West (270°)──┼──► East (90°)
│
│
South (180°)
LIDAR Frame
The Velodyne VLP-16 sensor frame.
Definition
Origin: Center of LIDAR sensor
X-axis: Forward (cable pointing backward)
Y-axis: Left
Z-axis: Up
Note
The LIDAR frame is aligned with the vehicle frame when properly mounted.
Transformation
Points from LIDAR frame to vehicle frame:
# LIDAR mounted at (0.3, 0, 1.8) relative to vehicle origin
def lidar_to_vehicle(points_lidar):
# points_lidar: Nx3 array [x, y, z]
translation = np.array([0.3, 0.0, 1.8])
points_vehicle = points_lidar + translation
return points_vehicle
Camera Frame
Standard computer vision (OpenCV) camera frame.
Definition
Origin: Camera optical center
X-axis: Right (positive rightward in image)
Y-axis: Down (positive downward in image)
Z-axis: Forward (positive into scene)
Camera Frame:
──────────────────────
│ ●───────► X (right) │
│ │ │
│ │ │
│ ▼ Y (down) │
│ │
──────────────────────
Image Plane
Z points out of camera (into scene)
Transformation to Vehicle Frame
# Camera frame to vehicle frame rotation
# Camera: X-right, Y-down, Z-forward
# Vehicle: X-forward, Y-left, Z-up
R_cam_to_vehicle = np.array([
[0, 0, 1], # Vehicle X = Camera Z
[-1, 0, 0], # Vehicle Y = -Camera X
[0, -1, 0] # Vehicle Z = -Camera Y
])
def camera_to_vehicle(points_camera, R, t):
"""Transform points from camera to vehicle frame."""
points_vehicle = (R @ points_camera.T).T + t
return points_vehicle
Occupancy Grid Frame
The 2D grid used for obstacle mapping.
Definition
Origin: Vehicle center (can be offset)
X-axis: Forward
Y-axis: Left
Resolution: Configurable (default 0.1 m/cell)
Grid Frame (top-down view):
Y (columns, left)
▲
│
│
│
├───────────────────► X (rows, forward)
(0,0)
Grid indices:
- Row 0 = rear of grid
- Column 0 = right side of grid
Grid to World Transformation
def grid_to_world(grid_x, grid_y, vehicle_x, vehicle_y, vehicle_heading):
"""Convert grid coordinates to world coordinates."""
# Grid to vehicle frame
veh_x = (grid_x - grid_center_x) * resolution
veh_y = (grid_y - grid_center_y) * resolution
# Vehicle to world (rotate by heading)
cos_h = np.cos(vehicle_heading)
sin_h = np.sin(vehicle_heading)
world_x = vehicle_x + veh_x * cos_h - veh_y * sin_h
world_y = vehicle_y + veh_x * sin_h + veh_y * cos_h
return world_x, world_y
Common Transformations
GPS to Vehicle Relative
Convert a GPS waypoint to vehicle-relative coordinates:
def gps_to_vehicle_relative(waypoint_lat, waypoint_lon,
vehicle_lat, vehicle_lon,
vehicle_heading):
# Convert both to UTM
wp_x, wp_y = gps_to_utm(waypoint_lat, waypoint_lon)
veh_x, veh_y = gps_to_utm(vehicle_lat, vehicle_lon)
# Relative position in world frame
dx = wp_x - veh_x
dy = wp_y - veh_y
# Rotate to vehicle frame
cos_h = np.cos(-vehicle_heading)
sin_h = np.sin(-vehicle_heading)
rel_x = dx * cos_h - dy * sin_h # Forward
rel_y = dx * sin_h + dy * cos_h # Left
return rel_x, rel_y
LIDAR Point to World
Transform a LIDAR point to world coordinates:
def lidar_to_world(point_lidar, vehicle_pose):
"""
point_lidar: [x, y, z] in LIDAR frame
vehicle_pose: [x, y, heading] in world frame
"""
# LIDAR to vehicle
lidar_offset = [0.3, 0.0, 1.8]
point_vehicle = point_lidar + lidar_offset
# Vehicle to world
veh_x, veh_y, heading = vehicle_pose
cos_h = np.cos(heading)
sin_h = np.sin(heading)
world_x = veh_x + point_vehicle[0] * cos_h - point_vehicle[1] * sin_h
world_y = veh_y + point_vehicle[0] * sin_h + point_vehicle[1] * cos_h
world_z = point_vehicle[2]
return [world_x, world_y, world_z]
Reference Standards
ISO 8855: Road vehicles — Vehicle dynamics and road-holding ability — Vocabulary
REP 103: ROS Standard Units of Measure and Coordinate Conventions
UTM: Universal Transverse Mercator coordinate system