Features in visual SLAM and VIO
Visual SLAM and visual-inertial odometry (VIO) work with features too, but each part of the range, bearing and signature triple of the landmark model changes. A monocular camera does not measure range. A keypoint at pixel fixes only the ray from the camera through the landmark. Multiplying by the inverse intrinsics, , turns the pixel into a direction in 3D, a bearing in both azimuth and elevation. The landmarks are 3D points , and the measurement model is the pinhole projection of the point into a camera with rotation and position : The division by depth in is why one view gives no range. The residual is the reprojection error, in pixels. A stereo pair measures the disparity between its two images, which gives depth, and an RGB-D camera measures depth at each pixel. With a single camera, a new landmark is triangulated from two or more views taken far enough apart, and the map is known only up to scale. VIO adds an IMU, whose accelerometer fixes the metric scale and the direction of gravity. The signature becomes a descriptor computed from the image patch around the keypoint, such as a 256-bit ORB descriptor or a 128-dimensional SIFT descriptor. A descriptor resembles its landmark but does not name it. Two corners can look alike, and one corner looks different from another viewpoint. The correspondences are therefore unknown. They come from matching descriptors, or from tracking patches from frame to frame, and the wrong matches are removed geometrically, for example with RANSAC on the essential matrix. The rest of this section builds this pipeline. A frame also has hundreds of keypoints rather than a few landmarks, which changes how the estimators are built. Filter-based VIO such as the MSCKF keeps a window of past camera poses in its state but not the points. Each point is triangulated when its track ends and then constrains only the poses. Optimization-based systems such as ORB-SLAM adjust the keyframe poses and the points together to minimize the reprojection error, which is bundle adjustment. VINS-Mono does the same over a sliding window and adds IMU terms between keyframes.The scene
The camera moves around a circle of radius 1.5 m in a 6 m by 6 m room, 0.5 m above the floor and looking along its direction of travel. It records 60 keyframes on the way, about 16 cm apart, and a 61st that repeats the pose of the first, so the loop closes. The room holds 1500 points: half on the walls and half on furniture spread through the room, kept at least 0.5 m away from the path. The camera has the nominal intrinsics of the real D435i color camera from the course’s camera configuration, px and principal point (321, 240) in a 640 by 480 image, and the same optical frame as the VIO section: forward, right, down. Each keyframe records the pixels of the points in its view with one pixel of noise. Matching is by point index, the stand-in for a feature descriptor. To imitate wrong descriptor matches, 5% of each keyframe’s pixels are replaced by a random pixel, so about one match in ten between two keyframes is wrong.Motion between two views
Two views of the same points satisfy the epipolar constraint from the stereo section. With calibrated cameras it involves the essential matrix, where are normalized image coordinates and moves points from camera to camera . Five matches determine . A wrong match ruins any estimate it takes part in, so the estimate is wrapped in RANSAC, as in the homographies section. RANSAC repeatedly fits to five random matches, counts the matches within 3 pixels of their epipolar line, and keeps the fit with the most. yields four candidate motions, from two rotations and two signs of . Only one of them puts the triangulated points in front of both cameras, andrecoverPose picks that one. The translation comes out with unit length: the images do not contain the length of the baseline, because the same pictures result from a scene twice as large viewed by a camera that moved twice as far. With and fixed, each inlier match is triangulated into a 3D point in camera ‘s frame.
Visual odometry
Chaining the two-view estimates gives visual odometry. The first pair’s baseline defines the unit of length. Every later pair also returns a unit translation, so its length is rescaled to keep the map consistent: points seen by the pair before and by the current pair must come out at the same distance from the shared camera, and the median ratio of the two distances sets the scale. The functionate measures the result. It finds the similarity, a rotation, a translation and a scale, that best aligns the estimated camera positions with the true ones, and reports the remaining root-mean-square distance, the absolute trajectory error.
Loop closure
At the last keyframe the camera is back at its starting pose. A real system recognizes this from the images, typically by comparing a bag-of-words summary of each keyframe’s descriptors. Here the shared point indices reveal it directly: most points in view were already mapped near the start. The function below relocalizes the last keyframe against that early map. Given known 3D points and their pixels, the camera pose follows from Perspective-n-Point (PnP), again wrapped in RANSAC. The same points, triangulated by the last pair of the chain, give the scale drift. Their distances from the camera in the chain’s units, compared with their distances in the units of the start map, show how far the unit of length has drifted around the loop.Pose graph optimization
The loop measurement disagrees with the chain, and the error has to be spread over all the keyframes instead of being dumped on the last one. A pose graph does this. Each keyframe is a node with a pose and a scale, a similarity transform in Sim(3). Each consecutive pair of keyframes is joined by an edge that holds their relative motion from visual odometry, at unchanged scale. The loop closure adds one more edge, from keyframe 0 to the last keyframe, carrying the PnP pose and the measured scale drift. The optimizer moves the nodes to minimize the total disagreement with all the edges, keeping keyframe 0 fixed. Each odometry edge gives way a little, and the loop edge is satisfied. Sim(3) rather than the rigid motions of SE(3) is the choice for a single camera: the scale drift is a real error in the chain, and only a node with its own scale can absorb it.The same steps in StellaVSLAM
StellaVSLAM, the maintained fork of OpenVSLAM, splits the work into three modules (Sumikura et al., 2019):
In the course’s turtlebot-maze repository,
slam/slam_bridge.py takes the simulated D435i’s color images, and in RGB-D mode its depth images, and streams them to slam/run_slam.cc, which feeds them to StellaVSLAM and returns the pose of every frame. The assignment’s Task 1 builds the front end of this section on real KITTI images, where finding and matching the features is the hard part. Task 2 runs StellaVSLAM on video of your own room.
Key references: (Sumikura et al., 2019; Corke, 2023)
References
- Corke, P. (2023). Robotics, vision and control: Fundamental algorithms in python.
- Sumikura, S., Shibuya, M., Sakurada, K. (2019). OpenVSLAM: A versatile visual SLAM framework. arXiv [cs.CV].
Found an error on this page? Report an issue.

