Skip to content

Commit 391a68c

Browse files
[SW-4178] Spot calibration params bug (#189)
* maybe fixed?? * some changes and debugging things happened * frame transforms look correct * pre-commit
1 parent a759ff5 commit 391a68c

1 file changed

Lines changed: 56 additions & 37 deletions

File tree

spot_wrapper/calibration/spot_in_hand_camera_calibration.py

Lines changed: 56 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from bosdyn.client.frame_helpers import (
2121
BODY_FRAME_NAME,
2222
HAND_FRAME_NAME,
23+
WR1_FRAME_NAME,
2324
get_a_tform_b,
2425
)
2526
from bosdyn.client.gripper_camera_param import GripperCameraParamClient
@@ -123,15 +124,15 @@ def extract_calibration_parameters(self, calibration_dict: dict, tag: str) -> di
123124
calibration["rgb_intrinsic"] = np.asarray(calibration_dict[tag]["intrinsic"][0]["camera_matrix"]).reshape(
124125
(3, 3)
125126
)
126-
depth_to_rgb_T = np.array(calibration_dict[tag]["extrinsic"][1][0]["T"]).reshape((3, 1))
127-
depth_to_rgb_R = np.array(calibration_dict[tag]["extrinsic"][1][0]["R"]).reshape((3, 3))
128-
calibration["depth_to_rgb"] = np.vstack(
129-
(np.hstack((depth_to_rgb_R, depth_to_rgb_T)), np.array([0, 0, 0, 1]))
127+
rgb_to_depth_T = np.array(calibration_dict[tag]["extrinsic"][1][0]["T"]).reshape((3, 1))
128+
rgb_to_depth_R = np.array(calibration_dict[tag]["extrinsic"][1][0]["R"]).reshape((3, 3))
129+
calibration["rgb_to_depth"] = np.vstack(
130+
(np.hstack((rgb_to_depth_R, rgb_to_depth_T)), np.array([0, 0, 0, 1]))
130131
)
131-
depth_to_planning_T = np.array(calibration_dict[tag]["extrinsic"][1]["planning_frame"]["T"]).reshape((3, 1))
132-
depth_to_planning_R = np.array(calibration_dict[tag]["extrinsic"][1]["planning_frame"]["R"]).reshape((3, 3))
133-
calibration["depth_to_planning_frame"] = np.vstack(
134-
(np.hstack((depth_to_planning_R, depth_to_planning_T)), np.array([0, 0, 0, 1]))
132+
depth_to_hand_T = np.array(calibration_dict[tag]["extrinsic"][1]["planning_frame"]["T"]).reshape((3, 1))
133+
depth_to_hand_R = np.array(calibration_dict[tag]["extrinsic"][1]["planning_frame"]["R"]).reshape((3, 3))
134+
calibration["depth_to_hand"] = np.vstack(
135+
(np.hstack((depth_to_hand_R, depth_to_hand_T)), np.array([0, 0, 0, 1]))
135136
)
136137
except KeyError as e:
137138
raise ValueError(f"Error: Missing key in the calibration data: {e}")
@@ -152,7 +153,6 @@ def write_calibration_to_robot(self, cal_dict: dict, tag: str = "default") -> No
152153
cal = self.extract_calibration_parameters(cal_dict, tag)
153154

154155
print("Pre Setting Param--------------------------------------------")
155-
print(f"Calibration Data being sent to robot: \n {cal}")
156156

157157
def convert_pinhole_intrinsic_to_proto(intrinsic_matrix: np.ndarray) -> ImageSource.PinholeModel:
158158
"""Converts a 3x3 intrinsic matrix to a PinholeModel protobuf."""
@@ -161,28 +161,48 @@ def convert_pinhole_intrinsic_to_proto(intrinsic_matrix: np.ndarray) -> ImageSou
161161
pinhole_model.CameraIntrinsics.principal_point = (intrinsic_matrix[0, 2], intrinsic_matrix[1, 2])
162162
return pinhole_model
163163

164+
hand_t_wr1_pose = get_a_tform_b(
165+
self.robot_state_client.get_robot_state().kinematic_state.transforms_snapshot,
166+
HAND_FRAME_NAME,
167+
WR1_FRAME_NAME,
168+
)
169+
hand_t_planning = np.eye(4)
170+
hand_t_planning[:-1, -1] = np.array(
171+
[
172+
hand_t_wr1_pose.x,
173+
hand_t_wr1_pose.y,
174+
hand_t_wr1_pose.z,
175+
]
176+
).reshape((3,))
177+
hand_t_planning[:-1, :-1] = hand_t_wr1_pose.rot.to_matrix()
178+
logger.info(f"\n{hand_t_planning=}\n")
179+
164180
depth_intrinsics = cal["depth_intrinsic"]
165181
rgb_intrinsics = cal["rgb_intrinsic"]
166-
depth_to_rgb = cal["depth_to_rgb"]
167-
depth_to_planning_frame = cal["depth_to_planning_frame"]
168-
rgb_to_planning_frame = np.linalg.inv(depth_to_rgb) @ depth_to_planning_frame
182+
rgb_t_depth = cal["rgb_to_depth"]
183+
184+
depth_to_planning = cal["depth_to_hand"] @ hand_t_planning
185+
rgb_to_planning = rgb_t_depth @ depth_to_planning
186+
187+
planning_t_depth = np.linalg.inv(depth_to_planning)
188+
planning_t_rgb = np.linalg.inv(rgb_to_planning)
169189

170190
# Converting calibration data to protobuf format
171191
depth_intrinsics_proto = convert_pinhole_intrinsic_to_proto(depth_intrinsics)
172192
rgb_intrinsics_proto = convert_pinhole_intrinsic_to_proto(rgb_intrinsics)
173-
depth_to_planning_frame_proto = SE3Pose.from_matrix(depth_to_planning_frame).to_proto()
174-
rgb_to_planning_frame_proto = SE3Pose.from_matrix(rgb_to_planning_frame).to_proto()
193+
planning_t_depth_frame_proto = SE3Pose.from_matrix(planning_t_depth).to_proto()
194+
planning_t_rgb_frame_proto = SE3Pose.from_matrix(planning_t_rgb).to_proto()
175195

176196
set_req = gripper_camera_param_pb2.SetGripperCameraCalibrationRequest(
177197
gripper_cam_cal=gripper_camera_param_pb2.GripperCameraCalibrationProto(
178198
depth=gripper_camera_param_pb2.GripperDepthCameraCalibrationParams(
179-
wr1_tform_sensor=depth_to_planning_frame_proto,
199+
wr1_tform_sensor=planning_t_depth_frame_proto,
180200
intrinsics=gripper_camera_param_pb2.GripperDepthCameraCalibrationParams.DepthCameraIntrinsics(
181201
pinhole=depth_intrinsics_proto
182202
),
183203
),
184204
color=gripper_camera_param_pb2.GripperColorCameraCalibrationParams(
185-
wr1_tform_sensor=rgb_to_planning_frame_proto,
205+
wr1_tform_sensor=planning_t_rgb_frame_proto,
186206
intrinsics=[
187207
gripper_camera_param_pb2.GripperColorCameraCalibrationParams.ColorCameraIntrinsics(
188208
pinhole=rgb_intrinsics_proto
@@ -191,7 +211,6 @@ def convert_pinhole_intrinsic_to_proto(intrinsic_matrix: np.ndarray) -> ImageSou
191211
),
192212
)
193213
)
194-
195214
# Send the request to the robot
196215
try:
197216
result = self.gripper_camera_client.set_camera_calib(set_req)
@@ -262,33 +281,33 @@ def adjust_standing_height(height: float) -> None:
262281
old_pose, ready_pose = self.offset_cameras_from_current_view(transform_offset=transform_offset)
263282
return ready_pose
264283

284+
def grab_state_as_transform(self) -> np.ndarray:
285+
robot_state = self.robot_state_client.get_robot_state()
286+
origin_t_planning_frame = get_a_tform_b(
287+
robot_state.kinematic_state.transforms_snapshot,
288+
BODY_FRAME_NAME,
289+
HAND_FRAME_NAME,
290+
)
291+
pose_transform = np.eye(4)
292+
pose_transform[:-1, -1] = np.array(
293+
[
294+
origin_t_planning_frame.x,
295+
origin_t_planning_frame.y,
296+
origin_t_planning_frame.z,
297+
]
298+
).reshape((3,))
299+
pose_transform[:-1, :-1] = origin_t_planning_frame.rot.to_matrix()
300+
return pose_transform
301+
265302
def offset_cameras_from_current_view(
266303
self,
267304
transform_offset: np.ndarray,
268305
origin_t_planning_frame: Optional[np.ndarray] = None,
269306
use_body: bool = False,
270307
duration_sec: float = 1.0,
271308
) -> Tuple[np.ndarray, np.ndarray]:
272-
def grab_state_as_transform() -> np.ndarray:
273-
robot_state = self.robot_state_client.get_robot_state()
274-
origin_t_planning_frame = get_a_tform_b(
275-
robot_state.kinematic_state.transforms_snapshot,
276-
BODY_FRAME_NAME,
277-
HAND_FRAME_NAME,
278-
)
279-
pose_transform = np.eye(4)
280-
pose_transform[:-1, -1] = np.array(
281-
[
282-
origin_t_planning_frame.x,
283-
origin_t_planning_frame.y,
284-
origin_t_planning_frame.z,
285-
]
286-
).reshape((3,))
287-
pose_transform[:-1, :-1] = origin_t_planning_frame.rot.to_matrix()
288-
return pose_transform
289-
290309
if origin_t_planning_frame is None:
291-
initial_pose = grab_state_as_transform()
310+
initial_pose = self.grab_state_as_transform()
292311
else:
293312
initial_pose = origin_t_planning_frame
294313

@@ -328,7 +347,7 @@ def grab_state_as_transform() -> np.ndarray:
328347
timeout_sec=duration_sec * 2,
329348
)
330349
sleep(duration_sec * 0.5) # settle before grabbing new state for better quality
331-
return (initial_pose, grab_state_as_transform()) # second value is new value
350+
return (initial_pose, self.grab_state_as_transform()) # second value is new value
332351

333352
def shutdown(self) -> None:
334353
stow_arm_command = RobotCommandBuilder.arm_stow_command()

0 commit comments

Comments
 (0)