Skip to content

Commit 2cca672

Browse files
author
David Conner
committed
modify manipulation states to add timeout and other parameters (based on #11)
* modify manipulation states * add most basic state import tests * add timeout outcome to constructor * Added velocity and acceleration scaling factors of 1 to moveit dyn goal to fix bug in TOTG which crashes with the default 0. (#13)
1 parent dc9a14b commit 2cca672

16 files changed

+141
-12
lines changed

flexbe_manipulation_states/flexbe_manipulation_states/get_joint_values_dyn_state.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
@author: Alberto Romay
3737
"""
3838

39+
from rclpy.duration import Duration
40+
3941
from flexbe_core import EventState
4042
from flexbe_core.proxy import ProxySubscriberCached
4143

@@ -45,31 +47,44 @@
4547
class GetJointValuesDynState(EventState):
4648
"""
4749
Retrieves current values of specified joints.
50+
In this version, specified joint names are passed by user data
51+
52+
-- timeout double Timeout value (optional)
53+
54+
-- joint_states_topic string Optional name of joint states topic
55+
(default: /joint_states)
4856
49-
># joint_names string[] List of desired joint names.
57+
># joint_names string[] List of desired joint names.
5058
51-
#> joint_values float[] List of current joint values.
59+
#> joint_values float[] List of current joint values.
5260
5361
<= retrieved Joint values are available.
62+
<= timeout Joint values are not available.
5463
5564
"""
5665

57-
def __init__(self):
66+
def __init__(self, timeout=None, joint_states_topic='/joint_states'):
5867
"""
5968
Constructor
6069
"""
6170
super().__init__(
62-
outcomes=['retrieved'],
71+
outcomes=['retrieved', 'timeout'],
6372
output_keys=['joint_values'],
6473
input_keys=['joint_names'])
6574

66-
self._topic = '/joint_states'
75+
self._topic = joint_states_topic
6776
self._sub = ProxySubscriberCached({self._topic: JointState}, inst_id=id(self))
6877

6978
self._joints = None
7079
self._joint_values = []
80+
self._return_code = None
81+
self._timeout = Duration(seconds=timeout)
7182

7283
def execute(self, userdata):
84+
if (self._return_code is not None):
85+
# Handle blocked transition or error during on_enter
86+
return self._return_code
87+
7388
while self._sub.has_buffered(self._topic):
7489
msg = self._sub.get_from_buffer(self._topic)
7590
for i, jnt_name in enumerate(msg.name):
@@ -78,12 +93,21 @@ def execute(self, userdata):
7893

7994
if all(v is not None for v in self._joint_values):
8095
userdata.joint_values = self._joint_values
96+
self._return_code = 'retrieved'
8197
return 'retrieved'
8298

99+
if (self._timeout is not None
100+
and (self.get_clock().now() - self._start_time) > self._timeout):
101+
self._return_code = 'timeout'
102+
return 'timeout'
103+
83104
def on_enter(self, userdata):
84105
self._sub.enable_buffer(self._topic)
85106
self._joint_values = [None] * len(self._joints)
86107
self._joints = userdata.joint_names
108+
self._return_code = None
109+
self._start_time = self.get_clock().now()
110+
userdata.joint_values = None
87111

88112
def on_exit(self, userdata):
89113
self._sub.disable_buffer(self._topic)

flexbe_manipulation_states/flexbe_manipulation_states/get_joint_values_state.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@
3636
@author: Philipp Schillinger
3737
"""
3838

39+
from rclpy.duration import Duration
40+
3941
from flexbe_core import EventState
4042
from flexbe_core.proxy import ProxySubscriberCached
4143

@@ -46,28 +48,37 @@ class GetJointValuesState(EventState):
4648
"""
4749
Retrieves current values of specified joints.
4850
49-
-- joints string[] List of desired joint names.
51+
-- joints string[] List of desired joint names.
52+
-- timeout double Timeout value (optional)
53+
-- joint_states_topic string Optional name of joint states topic
54+
(default: /joint_states)
5055
5156
#> joint_values float[] List of current joint values.
5257
5358
<= retrieved Joint values are available.
5459
5560
"""
5661

57-
def __init__(self, joints):
62+
def __init__(self, joints, timeout=None, joint_states_topic='/joint_states'):
5863
"""
5964
Constructor
6065
"""
61-
super().__init__(outcomes=['retrieved'],
66+
super().__init__(outcomes=['retrieved', 'timeout'],
6267
output_keys=['joint_values'])
6368

64-
self._topic = '/joint_states'
69+
self._topic = joint_states_topic
6570
self._sub = ProxySubscriberCached({self._topic: JointState}, inst_id=id(self))
6671

6772
self._joints = joints
6873
self._joint_values = []
74+
self._return_code = None
75+
self._timeout = Duration(seconds=timeout)
6976

7077
def execute(self, userdata):
78+
if (self._return_code is not None):
79+
# Handle blocked transition or error during on_enter
80+
return self._return_code
81+
7182
while self._sub.has_buffered(self._topic):
7283
msg = self._sub.get_from_buffer(self._topic)
7384
for i, jnt_name in enumerate(msg.name):
@@ -76,11 +87,20 @@ def execute(self, userdata):
7687

7788
if all(v is not None for v in self._joint_values):
7889
userdata.joint_values = self._joint_values
90+
self._return_code = 'retrieved'
7991
return 'retrieved'
8092

93+
if (self._timeout is not None
94+
and (self.get_clock().now() - self._start_time) > self._timeout):
95+
self._return_code = 'timeout'
96+
return 'timeout'
97+
8198
def on_enter(self, userdata):
8299
self._sub.enable_buffer(self._topic)
83100
self._joint_values = [None] * len(self._joints)
101+
self._return_code = None
102+
self._start_time = self.get_clock().now()
103+
userdata.joint_values = None
84104

85105
def on_exit(self, userdata):
86106
self._sub.disable_buffer(self._topic)

flexbe_manipulation_states/flexbe_manipulation_states/get_joints_from_srdf_group.py

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ class GetJointsFromSrdfGroup(EventState):
5454
-- robot_name string Optional name of the robot to be used.
5555
If left empty, the first one found will be used
5656
(only required if multiple robots are specified in the same file).
57+
-- srdf_name string Optional name of the srdf parameter
58+
(default: "/robot_description_semantic")
5759
5860
#> joint_names string[] List of joint values for the requested group.
5961
@@ -62,7 +64,7 @@ class GetJointsFromSrdfGroup(EventState):
6264
6365
"""
6466

65-
def __init__(self, move_group, robot_name=""):
67+
def __init__(self, move_group, robot_name="", srdf_name="/robot_description_semantic"):
6668
"""
6769
Constructor
6870
"""
@@ -71,23 +73,31 @@ def __init__(self, move_group, robot_name=""):
7173

7274
self._move_group = move_group
7375
self._robot_name = robot_name
76+
self._srdf_name = srdf_name
7477

7578
# Check existence of SRDF parameter.
7679
# Values will only be read during runtime to allow modifications.
7780
self._srdf_param = None
7881
try:
79-
self._srdf_param = self._node.get_parameter('/robot_description_semantic')
82+
self._srdf_param = self._node.get_parameter(self._srdf_name)
8083
except ParameterNotDeclaredException:
81-
Logger.logerr('Unable to get parameter: /robot_description_semantic')
84+
Logger.logerr(f"Unable to get srdf parameter: '{self._srdf_name}'")
8285

8386
self._param_error = False
8487
self._file_error = False
8588
self._srdf = None
89+
self._return_code = None
8690

8791
def execute(self, userdata):
8892
""" execute the state """
93+
if (self._return_code is not None):
94+
# Handle blocked transition or error during on_enter
95+
return self._return_code
96+
8997
if self._param_error:
98+
self._return_code = 'param_error'
9099
return 'param_error'
100+
91101
robot = None
92102
for rbt in self._srdf.iter('robot'):
93103
if self._robot_name in ('', rbt.attrib['name']):
@@ -96,6 +106,7 @@ def execute(self, userdata):
96106
if robot is None:
97107
Logger.logwarn(f'Did not find robot name in SRDF: {self._robot_name}')
98108
self._param_error = True
109+
self._return_code = 'param_error'
99110
return 'param_error'
100111

101112
group = None
@@ -107,25 +118,39 @@ def execute(self, userdata):
107118
if group is None:
108119
Logger.logwarn(f'Did not find group name in SRDF: {self._move_group}')
109120
self._param_error = True
121+
self._return_code = 'param_error'
110122
return 'param_error'
111123

112124
try:
113125
userdata.joint_names = [str(j.attrib['name']) for j in group.iter('joint')]
114126
except Exception as exc: # pylint: disable=W0703
115127
Logger.logwarn(f'Unable to parse joint values from SRDF:\n{str(exc)}')
116128
self._param_error = True
129+
self._return_code = 'param_error'
117130
return 'param_error'
118131

132+
self._return_code = 'retrieved'
119133
return 'retrieved'
120134

121135
def on_enter(self, userdata):
122136
# Parameter check
123137
if self._srdf_param is None:
124138
self._param_error = True
139+
self._return_code = 'param_error'
140+
return
141+
142+
try:
143+
self._srdf_param = self._node.get_parameter(self._srdf_name)
144+
except ParameterNotDeclaredException:
145+
Logger.logerr(f"Unable to get srdf parameter: '{self._srdf_name}'")
146+
self._param_error = True
147+
self._return_code = 'param_error'
125148
return
126149

127150
try:
128151
self._srdf = ET.fromstring(self._srdf_param)
129152
except Exception as exc: # pylint: disable=W0703
130153
Logger.logwarn(f'Unable to parse given SRDF parameter: /robot_description_semantic\n{exc}')
131154
self._param_error = True
155+
self._return_code = 'param_error'
156+
return

flexbe_manipulation_states/flexbe_manipulation_states/moveit_to_joints_dyn_state.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ def on_enter(self, userdata):
123123

124124
action_goal = MoveGroup_Goal()
125125
action_goal.request.group_name = self._move_group
126+
action_goal.request.max_velocity_scaling_factor = 1
127+
action_goal.request.max_acceleration_scaling_factor = 1
128+
126129
goal_constraints = Constraints()
127130
for i, jnt_name in enumerate(self._joint_names):
128131
goal_constraints.joint_constraints.append(JointConstraint(joint_name=jnt_name,

flexbe_manipulation_states/flexbe_manipulation_states/moveit_to_joints_state.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ def on_enter(self, userdata):
120120

121121
action_goal = MoveGroup_Goal()
122122
action_goal.request.group_name = self._move_group
123+
action_goal.request.max_velocity_scaling_factor = 1
124+
action_goal.request.max_acceleration_scaling_factor = 1
123125
goal_constraints = Constraints()
124126
for i, jnt_name in enumerate(self._joint_names):
125127
goal_constraints.joint_constraints.append(JointConstraint(joint_name=jnt_name,
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Declare state to be tested
2+
path: flexbe_manipulation_states.get_joint_values_dyn_state
3+
class: GetJointValuesDynState
4+
5+
import_only: True
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Declare state to be tested
2+
path: flexbe_manipulation_states.get_joint_values_state
3+
class: GetJointValuesState
4+
5+
import_only: True
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Declare state to be tested
2+
path: flexbe_manipulation_states.get_joints_from_srdf_group
3+
class: GetJointsFromSrdfGroup
4+
5+
import_only: True
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Declare state to be tested
2+
path: flexbe_manipulation_states.get_joints_from_srdf_state
3+
class: GetJointsFromSrdfState
4+
5+
import_only: True
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Declare state to be tested
2+
path: flexbe_manipulation_states.joint_state_to_moveit
3+
class: JointStateToMoveit
4+
5+
import_only: True

0 commit comments

Comments
 (0)