The D435i IMU
The constants below are the ones the course simulator gives the D435i’s IMU. The white noise comes from the BMI055 noise densities, 0.014 °/s/√Hz for the gyroscope and 150 µg/√Hz for the accelerometer, converted to one sample at 200 Hz. The real camera streams the gyroscope at 200 Hz and the accelerometer at 63 Hz by default (librealsense); the simulator runs both at 200 Hz, and so does this section. Each bias has two parts. A constant part is drawn when the sensor powers on, with a standard deviation of 5 mrad/s for the gyroscope and 0.05 m/s² for the accelerometer. A second part wanders slowly as a first-order Gauss-Markov process, which decays toward zero with a time constant of a few hundred seconds while noise keeps pushing it. These bias values were chosen to make the drift visible within a minute, not taken from a datasheet.The scene
The TurtleBot drives the loop of the IMU section, a circle of radius 1.5 m at 0.2 m/s for 60 s, with the camera 20 cm above the floor. The room’s walls are 4 m from the center, and 240 points on them, up to 2.5 m high, form a map that the robot already has. Each camera frame sees some of these points, and the filter knows which map point each pixel belongs to. Building that map and finding those correspondences is the work of SLAM and of the visual SLAM section. This section isolates the fusion of the two sensors. The code below generates the true motion, the true biases and the IMU readings, and then integrates the readings with no correction, as in the IMU section.The camera measurement
The camera is the D435i’s color camera, with the nominal intrinsics of the real camera from the course’s camera configuration: px and the principal point at (321, 240) in a 640 by 480 image. The camera’s optical frame has forward, right and down, while the robot’s body frame has forward, left and up. The fixed rotation maps one to the other. A map point appears at the pixel The camera sees a point if it lies at least 0.3 m in front of it, within 6 m, and inside the image. The filter uses up to 15 visible points per frame, five frames a second, each with one pixel of noise.An error-state Kalman filter
An EKF linearizes around its estimate and adds a correction vector to it. That works for position, velocity and biases, but a rotation matrix cannot be corrected by adding to it. The error-state filter separates the two jobs. It keeps a nominal estimate that it propagates with the full nonlinear model, and a small error vector with covariance . The orientation error is a rotation vector applied on the right, , so it lives in the body frame where the gyroscope measures.Prediction
For each IMU sample, the filter subtracts the estimated biases and integrates as in the IMU section: The error grows according to the Jacobian of this step. Its nonzero blocks say that an orientation error rotates with the body, a gyroscope bias error turns into an orientation error, a velocity error turns into a position error, and an orientation error rotates the measured specific force and so becomes a velocity error: The covariance prediction is , where holds the white noise of the two sensors and the random walk of the two biases. The filter models each bias as a random walk, while the simulated bias decays slowly toward its power-on value; over one minute the difference is negligible.Correction
At each camera frame the filter stacks the pixel residuals of all the points it sees. Differentiating with gives the two nonzero blocks of the measurement Jacobian, where is the Jacobian of the pinhole projection. The biases and the velocity have no direct effect on a pixel. The filter learns them only through their correlation with the pose in . The update is the usual Kalman update with . The estimated error is then folded into the nominal state, the rotation by , and reset to zero. Theproject function returns both the pixel and the Jacobian.
Running VIO
The filter starts from the true pose and velocity, and with both bias estimates at zero, with a covariance equal to the spread of the true biases.From this filter to VIO in practice
The filter here had a map. A real VIO system builds its landmarks as it goes, by tracking image features over several frames and triangulating them, which is the front end of the visual SLAM section. Systems such as MSCKF keep a short window of past camera poses in the filter state instead of the landmarks, and ORB-SLAM3 optimizes the IMU and camera terms together over a window of keyframes (Campos2020-xm). In the course simulator the same two inputs exist as ROS topics. The camera’s IMU publishes on/camera/imu with the noise and drifting bias described above, in the frame camera_imu_optical_frame, and the color images arrive on /camera/color/image_raw. The simulated camera is smaller than the real one, 320 by 240 pixels with a 60° horizontal field of view, so its focal length is about 277 px and its principal point (160, 120); a filter run in the maze needs those intrinsics.
Key references: (Corke, 2023; Campos2020-xm)
References
- Corke, P. (2023). Robotics, vision and control: Fundamental algorithms in python.
Found an error on this page? Report an issue.

