Fix createPoses

release/4.3a0
Frank Dellaert 2024-10-28 08:55:49 -07:00
parent d48b1fc840
commit 26a3728d80
6 changed files with 52 additions and 20 deletions

View File

@ -56,7 +56,7 @@ std::vector<Point3> createPoints() {
/** /**
* Create a set of ground-truth poses * Create a set of ground-truth poses
* Default values give a circular trajectory, radius 30 at pi/4 intervals, * Default values give a circular trajectory, radius 30 at pi/4 intervals,
* always facing the circle center * always facing the circle center
*/ */
std::vector<Pose3> createPoses( std::vector<Pose3> createPoses(

View File

@ -62,7 +62,7 @@ def main():
points = SFMdata.createPoints() points = SFMdata.createPoints()
# Create the set of ground-truth poses # Create the set of ground-truth poses
poses = SFMdata.createPoses(K) poses = SFMdata.createPoses()
# Create a factor graph # Create a factor graph
graph = NonlinearFactorGraph() graph = NonlinearFactorGraph()

View File

@ -3,14 +3,14 @@ A structure-from-motion example with landmarks
- The landmarks form a 10 meter cube - The landmarks form a 10 meter cube
- The robot rotates around the landmarks, always facing towards the cube - The robot rotates around the landmarks, always facing towards the cube
""" """
# pylint: disable=invalid-name, E1101 # pylint: disable=invalid-name, E1101
from typing import List from typing import List
import numpy as np import numpy as np
import gtsam from gtsam import Point3, Pose3, Rot3
from gtsam import Cal3_S2, Point3, Pose3
def createPoints() -> List[Point3]: def createPoints() -> List[Point3]:
@ -28,16 +28,49 @@ def createPoints() -> List[Point3]:
return points return points
def createPoses(K: Cal3_S2) -> List[Pose3]: _M_PI_2 = np.pi / 2
"""Generate a set of ground-truth camera poses arranged in a circle about the origin.""" _M_PI_4 = np.pi / 4
radius = 40.0
height = 10.0
angles = np.linspace(0, 2 * np.pi, 8, endpoint=False) def createPoses(
up = gtsam.Point3(0, 0, 1) init: Pose3 = Pose3(Rot3.Ypr(_M_PI_2, 0, -_M_PI_2), Point3(30, 0, 0)),
target = gtsam.Point3(0, 0, 0) delta: Pose3 = Pose3(
poses = [] Rot3.Ypr(0, -_M_PI_4, 0),
for theta in angles: Point3(np.sin(_M_PI_4) * 30, 0, 30 * (1 - np.sin(_M_PI_4))),
position = gtsam.Point3(radius * np.cos(theta), radius * np.sin(theta), height) ),
camera = gtsam.PinholeCameraCal3_S2.Lookat(position, target, up, K) steps: int = 8,
poses.append(camera.pose()) ) -> List[Pose3]:
"""
Create a set of ground-truth poses
Default values give a circular trajectory, radius 30 at pi/4 intervals,
always facing the circle center
"""
poses = [init]
for _ in range(1, steps):
poses.append(poses[-1].compose(delta))
return poses return poses
def posesOnCircle(num_cameras=8, R=30):
"""Create regularly spaced poses with specified radius and number of cameras."""
theta = 2 * np.pi / num_cameras
# Initial pose at angle 0, position (R, 0, 0), facing the center with Y-axis pointing down
init_rotation = Rot3.Ypr(_M_PI_2, 0, -_M_PI_2)
init_position = np.array([R, 0, 0])
init = Pose3(init_rotation, init_position)
# Delta rotation: rotate by -theta around Z-axis (counterclockwise movement)
delta_rotation = Rot3.Ypr(0, -theta, 0)
# Delta translation in world frame
delta_translation_world = np.array([R * (np.cos(theta) - 1), R * np.sin(theta), 0])
# Transform delta translation to local frame of the camera
delta_translation_local = init.rotation().unrotate(delta_translation_world)
# Define delta pose
delta = Pose3(delta_rotation, delta_translation_local)
# Generate poses
return createPoses(init, delta, num_cameras)

View File

@ -31,8 +31,7 @@ def get_data() -> Tuple[gtsam.Values, List[gtsam.BinaryMeasurementUnit3]]:
that lie on a circle and face the center. The poses of 8 cameras are obtained from SFMdata that lie on a circle and face the center. The poses of 8 cameras are obtained from SFMdata
and the unit translations directions between some camera pairs are computed from their and the unit translations directions between some camera pairs are computed from their
global translations. """ global translations. """
fx, fy, s, u0, v0 = 50.0, 50.0, 0.0, 50.0, 50.0 wTc_list = SFMdata.createPoses()
wTc_list = SFMdata.createPoses(gtsam.Cal3_S2(fx, fy, s, u0, v0))
# Rotations of the cameras in the world frame. # Rotations of the cameras in the world frame.
wRc_values = gtsam.Values() wRc_values = gtsam.Values()
# Normalized translation directions from camera i to camera j # Normalized translation directions from camera i to camera j

View File

@ -73,7 +73,7 @@ def visual_ISAM2_example():
points = SFMdata.createPoints() points = SFMdata.createPoints()
# Create the set of ground-truth poses # Create the set of ground-truth poses
poses = SFMdata.createPoses(K) poses = SFMdata.createPoses()
# Create an iSAM2 object. Unlike iSAM1, which performs periodic batch steps # Create an iSAM2 object. Unlike iSAM1, which performs periodic batch steps
# to maintain proper linearization and efficient variable ordering, iSAM2 # to maintain proper linearization and efficient variable ordering, iSAM2

View File

@ -36,7 +36,7 @@ def main():
# Create the set of ground-truth landmarks # Create the set of ground-truth landmarks
points = SFMdata.createPoints() points = SFMdata.createPoints()
# Create the set of ground-truth poses # Create the set of ground-truth poses
poses = SFMdata.createPoses(K) poses = SFMdata.createPoses()
# Create a NonlinearISAM object which will relinearize and reorder the variables # Create a NonlinearISAM object which will relinearize and reorder the variables
# every "reorderInterval" updates # every "reorderInterval" updates