Skip to content

Commit 9a85b3e

Browse files
readme updated
Signed-off-by: Tiffany Cappellari <tcappellari@theaiinstitute.com>
1 parent 3298054 commit 9a85b3e

8 files changed

Lines changed: 322 additions & 298 deletions

spot_wrapper/calibration/README.md

Lines changed: 192 additions & 162 deletions
Large diffs are not rendered by default.

spot_wrapper/calibration/automatic_camera_calibration_robot.py

Lines changed: 0 additions & 132 deletions
This file was deleted.

spot_wrapper/calibration/calibrate_spot_hand.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
import numpy as np
99
import yaml
1010

11-
from spot_wrapper.calibration.automatic_camera_calibration_robot import AutomaticCameraCalibrationRobot
1211
from spot_wrapper.calibration.calibration_clis import (
1312
calibrate_robot_cli,
1413
setup_calibration_param,
1514
spot_cli,
1615
)
16+
from spot_wrapper.calibration.calibration_helpers import AutomaticCameraCalibrationRobot
1717
from spot_wrapper.calibration.calibration_util import (
1818
calibration_helper,
1919
get_multiple_perspective_camera_calibration_dataset,

spot_wrapper/calibration/calibration_helpers.py

Lines changed: 127 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
from __future__ import annotations
44

5-
from typing import Optional, TypedDict
5+
from abc import ABC, abstractmethod
6+
from typing import List, Optional, Tuple, TypedDict, Union
67

78
import numpy as np
89

@@ -26,3 +27,128 @@ class CalibrationResults(TypedDict):
2627
R_handeye: Optional[np.ndarray]
2728
T_handeye: Optional[np.ndarray]
2829
average_reprojection_error: float
30+
31+
32+
class AutomaticCameraCalibrationRobot(ABC):
33+
@abstractmethod
34+
def capture_images(self) -> Union[List, np.ndarray]:
35+
"""
36+
Capture images from the cameras you wish to calibrate at the same moment in time
37+
(time-synchronized). Then, construct either a list or a NumPy array
38+
of these images. This will be called every time that your robot reaches a new
39+
calibration viewpoint, so ensure that image order to camera correlation is consistent
40+
across all calls. Also, it is important to ensure that the photos are as time-synchronized
41+
as possible, with as little motion blur as possible.
42+
43+
Returns:
44+
Union[List, np.ndarray]: The time-synchronized images from all relevant cameras.
45+
"""
46+
pass
47+
48+
@abstractmethod
49+
def localize_target_to_principal_camera(self, images: Union[List, np.ndarray]) -> Tuple[np.ndarray, np.ndarray]:
50+
"""
51+
Localize the charuco board relative to what is considered
52+
the principal camera for the calibration. This could be done
53+
either visually, or via kinematics and fixing the board relative
54+
to the robot. Visually is more flexible, although this
55+
implies some knowledge of the principal cameras intrinsics.
56+
57+
In this case, principal camera could be an actual camera, or could also be a "virtual"
58+
camera. The principal camera's frame is just what frame is used to sample viewpoints in.
59+
60+
The board pose's translation should be at the center of the board, with the orientation
61+
in OpenCV format, where the +Z points out of the board with
62+
the other axis being parallel to the sides of the board.
63+
64+
Your camera pose should be in OpenCV/ROS convention, where
65+
# +x should point to the right in the image
66+
# +y should point down in the image
67+
# +z should point into to plane of the image
68+
69+
If you'd like to do this through visual localization, you can use
70+
71+
def est_camera_t_charuco_board_center(
72+
img: np.ndarray,
73+
charuco_board: cv2.aruco_CharucoBoard,
74+
aruco_dict: cv2.aruco_Dictionary,
75+
camera_matrix: np.ndarray,
76+
dist_coeffs: np.ndarray,
77+
)
78+
from calibration_util.py
79+
80+
Args:
81+
images (Union[List, np.ndarray]): the images that could be used to determine
82+
how far the target is from the "principal" camera
83+
84+
Returns:
85+
Tuple[np.ndarray, np.ndarray]: _description_
86+
"""
87+
pass
88+
89+
@abstractmethod
90+
def move_cameras_to_see_calibration_target(self) -> np.ndarray:
91+
"""
92+
This is a robot specific sequence to start the calibration. This
93+
could be as simple as a heuristic to move the robot to a known pose where
94+
it is generally looking at the checkerboard, or this could be a more sophisticated
95+
sequence to look around in the scene until a board is found
96+
(for example, grabbing images with self.capture_images(),
97+
and checking if a board is found with detect_charuco_corners from calibration_util.py)
98+
99+
Returns:
100+
np.ndarray: the 4x4 homogenous transform of the starting pose where the calibration
101+
board is visible.
102+
"""
103+
pass
104+
105+
@abstractmethod
106+
def offset_cameras_from_current_view(
107+
self,
108+
transform_offset: np.ndarray,
109+
origin_t_planning_frame: Optional[np.ndarray] = None,
110+
duration_sec: float = 1.0,
111+
) -> Tuple[np.ndarray, np.ndarray]:
112+
"""
113+
Move the robot to a desired position, such that the cameras move by transform_offset.
114+
This is how the robot visits desired viewpoints.
115+
116+
IMPORTANT: You likely have to convert transform_offset from the "principal"
117+
camera frame into the planning frame (if the camera frame isn't the planning frame).
118+
This can be done by calling
119+
120+
convert_camera_t_viewpoint_to_origin_t_planning_frame(
121+
origin_t_planning_frame=origin_t_planning_frame,
122+
planning_frame_t_opencv_camera=HOMOGENOUS_TRANSFORM_FROM_PLANNING_FRAME_TO_OPENCV_CAM,
123+
opencv_camera_t_viewpoint=transform_offset,
124+
)
125+
from calibration_util.py
126+
127+
Your camera pose should be in OpenCV/ROS convention, where
128+
+x should point to the right in the image
129+
+y should point down in the image
130+
+z should point into to plane of the image
131+
132+
Args:
133+
transform_offset (np.ndarray): the 4x4 homogenous transform of
134+
how far you'd like to shift your cameras
135+
origin_t_planning_frame (Optional[np.ndarray], optional): the 4x4 homogenous
136+
transform of your robot origin to planning frame. Could be hard-coded
137+
or read off of the robot. Defaults to None.
138+
duration_sec (float, optional): How many seconds provided to execute
139+
the move. Defaults to 1.0.
140+
141+
Returns:
142+
Tuple[np.ndarray, np.ndarray]: the 4x4 homogenous transform of origin_t_planning_frame
143+
before the move, and the 4x4 homogenous transform of origin_t_planning_frame
144+
after the move.
145+
"""
146+
pass
147+
148+
@abstractmethod
149+
def shutdown(self) -> None:
150+
"""
151+
Cleanup the robot connection, and disconnect so that other programs can resume
152+
control of the robot while this program continues to solve the calibration parameters.
153+
"""
154+
pass

spot_wrapper/calibration/calibration_util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import numpy as np
1414
import yaml
1515

16-
from spot_wrapper.calibration.automatic_camera_calibration_robot import (
16+
from spot_wrapper.calibration.calibration_helpers import (
1717
AutomaticCameraCalibrationRobot,
1818
)
1919
from spot_wrapper.calibration.charuco_board_detection import (
46.4 KB
Loading
38.8 KB
Loading

spot_wrapper/calibration/spot_in_hand_camera_calibration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
from bosdyn.client.robot_state import RobotStateClient
4040
from bosdyn.client.time_sync import TimedOutError
4141

42-
from spot_wrapper.calibration.automatic_camera_calibration_robot import (
42+
from spot_wrapper.calibration.calibration_helpers import (
4343
AutomaticCameraCalibrationRobot,
4444
)
4545
from spot_wrapper.calibration.charuco_board_detection import (

0 commit comments

Comments
 (0)