Perception-Based Localization
Pose Engine
Offline and online 6DoF pose and odometry from lidars and/or cameras. GNSS-independent. Accurate, precise, and deterministic.
Why it matters
GNSS isn't a reliable solution.
Urban canyons, solar events, and spoofing/jamming degrade GNSS accuracy, often without a valid quality indicator. Pose Engine localizes to a map using perception sensors, with no dependency on satellite signals.
Mapping with lidars or cameras; localization with same plus IMU and encoders. No satellite signal, RTK base station, or environment modification required.
Maps are long-term reliable in dynamic environments with third-party movers and seasonal changes.
Every robot (including different types) localizes to the same map. Maps are modular; updates and distribution occur only on regions that change. Localization is consistent.
How it works
Offline: Collect data, get pose.
No special motion required. Collect and upload sensor data, get back a 6DoF trajectory for each body-attached frame of interest.
Capture data from all sensors (lidars, cameras, radars, IMUs, encoders, GNSS and/or INS units) during normal robot operation. If the robot has not been recently calibrated, collect calibration data immediately before or after.
For Pose-as-a-Service with human review, upload the sensor data via the Data Portal API.
For local offline pose generation, invoke the Docker file with a path to the data.
Receive CSV files per selected sensor coordinate frame: local map pose with body-frame velocities, and ECEF pose if GNSS is included in the sensor data.
Online: Map, bootstrap, localize.
Collect data and build a map of the site. Bootstrap the robot into the map upon initialization. Move within the mapped area and get odometry and pose.
Move one or more data collection vehicles throughout the site. Capture sensor data from all sensors (lidars, cameras, radars, IMUs, encoders, GNSS and/or INS units). Build a map.
Using a hint for starting pose from last known pose, GNSS of any quality, fiducial markers, or even the scene itself, determine the initial robot pose for a new localization session.
Get high-frequency, low-latency 6DoF map-relative pose and odometry in whatever representation, message, and channel required by your autonomy stack.
Pose Engine offline outputs
Pose trajectory for annotation and labelling pipelines.
Pose for each sensor coordinate frame. ECEF pose included if GNSS data is provided. Same rigid-transform convention throughout; the local file also carries body-frame velocities.
# world-from-body rigid transform, body-frame velocities # world frame: local map origin (set at Platform Setup) # <customer>_<log-id>_<sensor-cf>.local.csv time_s, px_m, py_m, pz_m, rx_rad, ry_rad, rz_rad, vx_mps, vy_mps, vz_mps, wx_rps, wy_rps, wz_rps 1776371688.261120081, -0.991453, -13.979609, 0.898994, -0.013059700, -0.004910992, -0.945530403, 0.007306, -0.004017, 0.001259, -0.000613, -0.000246, 0.001082 1776371688.271120071, -0.991448, -13.979691, 0.899010, -0.013065724, -0.004917313, -0.945524474, 0.006687, -0.004729, 0.001629, 0.000016, -0.001170, 0.000193
| time_s | Time of validity (seconds) |
| px_m, py_m, pz_m | Position in local map frame (meters) |
| rx_rad, ry_rad, rz_rad | Rotation as so(3) logarithm; see Rotation note tab |
| vx_mps, vy_mps, vz_mps | Body-frame linear velocity: +X forward, +Y left, +Z up (m/s) |
| wx_rps, wy_rps, wz_rps | Body-frame angular velocity: roll, pitch, yaw rate (rad/s) |
# world-from-body rigid transform # world frame: ECEF (only available if GNSS data is provided) # <customer>_<log-id>_<sensor-cf>.ecef.csv time_s, px_m, py_m, pz_m, rx_rad, ry_rad, rz_rad 1776371688.261120081, -2687738.311, -4291128.930, 3865469.473, 0.968923418, 0.190917898, -1.392946097 1776371688.301120043, -2687738.311, -4291128.931, 3865469.473, 0.968897924, 0.190896033, -1.392959755
| time_s | Time of validity (seconds) |
| px_m, py_m, pz_m | Position in ECEF frame (meters) |
| rx_rad, ry_rad, rz_rad | Rotation as so(3) logarithm; see Rotation note tab |
Rotation is stored as the so(3) logarithm (axis-angle vector form). The norm of [rx, ry, rz] is the rotation angle in radians; the unit vector is the axis of rotation.
# Recover rotation matrix R from axis-angle vector w = [rx, ry, rz] import numpy as np def rodrigues(w): t = np.linalg.norm(w) if t < 1e-9: return np.eye(3) skew = np.array([[ 0, -w[2], w[1]], [ w[2], 0, -w[0]], [-w[1], w[0], 0]]) return np.eye(3) + np.sin(t)/t*skew + (1-np.cos(t))/t**2 * skew@skew # Equivalent library calls: # scipy.spatial.transform.Rotation.from_rotvec(w).as_matrix() # kornia.geometry.conversions.angle_axis_to_rotation_matrix(w) # pypose.mat_from_rotvec(w) # Apply the transform: # xyz_world = R @ xyz_body + p
What makes it different
Built for mission-critical production deployment.
CPU-only. No GPU, no inference. 3–4 cores on Jetson Orin or equivalent. Auditable, reproducible results.
Modular spatial chunks. Multi-agent map contributions from heterogeneous platforms. Maps can be updated without full reprocessing.
Map support and localization quality metrics provide context for reliable "trust when present" outputs.
Accurate extrinsics, intrinsics, and time offsets from Calibration Anywhere directly improve localization accuracy.
Supported sensors
Mapping with lidars or cameras;
localization from same + IMU and/or encoders.
- RGB, multispectral
- Stereo, depth (stereo or indirect ToF)
- Rolling shutter and global shutter
- Fisheye, wide-angle, narrow-angle, catadioptric, pinhole
- 3D mechanical scanning, fixed, and flash lidars
- Pulse or FMCW (doppler) modulation
- 3DoF gyro + 3DoF accelerometer
- Wheel encoders (shaft ticks or wheel speeds)
- One or more receivers
- With or without RTK corrections
- Any reported pose or position estimates
Deployment options
From Pose-as-a-Service to production localization.
Start with offline pose generation in the cloud to build ground truth, fix annotation pipelines, and train better models. Bring that same solution on-prem to run locally on stored data. Deploy online when you're ready to replace your localization stack.
- Upload sensor data to Data Portal
- Typical TAT: 1-2 business days with human review
- Suitable for ground truth generation, annotation and labelling pipelines, and ML model training
- Invoke Docker container with attached sensor data
- Typical TAT: minutes to hours, depends on the data size
- Suitable for ground truth generation, annotation and labelling pipelines, and ML model training
- 3–4 cores, CPU only, Jetson Orin or equivalent
- Configurable output rate, format, and quality signals
- Supports air-gapped environments
- Suitable for production deployments
See it work for your robot.
Share sensor data; we'll send you a free pose result. No commitment, no engineers required on your end.
Get a free offline pose trajectory