Skip to content

Commit 79f5784

Browse files
committed
update ik: input as a pose in robot frame
1 parent 31b4b9b commit 79f5784

File tree

2 files changed

+173
-37
lines changed

2 files changed

+173
-37
lines changed

examples/ioai_examples/ioai_env.py

Lines changed: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -476,17 +476,79 @@ def _setup_mink(self):
476476
self.damping = 1e-3
477477
self.rate_limiter = RateLimiter(frequency=1000, warn=False)
478478

479+
def world_to_robot_frame(self, world_position, world_orientation):
480+
"""Transform pose from world frame to robot base frame.
481+
482+
Args:
483+
world_position: Position in world frame [x, y, z]
484+
world_orientation: Orientation in world frame [qx, qy, qz, qw]
485+
486+
Returns:
487+
Tuple of (robot_position, robot_orientation) in robot base frame
488+
"""
489+
from scipy.spatial.transform import Rotation
490+
491+
# Get robot base pose in world frame
492+
base_position = self.robot.get_position()
493+
base_orientation = self.robot.get_orientation()
494+
495+
# Create transformation matrices
496+
base_rot = Rotation.from_quat(base_orientation)
497+
world_rot = Rotation.from_quat(world_orientation)
498+
499+
# Transform position: subtract base position and rotate
500+
relative_position = world_position - base_position
501+
robot_position = base_rot.inv().apply(relative_position)
502+
503+
# Transform orientation: compose rotations
504+
robot_orientation = (base_rot.inv() * world_rot).as_quat()
505+
506+
return robot_position, robot_orientation
507+
508+
def robot_to_world_frame(self, robot_position, robot_orientation):
509+
"""Transform pose from robot base frame to world frame.
510+
511+
Args:
512+
robot_position: Position in robot base frame [x, y, z]
513+
robot_orientation: Orientation in robot base frame [qx, qy, qz, qw]
514+
515+
Returns:
516+
Tuple of (world_position, world_orientation) in world frame
517+
"""
518+
from scipy.spatial.transform import Rotation
519+
520+
# Get robot base pose in world frame
521+
base_position = self.robot.get_position()
522+
base_orientation = self.robot.get_orientation()
523+
524+
# Create transformation matrices
525+
base_rot = Rotation.from_quat(base_orientation)
526+
robot_rot = Rotation.from_quat(robot_orientation)
527+
528+
# Transform position: rotate and add base position
529+
world_position = base_rot.apply(robot_position) + base_position
530+
531+
# Transform orientation: compose rotations
532+
world_orientation = (base_rot * robot_rot).as_quat()
533+
534+
return world_position, world_orientation
535+
479536
def compute_simple_ik(self, start_joint, target_pose, arm_id="left_arm"):
480537
"""Compute inverse kinematics using Mink.
481538
482539
Args:
483540
start_joint: Initial joint configuration (not used in current implementation)
484-
target_pose: Target pose [x, y, z, qx, qy, qz, qw] in world coordinates
541+
target_pose: Target pose [x, y, z, qx, qy, qz, qw] in robot base frame
485542
arm_id: The ID of the arm, either "left_arm" or "right_arm"
486543
487544
Returns:
488545
Target joint configuration for the specified arm
489546
"""
547+
# Transform target pose from robot frame to world frame for IK
548+
target_position = target_pose[:3]
549+
target_orientation = target_pose[3:7]
550+
world_position, world_orientation = self.robot_to_world_frame(target_position, target_orientation)
551+
490552
# Set target for chassis
491553
chassis_target = mink.SE3.from_rotation_and_translation(
492554
rotation=mink.SO3(wxyz=xyzw_to_wxyz(self.robot.get_orientation())),
@@ -506,22 +568,18 @@ def compute_simple_ik(self, start_joint, target_pose, arm_id="left_arm"):
506568
# Set target for posture
507569
self.tasks["posture"].set_target_from_configuration(self.mink_config)
508570

509-
# Extract position and orientation from target pose
510-
target_position = target_pose[:3]
511-
target_orientation = target_pose[3:7] # [qx, qy, qz, qw]
512-
513-
# Set target for the specified arm
571+
# Set target for the specified arm using world frame pose
514572
if arm_id == "left_arm":
515573
target = mink.SE3.from_rotation_and_translation(
516-
rotation=mink.SO3(wxyz=xyzw_to_wxyz(target_orientation)),
517-
translation=target_position
574+
rotation=mink.SO3(wxyz=xyzw_to_wxyz(world_orientation)),
575+
translation=world_position
518576
)
519577
self.tasks["left_arm"].set_target(target)
520578
tasks = [self.tasks["torso"], self.tasks["posture"], self.tasks["chassis"], self.tasks["left_arm"]]
521579
elif arm_id == "right_arm":
522580
target = mink.SE3.from_rotation_and_translation(
523-
rotation=mink.SO3(wxyz=xyzw_to_wxyz(target_orientation)),
524-
translation=target_position
581+
rotation=mink.SO3(wxyz=xyzw_to_wxyz(world_orientation)),
582+
translation=world_position
525583
)
526584
self.tasks["right_arm"].set_target(target)
527585
tasks = [self.tasks["torso"], self.tasks["posture"], self.tasks["chassis"], self.tasks["right_arm"]]
@@ -654,14 +712,14 @@ def _move_left_arm_to_pose(self, target_position, target_orientation):
654712
"""Move left arm to target pose with IK solving and motion control.
655713
656714
Args:
657-
target_position: Target position [x, y, z]
658-
target_orientation: Target orientation [qx, qy, qz, qw]
715+
target_position: Target position [x, y, z] in robot base frame
716+
target_orientation: Target orientation [qx, qy, qz, qw] in robot base frame
659717
660718
Returns:
661719
True if motion is complete, False otherwise
662720
"""
663721
if not self.motion_in_progress:
664-
# Prepare target pose
722+
# Prepare target pose in robot frame
665723
target_pose = np.concatenate([target_position, target_orientation])
666724

667725
# Solve IK and start motion
@@ -683,14 +741,14 @@ def _move_right_arm_to_pose(self, target_position, target_orientation):
683741
"""Move right arm to target pose with IK solving and motion control.
684742
685743
Args:
686-
target_position: Target position [x, y, z]
687-
target_orientation: Target orientation [qx, qy, qz, qw]
744+
target_position: Target position [x, y, z] in robot base frame
745+
target_orientation: Target orientation [qx, qy, qz, qw] in robot base frame
688746
689747
Returns:
690748
True if motion is complete, False otherwise
691749
"""
692750
if not self.motion_in_progress:
693-
# Prepare target pose
751+
# Prepare target pose in robot frame
694752
target_pose = np.concatenate([target_position, target_orientation])
695753

696754
# Solve IK and start motion

examples/ioai_examples/ioai_grasp_env.py

Lines changed: 99 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -335,17 +335,79 @@ def _setup_mink(self):
335335
self.damping = 1e-3
336336
self.rate_limiter = RateLimiter(frequency=1000, warn=False)
337337

338+
def world_to_robot_frame(self, world_position, world_orientation):
339+
"""Transform pose from world frame to robot base frame.
340+
341+
Args:
342+
world_position: Position in world frame [x, y, z]
343+
world_orientation: Orientation in world frame [qx, qy, qz, qw]
344+
345+
Returns:
346+
Tuple of (robot_position, robot_orientation) in robot base frame
347+
"""
348+
from scipy.spatial.transform import Rotation
349+
350+
# Get robot base pose in world frame
351+
base_position = self.robot.get_position()
352+
base_orientation = self.robot.get_orientation()
353+
354+
# Create transformation matrices
355+
base_rot = Rotation.from_quat(base_orientation)
356+
world_rot = Rotation.from_quat(world_orientation)
357+
358+
# Transform position: subtract base position and rotate
359+
relative_position = world_position - base_position
360+
robot_position = base_rot.inv().apply(relative_position)
361+
362+
# Transform orientation: compose rotations
363+
robot_orientation = (base_rot.inv() * world_rot).as_quat()
364+
365+
return robot_position, robot_orientation
366+
367+
def robot_to_world_frame(self, robot_position, robot_orientation):
368+
"""Transform pose from robot base frame to world frame.
369+
370+
Args:
371+
robot_position: Position in robot base frame [x, y, z]
372+
robot_orientation: Orientation in robot base frame [qx, qy, qz, qw]
373+
374+
Returns:
375+
Tuple of (world_position, world_orientation) in world frame
376+
"""
377+
from scipy.spatial.transform import Rotation
378+
379+
# Get robot base pose in world frame
380+
base_position = self.robot.get_position()
381+
base_orientation = self.robot.get_orientation()
382+
383+
# Create transformation matrices
384+
base_rot = Rotation.from_quat(base_orientation)
385+
robot_rot = Rotation.from_quat(robot_orientation)
386+
387+
# Transform position: rotate and add base position
388+
world_position = base_rot.apply(robot_position) + base_position
389+
390+
# Transform orientation: compose rotations
391+
world_orientation = (base_rot * robot_rot).as_quat()
392+
393+
return world_position, world_orientation
394+
338395
def compute_simple_ik(self, start_joint, target_pose, arm_id="left_arm"):
339396
"""Compute inverse kinematics using Mink.
340397
341398
Args:
342399
start_joint: Initial joint configuration (not used in current implementation)
343-
target_pose: Target pose [x, y, z, qx, qy, qz, qw] in world coordinates
400+
target_pose: Target pose [x, y, z, qx, qy, qz, qw] in robot base frame
344401
arm_id: The ID of the arm, either "left_arm" or "right_arm"
345402
346403
Returns:
347404
Target joint configuration for the specified arm
348405
"""
406+
# Transform target pose from robot frame to world frame for IK
407+
target_position = target_pose[:3]
408+
target_orientation = target_pose[3:7]
409+
world_position, world_orientation = self.robot_to_world_frame(target_position, target_orientation)
410+
349411
# Set target for chassis
350412
chassis_target = mink.SE3.from_rotation_and_translation(
351413
rotation=mink.SO3(wxyz=xyzw_to_wxyz(self.robot.get_orientation())),
@@ -365,22 +427,18 @@ def compute_simple_ik(self, start_joint, target_pose, arm_id="left_arm"):
365427
# Set target for posture
366428
self.tasks["posture"].set_target_from_configuration(self.mink_config)
367429

368-
# Extract position and orientation from target pose
369-
target_position = target_pose[:3]
370-
target_orientation = target_pose[3:7] # [qx, qy, qz, qw]
371-
372-
# Set target for the specified arm
430+
# Set target for the specified arm using world frame pose
373431
if arm_id == "left_arm":
374432
target = mink.SE3.from_rotation_and_translation(
375-
rotation=mink.SO3(wxyz=xyzw_to_wxyz(target_orientation)),
376-
translation=target_position
433+
rotation=mink.SO3(wxyz=xyzw_to_wxyz(world_orientation)),
434+
translation=world_position
377435
)
378436
self.tasks["left_arm"].set_target(target)
379437
tasks = [self.tasks["torso"], self.tasks["posture"], self.tasks["chassis"], self.tasks["left_arm"]]
380438
elif arm_id == "right_arm":
381439
target = mink.SE3.from_rotation_and_translation(
382-
rotation=mink.SO3(wxyz=xyzw_to_wxyz(target_orientation)),
383-
translation=target_position
440+
rotation=mink.SO3(wxyz=xyzw_to_wxyz(world_orientation)),
441+
translation=world_position
384442
)
385443
self.tasks["right_arm"].set_target(target)
386444
tasks = [self.tasks["torso"], self.tasks["posture"], self.tasks["chassis"], self.tasks["right_arm"]]
@@ -513,14 +571,14 @@ def _move_left_arm_to_pose(self, target_position, target_orientation):
513571
"""Move left arm to target pose with IK solving and motion control.
514572
515573
Args:
516-
target_position: Target position [x, y, z]
517-
target_orientation: Target orientation [qx, qy, qz, qw]
574+
target_position: Target position [x, y, z] in robot base frame
575+
target_orientation: Target orientation [qx, qy, qz, qw] in robot base frame
518576
519577
Returns:
520578
True if motion is complete, False otherwise
521579
"""
522580
if not self.motion_in_progress:
523-
# Prepare target pose
581+
# Prepare target pose in robot frame
524582
target_pose = np.concatenate([target_position, target_orientation])
525583

526584
# Solve IK and start motion
@@ -542,14 +600,14 @@ def _move_right_arm_to_pose(self, target_position, target_orientation):
542600
"""Move right arm to target pose with IK solving and motion control.
543601
544602
Args:
545-
target_position: Target position [x, y, z]
546-
target_orientation: Target orientation [qx, qy, qz, qw]
603+
target_position: Target position [x, y, z] in robot base frame
604+
target_orientation: Target orientation [qx, qy, qz, qw] in robot base frame
547605
548606
Returns:
549607
True if motion is complete, False otherwise
550608
"""
551609
if not self.motion_in_progress:
552-
# Prepare target pose
610+
# Prepare target pose in robot frame
553611
target_pose = np.concatenate([target_position, target_orientation])
554612

555613
# Solve IK and start motion
@@ -602,7 +660,11 @@ def pick_and_place_callback(self):
602660

603661
def init_state():
604662
"""Move to initial pose"""
605-
return self._move_left_arm_to_pose([0.5, 0.3, 0.7], [0, 0.7071, 0, 0.7071])
663+
# Convert world frame pose to robot frame
664+
world_pos = np.array([0.5, 0.3, 0.7])
665+
world_ori = np.array([0, 0.7071, 0, 0.7071])
666+
robot_pos, robot_ori = self.world_to_robot_frame(world_pos, world_ori)
667+
return self._move_left_arm_to_pose(robot_pos, robot_ori)
606668

607669
def move_to_pre_pick_state():
608670
"""Move to pre-pick position"""
@@ -611,11 +673,19 @@ def move_to_pre_pick_state():
611673
self.cube_position = cube_state["position"].copy()
612674
self.state_first_entry = False
613675

614-
return self._move_left_arm_to_pose(self.cube_position + np.array([0, 0, 0.15]), [0, 0.7071, 0, 0.7071])
676+
# Convert world frame pose to robot frame
677+
world_pos = self.cube_position + np.array([0, 0, 0.15])
678+
world_ori = np.array([0, 0.7071, 0, 0.7071])
679+
robot_pos, robot_ori = self.world_to_robot_frame(world_pos, world_ori)
680+
return self._move_left_arm_to_pose(robot_pos, robot_ori)
615681

616682
def move_to_pick_state():
617683
"""Move to pick position"""
618-
return self._move_left_arm_to_pose(self.cube_position + np.array([0, 0, 0.03]), [0, 0.7071, 0, 0.7071])
684+
# Convert world frame pose to robot frame
685+
world_pos = self.cube_position + np.array([0, 0, 0.03])
686+
world_ori = np.array([0, 0.7071, 0, 0.7071])
687+
robot_pos, robot_ori = self.world_to_robot_frame(world_pos, world_ori)
688+
return self._move_left_arm_to_pose(robot_pos, robot_ori)
619689

620690
def grasp_state():
621691
"""Grasp the object"""
@@ -631,7 +701,11 @@ def grasp_state():
631701

632702
def move_to_pre_place_state():
633703
"""Move to pre-place position"""
634-
return self._move_left_arm_to_pose(self.cube_position + np.array([-0.1, 0, 0.4]), [0, 0.7071, 0, 0.7071])
704+
# Convert world frame pose to robot frame
705+
world_pos = self.cube_position + np.array([-0.1, 0, 0.4])
706+
world_ori = np.array([0, 0.7071, 0, 0.7071])
707+
robot_pos, robot_ori = self.world_to_robot_frame(world_pos, world_ori)
708+
return self._move_left_arm_to_pose(robot_pos, robot_ori)
635709

636710
def move_to_place_state():
637711
"""Move to place position"""
@@ -640,7 +714,11 @@ def move_to_place_state():
640714
self.bin_position = bin_state["position"].copy()
641715
self.state_first_entry = False
642716

643-
return self._move_left_arm_to_pose(self.bin_position + np.array([0, 0, 0.3]), [0, 0.7071, 0, 0.7071])
717+
# Convert world frame pose to robot frame
718+
world_pos = self.bin_position + np.array([0, 0, 0.3])
719+
world_ori = np.array([0, 0.7071, 0, 0.7071])
720+
robot_pos, robot_ori = self.world_to_robot_frame(world_pos, world_ori)
721+
return self._move_left_arm_to_pose(robot_pos, robot_ori)
644722

645723
def release_state():
646724
"""Release the object"""

0 commit comments

Comments
 (0)