Skip to content

Commit 939a000

Browse files
authored
Merge pull request #57 from pollen-robotics/56-more-control-over-ik-behaviors-from-grpc-level
56 more control over ik behaviors from grpc level
2 parents f95b0eb + 9a23bc0 commit 939a000

File tree

4 files changed

+115
-3
lines changed

4 files changed

+115
-3
lines changed

pollen_kdl_kinematics/pollen_kdl_kinematics/pollen_kdl_kinematics_node.py

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import rclpy
99
from geometry_msgs.msg import Pose, PoseStamped
1010
from pollen_msgs.srv import GetForwardKinematics, GetInverseKinematics
11+
from pollen_msgs.msg import IKRequest, ReachabilityState
1112
from rclpy.lifecycle import LifecycleNode, State, TransitionCallbackReturn
1213
from rclpy.qos import (HistoryPolicy, QoSDurabilityPolicy, QoSProfile,
1314
ReliabilityPolicy)
@@ -21,7 +22,6 @@
2122
limit_orbita3d_joints,
2223
limit_orbita3d_joints_wrist,
2324
limit_theta_to_interval,
24-
tend_to_prefered_theta,
2525
get_best_theta_to_current_joints,)
2626
from scipy.spatial.transform import Rotation
2727
from sensor_msgs.msg import JointState
@@ -56,7 +56,9 @@ def __init__(self):
5656

5757
self.chain, self.fk_solver, self.ik_solver = {}, {}, {}
5858
self.fk_srv, self.ik_srv = {}, {}
59+
self.reachability_pub = {}
5960
self.target_sub, self.averaged_target_sub = {}, {}
61+
self.ik_target_sub = {}
6062
self.averaged_pose = {}
6163
self.max_joint_vel = {}
6264

@@ -129,10 +131,18 @@ def __init__(self):
129131
qos_profile=5,
130132
)
131133

134+
self.reachability_pub[arm] = self.create_publisher(
135+
msg_type=ReachabilityState,
136+
topic=f"/{arm}_reachability_states",
137+
qos_profile=10,
138+
)
139+
132140
if arm.startswith("l"):
133141
q0 = [0.0, np.pi / 2, 0.0, -np.pi / 2, 0.0, 0.0, 0.0]
134142
else:
135143
q0 = [0.0, -np.pi / 2, 0.0, -np.pi / 2, 0.0, 0.0, 0.0]
144+
145+
# Keeping both on _target_pose mechanisms for compatibility reasons
136146
self.target_sub[arm] = self.create_subscription(
137147
msg_type=PoseStamped,
138148
topic=f"/{arm}/target_pose",
@@ -149,6 +159,18 @@ def __init__(self):
149159
)
150160
self.logger.info(f'Adding subscription on "{self.target_sub[arm].topic}"...')
151161

162+
self.ik_target_sub[arm] = self.create_subscription(
163+
msg_type=IKRequest,
164+
topic=f"/{arm}/ik_target_pose",
165+
qos_profile=high_freq_qos_profile,
166+
callback=partial(
167+
self.on_ik_target_pose,
168+
name=arm,
169+
forward_publisher=forward_position_pub,
170+
),
171+
)
172+
self.logger.info(f'Adding subscription on "{self.ik_target_sub[arm].topic}"...')
173+
152174
self.averaged_target_sub[arm] = self.create_subscription(
153175
msg_type=PoseStamped,
154176
topic=f"/{arm}/averaged_target_pose",
@@ -371,7 +393,7 @@ def inverse_kinematics_srv(
371393
M,
372394
"discrete",
373395
current_joints=current_joints,
374-
interval_limit=[-np.pi, np.pi],
396+
constrained_mode="unconstrained",
375397
current_pose=current_pose
376398
)
377399
# # self.logger.info(M)
@@ -394,8 +416,65 @@ def inverse_kinematics_srv(
394416

395417
return response
396418

419+
def on_ik_target_pose(self, msg: IKRequest, name, forward_publisher):
420+
M = ros_pose_to_matrix(msg.pose.pose)
421+
constrained_mode = msg.constrained_mode
422+
continuous_mode = msg.continuous_mode
423+
preferred_theta = msg.preferred_theta
424+
d_theta_max = msg.d_theta_max
425+
order_id = msg.order_id
426+
427+
if continuous_mode == "undefined":
428+
continuous_mode = "continuous"
429+
430+
if constrained_mode == "undefined":
431+
constrained_mode = "unconstrained"
432+
433+
# if constrained_mode == "low_elbow":
434+
# interval_limit = [-4 * np.pi / 5, 0]
435+
# self.logger.info(f"Preferred theta: {preferred_theta}")
436+
# self.logger.info(f"Continuous mode: {continuous_mode}")
437+
# self.logger.info(f"Constrained mode: {constrained_mode}")
438+
# self.logger.info(f"Order ID: {order_id}")
439+
# self.logger.info(f"Max d_theta: {d_theta_max}")
440+
441+
if "arm" in name:
442+
current_joints = self.get_current_position(self.chain[name])
443+
error, current_pose = forward_kinematics(
444+
self.fk_solver[name],
445+
current_joints,
446+
self.chain[name].getNrOfJoints(),
447+
)
448+
449+
sol, is_reachable, state = self.control_ik.symbolic_inverse_kinematics(
450+
name,
451+
M,
452+
continuous_mode,
453+
current_joints=current_joints,
454+
constrained_mode=constrained_mode,
455+
current_pose=current_pose,
456+
d_theta_max=d_theta_max,
457+
preferred_theta=preferred_theta,
458+
)
459+
else:
460+
self.logger.error("IK target pose should be only for the arms")
461+
raise ValueError("IK target pose should be only for the arms")
462+
463+
msg = Float64MultiArray()
464+
msg.data = sol
465+
forward_publisher.publish(msg)
466+
reachability_msg = ReachabilityState()
467+
reachability_msg.header.stamp = self.get_clock().now().to_msg()
468+
reachability_msg.header.frame_id = "torso"
469+
reachability_msg.is_reachable = is_reachable
470+
reachability_msg.state = state
471+
reachability_msg.order_id = order_id
472+
self.reachability_pub[name].publish(reachability_msg)
473+
474+
397475
def on_target_pose(self, msg: PoseStamped, name, q0, forward_publisher):
398476
M = ros_pose_to_matrix(msg.pose)
477+
399478
if "arm" in name:
400479
current_joints = self.get_current_position(self.chain[name])
401480
error, current_pose = forward_kinematics(
@@ -408,7 +487,7 @@ def on_target_pose(self, msg: PoseStamped, name, q0, forward_publisher):
408487
M,
409488
"continuous",
410489
current_joints=current_joints,
411-
interval_limit=[-4 * np.pi / 5, 0],
490+
constrained_mode="low_elbow", # "unconstrained"
412491
current_pose=current_pose
413492
)
414493
else:

pollen_msgs/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ rosidl_generate_interfaces(${PROJECT_NAME}
2626
"msg/GotoFeedback.msg"
2727
"msg/GotoRequest.msg"
2828
"msg/GotoResult.msg"
29+
"msg/IKRequest.msg"
30+
"msg/ReachabilityState.msg"
2931

3032
"action/Goto.action"
3133

pollen_msgs/msg/IKRequest.msg

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# 6d goal pose
2+
geometry_msgs/PoseStamped pose
3+
4+
# Current options are "unconstrained" and "low_elbow"
5+
string constrained_mode
6+
7+
# Value in [-pi, pi], angle of the elbow that the IK will try to obtain
8+
# The value should be the same for both arms - IK will adapt this value for the left arm
9+
# Examples :
10+
# -4pi/6 - Default value
11+
# -5pi/6 - with this value the elbows are a bit higher
12+
13+
float64 preferred_theta
14+
15+
# When in continuous mode this is the maximum amount of rads that the elbow can rotate on the reachability circle
16+
# Common value : 0.01
17+
float64 d_theta_max
18+
19+
# Current options are "continuous" and "discrete"
20+
string continuous_mode
21+
22+
# When present this value must be unic for each message and it will be used to identify reachability information for a given request
23+
int64 order_id
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
std_msgs/Header header
2+
3+
#it will be used to identify reachability information for a given request
4+
int64 order_id
5+
6+
bool is_reachable
7+
8+
string state

0 commit comments

Comments
 (0)