Skip to content

Commit 6246e9c

Browse files
committed
[motion-exe] first wip on the motion executioner we will get rid of the process manager
1 parent 56b3ad0 commit 6246e9c

7 files changed

Lines changed: 269 additions & 13 deletions

File tree

src/pycram/robot_execution/__init__.py

Whitespace-only changes.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
from pycram.external_interfaces import giskard
2+
from pycram.robot_description import RobotDescription
3+
from pycram.world import World
4+
from pycram.local_transformer import LocalTransformer
5+
from pycram.datastructures.enums import MovementType, WaypointsMovementType
6+
from pycram.helpers import euler_from_quaternion
7+
from scipy.spatial.transform import Rotation as R
8+
import numpy as np
9+
10+
# Falls du eigene Exceptions hast:
11+
from pycram.failures import NavigationGoalNotReachedError, ToolPoseNotReachedError
12+
13+
def map_MoveMotion(motion):
14+
giskard.avoid_all_collisions()
15+
giskard.achieve_cartesian_goal(
16+
motion.target,
17+
RobotDescription.current_robot_description.base_link,
18+
"map"
19+
)
20+
if not World.current_world.robot.pose.almost_equal(motion.target, 0.05, 3):
21+
raise NavigationGoalNotReachedError(World.current_world.robot.pose, motion.target)
22+
23+
def map_LookingMotion(motion):
24+
target = motion.target
25+
robot = World.robot
26+
27+
local_transformer = LocalTransformer()
28+
neck = RobotDescription.current_robot_description.get_neck()
29+
pan_link = neck["yaw"][0]
30+
tilt_link = neck["pitch"][0]
31+
pan_joint = neck["yaw"][1]
32+
tilt_joint = neck["pitch"][1]
33+
34+
pose_in_pan = local_transformer.transform_pose(target, robot.get_link_tf_frame(pan_link)).position.to_list()
35+
pose_in_tilt = local_transformer.transform_pose(target, robot.get_link_tf_frame(tilt_link)).position.to_list()
36+
new_pan = np.arctan2(pose_in_pan[1], pose_in_pan[0])
37+
38+
tilt_offset = RobotDescription.current_robot_description.get_offset(tilt_joint)
39+
quaternion_list = [0, 0, 0, 1]
40+
if tilt_offset:
41+
q = tilt_offset.pose.orientation
42+
quaternion_list = [q.x, q.y, q.z, q.w]
43+
44+
tilt_offset_rotation = euler_from_quaternion(quaternion_list, axes='sxyz')
45+
adjusted_pose_in_tilt = R.from_euler('xyz', tilt_offset_rotation).apply(pose_in_tilt)
46+
new_tilt = -np.arctan2(adjusted_pose_in_tilt[2], np.sqrt(adjusted_pose_in_tilt[0] ** 2 + adjusted_pose_in_tilt[1] ** 2))
47+
48+
if RobotDescription.current_robot_description.name in {"iCub", "tiago_dual"}:
49+
new_tilt = -new_tilt
50+
51+
current_pan = robot.get_joint_position(pan_joint)
52+
current_tilt = robot.get_joint_position(tilt_joint)
53+
54+
giskard.avoid_all_collisions()
55+
giskard.achieve_joint_goal({
56+
pan_joint: new_pan + current_pan,
57+
tilt_joint: new_tilt + current_tilt
58+
})
59+
60+
def map_MoveTCPMotion(motion):
61+
lt = LocalTransformer()
62+
pose_in_map = lt.transform_pose(motion.target, "map")
63+
tip_link = RobotDescription.current_robot_description.get_arm_chain(motion.arm).get_tool_frame()
64+
root_link = "map"
65+
66+
gripper_that_can_collide = motion.arm if motion.allow_gripper_collision else None
67+
if motion.allow_gripper_collision:
68+
giskard.allow_gripper_collision(motion.arm)
69+
70+
if motion.movement_type == MovementType.STRAIGHT_TRANSLATION:
71+
giskard.achieve_straight_translation_goal(pose_in_map.position.to_list(), tip_link, root_link)
72+
elif motion.movement_type == MovementType.STRAIGHT_CARTESIAN:
73+
giskard.achieve_straight_cartesian_goal(pose_in_map, tip_link, root_link)
74+
elif motion.movement_type == MovementType.TRANSLATION:
75+
giskard.achieve_translation_goal(pose_in_map.position.to_list(), tip_link, root_link)
76+
elif motion.movement_type == MovementType.CARTESIAN:
77+
giskard.achieve_cartesian_goal(pose_in_map, tip_link, root_link,
78+
grippers_that_can_collide=gripper_that_can_collide)
79+
80+
if not World.current_world.robot.get_link_pose(tip_link).almost_equal(motion.target, 0.3, 3):
81+
raise ToolPoseNotReachedError(World.current_world.robot.get_link_pose(tip_link), motion.target)
82+
83+
def map_MoveArmJointsMotion(motion):
84+
joint_goals = {}
85+
if motion.left_arm_poses:
86+
joint_goals.update(motion.left_arm_poses)
87+
if motion.right_arm_poses:
88+
joint_goals.update(motion.right_arm_poses)
89+
giskard.avoid_all_collisions()
90+
giskard.achieve_joint_goal(joint_goals)
91+
92+
def map_MoveJointsMotion(motion):
93+
name_to_position = dict(zip(motion.names, motion.positions))
94+
giskard.avoid_all_collisions()
95+
giskard.achieve_joint_goal(
96+
name_to_position,
97+
align=motion.align,
98+
tip_link=motion.tip_link,
99+
tip_normal=motion.tip_normal,
100+
root_link=motion.root_link,
101+
root_normal=motion.root_normal
102+
)
103+
104+
def map_OpeningMotion(motion):
105+
giskard.achieve_open_container_goal(
106+
RobotDescription.current_robot_description.get_arm_chain(motion.arm).get_tool_frame(),
107+
motion.object_part.name
108+
)
109+
110+
def map_ClosingMotion(motion):
111+
giskard.achieve_close_container_goal(
112+
RobotDescription.current_robot_description.get_arm_chain(motion.arm).get_tool_frame(),
113+
motion.object_part.name
114+
)
115+
116+
def map_MoveTCPWaypointsMotion(motion):
117+
lt = LocalTransformer()
118+
waypoints = [lt.transform_pose(x, "map") for x in motion.waypoints]
119+
tip_link = RobotDescription.current_robot_description.get_arm_chain(motion.arm).get_tool_frame()
120+
root_link = "map"
121+
122+
giskard.avoid_all_collisions()
123+
if motion.allow_gripper_collision:
124+
giskard.allow_gripper_collision(motion.arm)
125+
126+
giskard.achieve_cartesian_waypoints_goal(
127+
waypoints=waypoints,
128+
tip_link=tip_link,
129+
root_link=root_link,
130+
enforce_final_orientation=True if motion.movement_type == WaypointsMovementType.ENFORCE_ORIENTATION_FINAL_POINT else False
131+
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from pycram.external_interfaces import giskard
2+
from pycram.plan import Plan, MotionNode
3+
from pycram.robot_description import RobotDescription
4+
from pycram.robot_plans import BaseMotion
5+
6+
# --- generischer executor ---
7+
def execute_with_giskard(motion: BaseMotion):
8+
func_name = f"map_{type(motion).__name__}"
9+
mapper = globals().get(func_name)
10+
if not callable(mapper):
11+
raise ValueError(f"No Giskard mapper function found for {type(motion).__name__}")
12+
mapper(motion)
13+
14+
def execute_leaf_motions_with_giskard(plan: Plan):
15+
for node in plan.nodes:
16+
if isinstance(node, MotionNode) and not node.children:
17+
print("Executing:", node.designator_ref)
18+
execute_with_giskard(node.designator_ref)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from pycram.robot_plans.motions import MoveMotion
2+
from pycram.external_interfaces import giskard
3+
from pycram.robot_description import RobotDescription
4+

src/pycram/robot_plans/motions/container.py

Lines changed: 61 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,16 @@
22

33
from .base import BaseMotion
44
from ...datastructures.enums import Arms
5+
from ...datastructures.pose import PoseStamped
6+
from ...datastructures.world import World
57
from ...description import ObjectDescription
8+
from ...external_interfaces.ik import request_ik
69
from ...plan import with_plan
710
from ...process_module import ProcessModuleManager
11+
from ...robot_description import RobotDescription
12+
from ...utils import _apply_ik
13+
from ...world_concepts.world_object import Object
14+
from ...world_reasoning import link_pose_for_joint_config
815

916

1017
@with_plan
@@ -24,8 +31,33 @@ class OpeningMotion(BaseMotion):
2431
"""
2532

2633
def perform(self):
27-
pm_manager = ProcessModuleManager().get_manager()
28-
return pm_manager.open().execute(self)
34+
part_of_object = self.object_part.parent_entity
35+
36+
container_joint_name = part_of_object.find_joint_above_link(self.object_part.name)
37+
lower_limit, upper_limit = part_of_object.get_joint_limits(container_joint_name)
38+
39+
goal_pose = link_pose_for_joint_config(part_of_object, {
40+
container_joint_name: max(lower_limit, upper_limit - 0.05)}, self.object_part.name)
41+
42+
self._move_arm_tcp(goal_pose, World.robot, self.arm)
43+
44+
part_of_object.set_joint_position(container_joint_name, upper_limit)
45+
46+
def _move_arm_tcp(target: PoseStamped, robot: Object, arm: Arms, tip_link: str = None) -> None:
47+
"""
48+
Calls the ik solver to calculate the inverse kinematics of the arm and then sets the joint states accordingly.
49+
50+
:param target: Target pose to which the end-effector should move.
51+
:param robot: Robot object representing the robot.
52+
:param arm: Which arm to move
53+
"""
54+
if tip_link is None:
55+
tip_link = RobotDescription.current_robot_description.get_arm_chain(arm).get_tool_frame()
56+
57+
joints = RobotDescription.current_robot_description.get_arm_chain(arm).joints
58+
59+
inv = request_ik(target, robot, joints, tip_link)
60+
_apply_ik(robot, inv)
2961

3062

3163
@with_plan
@@ -45,5 +77,30 @@ class ClosingMotion(BaseMotion):
4577
"""
4678

4779
def perform(self):
48-
pm_manager = ProcessModuleManager().get_manager()
49-
return pm_manager.close().execute(self)
80+
part_of_object = self.object_part.parent_entity
81+
82+
container_joint_name = part_of_object.find_joint_above_link(self.object_part.name)
83+
lower_joint_limit = part_of_object.get_joint_limits(container_joint_name)[0]
84+
85+
goal_pose = link_pose_for_joint_config(part_of_object, {
86+
container_joint_name: lower_joint_limit}, self.object_part.name)
87+
88+
self._move_arm_tcp(goal_pose, World.robot, self.arm)
89+
90+
part_of_object.set_joint_position(container_joint_name, lower_joint_limit)
91+
92+
def _move_arm_tcp(target: PoseStamped, robot: Object, arm: Arms, tip_link: str = None) -> None:
93+
"""
94+
Calls the ik solver to calculate the inverse kinematics of the arm and then sets the joint states accordingly.
95+
96+
:param target: Target pose to which the end-effector should move.
97+
:param robot: Robot object representing the robot.
98+
:param arm: Which arm to move
99+
"""
100+
if tip_link is None:
101+
tip_link = RobotDescription.current_robot_description.get_arm_chain(arm).get_tool_frame()
102+
103+
joints = RobotDescription.current_robot_description.get_arm_chain(arm).joints
104+
105+
inv = request_ik(target, robot, joints, tip_link)
106+
_apply_ik(robot, inv)

src/pycram/robot_plans/motions/gripper.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
from ...datastructures.enums import Arms, GripperState, MovementType, WaypointsMovementType, Frame
66
from ...datastructures.grasp import GraspDescription
77
from ...datastructures.pose import PoseStamped
8+
from ...datastructures.world import World
9+
from ...external_interfaces.ik import request_ik
810
from ...failure_handling import try_motion
911
from ...failures import ToolPoseNotReachedError
1012
from ...local_transformer import LocalTransformer
1113
from ...plan import with_plan
1214
from ...process_module import ProcessModuleManager
15+
from ...robot_description import RobotDescription
16+
from ...utils import _apply_ik
1317
from ...world_concepts.world_object import Object
1418

15-
1619
# class ReachMotion(BaseMotion):
1720
# """
1821
# """
@@ -88,8 +91,15 @@ class MoveGripperMotion(BaseMotion):
8891
"""
8992

9093
def perform(self):
91-
pm_manager = ProcessModuleManager().get_manager()
92-
return pm_manager.move_gripper().execute(self)
94+
robot_description = RobotDescription.current_robot_description
95+
gripper = self.gripper
96+
arm_chain = robot_description.get_arm_chain(gripper)
97+
if arm_chain.end_effector.gripper_object_name is not None:
98+
robot = World.current_world.get_object_by_name(arm_chain.end_effector.gripper_object_name)
99+
else:
100+
robot = World.robot
101+
motion = self.motion
102+
robot.set_multiple_joint_positions(arm_chain.get_static_gripper_state(motion))
93103

94104

95105
@with_plan
@@ -117,9 +127,26 @@ class MoveTCPMotion(BaseMotion):
117127
"""
118128

119129
def perform(self):
120-
pm_manager = ProcessModuleManager().get_manager()
121-
try_motion(pm_manager.move_tcp(), self, ToolPoseNotReachedError)
130+
target = self.target
131+
robot = World.robot
132+
arm = self.arm
133+
self.move_arm_tcp(target=target, robot=robot, arm=arm)
134+
135+
def move_arm_tcp(self, target: PoseStamped, robot: Object, arm: Arms, tip_link: str = None) -> None:
136+
"""
137+
Calls the ik solver to calculate the inverse kinematics of the arm and then sets the joint states accordingly.
122138
139+
:param target: Target pose to which the end-effector should move.
140+
:param robot: Robot object representing the robot.
141+
:param arm: Which arm to move
142+
"""
143+
if tip_link is None:
144+
tip_link = RobotDescription.current_robot_description.get_arm_chain(arm).get_tool_frame()
145+
146+
joints = RobotDescription.current_robot_description.get_arm_chain(arm).joints
147+
148+
inv = request_ik(target, robot, joints, tip_link)
149+
_apply_ik(robot, inv)
123150

124151
@with_plan
125152
@dataclass
@@ -146,5 +173,23 @@ class MoveTCPWaypointsMotion(BaseMotion):
146173
"""
147174

148175
def perform(self):
149-
pm_manager = ProcessModuleManager().get_manager()
150-
pm_manager.move_tcp_waypoints().execute(self)
176+
waypoints = self.waypoints
177+
robot = World.robot
178+
arm = self.arm
179+
for waypoint in waypoints:
180+
self.move_arm_tcp(target=waypoint, robot=robot, arm=arm)
181+
def move_arm_tcp(self, target: PoseStamped, robot: Object, arm: Arms, tip_link: str = None) -> None:
182+
"""
183+
Calls the ik solver to calculate the inverse kinematics of the arm and then sets the joint states accordingly.
184+
185+
:param target: Target pose to which the end-effector should move.
186+
:param robot: Robot object representing the robot.
187+
:param arm: Which arm to move
188+
"""
189+
if tip_link is None:
190+
tip_link = RobotDescription.current_robot_description.get_arm_chain(arm).get_tool_frame()
191+
192+
joints = RobotDescription.current_robot_description.get_arm_chain(arm).joints
193+
194+
inv = request_ik(target, robot, joints, tip_link)
195+
_apply_ik(robot, inv)

src/pycram/robot_plans/motions/navigation.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from .base import BaseMotion
44
from ...datastructures.pose import PoseStamped
5+
from ...datastructures.world import World
56
from ...plan import with_plan
67
from ...process_module import ProcessModuleManager
78

@@ -24,8 +25,8 @@ class MoveMotion(BaseMotion):
2425
"""
2526

2627
def perform(self):
27-
pm_manager = ProcessModuleManager().get_manager()
28-
return pm_manager.navigate().execute(self)
28+
robot = World.robot
29+
robot.set_pose(self.target)
2930

3031

3132
@with_plan

0 commit comments

Comments
 (0)