Skip to content

Commit 47b8d59

Browse files
committed
Merge pull request #152 from personalrobotics/feature/tsr_conversions
Added tsr conversion methods for JSON and YAML.
2 parents aa63713 + b05e913 commit 47b8d59

File tree

3 files changed

+166
-103
lines changed

3 files changed

+166
-103
lines changed

src/prpy/planning/cbirrt.py

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,13 @@
2828
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2929
# POSSIBILITY OF SUCH DAMAGE.
3030

31-
import copy, logging, numpy, openravepy, os, tempfile
31+
import numpy, openravepy
3232
from ..util import SetTrajectoryTags
3333
from base import (BasePlanner, PlanningError, UnsupportedPlanningError,
3434
PlanningMethod, Tags)
3535
import prpy.kin, prpy.tsr
3636

37+
3738
class CBiRRTPlanner(BasePlanner):
3839
def __init__(self):
3940
super(CBiRRTPlanner, self).__init__()
@@ -109,7 +110,7 @@ def PlanToEndEffectorOffset(self, robot, direction, distance,
109110
# 'object frame w' is at ee, z pointed along direction to move
110111
H_world_w = prpy.kin.H_from_op_diff(H_world_ee[0:3,3], direction)
111112
H_w_ee = numpy.dot(prpy.kin.invert_H(H_world_w), H_world_ee)
112-
113+
113114
# Serialize TSR string (goal)
114115
Hw_end = numpy.eye(4)
115116
Hw_end[2,3] = distance
@@ -135,7 +136,7 @@ def PlanToEndEffectorOffset(self, robot, direction, distance,
135136
Bw = Bw,
136137
manip = robot.GetActiveManipulatorIndex())
137138
traj_tsr_chain = prpy.tsr.tsr.TSRChain(constrain=True, TSRs=[trajtsr])
138-
139+
139140
return self.Plan(robot,
140141
psample=0.1,
141142
tsr_chains=[goal_tsr_chain, traj_tsr_chain],
@@ -227,7 +228,7 @@ def Plan(self, robot, smoothingitrs=None, timelimit=None, allowlimadj=0,
227228
robot.GetActiveDOF(), len(start_config)
228229
)
229230
)
230-
231+
231232
args += ['jointstarts'] + self.serialize_dof_values(start_config)
232233

233234
if jointgoals is not None:
@@ -239,12 +240,12 @@ def Plan(self, robot, smoothingitrs=None, timelimit=None, allowlimadj=0,
239240
robot.GetActiveDOF(), len(goal_config)
240241
)
241242
)
242-
243+
243244
args += ['jointgoals'] + self.serialize_dof_values(goal_config)
244245

245246
if tsr_chains is not None:
246247
for tsr_chain in tsr_chains:
247-
args += [ 'TSRChain', tsr_chain.serialize() ]
248+
args += ['TSRChain', SerializeTSRChain(tsr_chain)]
248249

249250
# FIXME: Why can't we write to anything other than cmovetraj.txt or
250251
# /tmp/cmovetraj.txt with CBiRRT?
@@ -258,7 +259,7 @@ def Plan(self, robot, smoothingitrs=None, timelimit=None, allowlimadj=0,
258259

259260
if not response.strip().startswith('1'):
260261
raise PlanningError('Unknown error: ' + response)
261-
262+
262263
# Construct the output trajectory.
263264
with open(traj_path, 'rb') as traj_file:
264265
traj_xml = traj_file.read()
@@ -290,4 +291,75 @@ def serialize_dof_values(dof_values):
290291
return [ str(len(dof_values)),
291292
' '.join([ str(x) for x in dof_values]) ]
292293

293-
294+
295+
def SerializeTransform12Col(tm, format='%.5f'):
296+
return ' '.join([(format % (i,)) for i in tm[0:3, :].T.reshape(12)])
297+
298+
299+
def SerializeArray(a, format='%.5f'):
300+
return ' '.join([(format % (i,)) for i in a.reshape(-1)])
301+
302+
303+
def SerializeTSR(self):
304+
"""
305+
Function for Serializing TSRs for CBIRRT.
306+
307+
SerializeTSR(manipindex,bodyandlink,T0_w,Tw_e,Bw)
308+
309+
Input:
310+
manipindex (int): the 0-indexed index of the robot's manipulator
311+
bodyandlink (str): body and link which is used as the 0 frame. Format
312+
'body_name link_name'. For world frame, specify 'NULL'
313+
T0_w (double 4x4): transform matrix of the TSR's reference frame relative
314+
to the 0 frame
315+
Tw_e (double 4x4): transform matrix of the TSR's offset frame relative to
316+
the w frame
317+
Bw (double 1x12): bounds in x y z roll pitch yaw.
318+
Format: [x_min, x_max, y_min, y_max ...]
319+
320+
Output:
321+
outstring (str): string to use for SerializeTSRChain function
322+
"""
323+
return '%d %s %s %s %s' % (self.manipindex, self.bodyandlink,
324+
SerializeTransform12Col(self.T0_w),
325+
SerializeTransform12Col(self.Tw_e),
326+
SerializeArray(self.Bw))
327+
328+
329+
def SerializeTSRChain(self):
330+
"""
331+
Function for Serializing TSR Chains for CBIRRT.
332+
333+
_SerializeTSRChain(bSampleFromChain, bConstrainToChain,
334+
numTSRs, allTSRstring,
335+
mimicbodyname, mimicbodyjoints)
336+
337+
Input:
338+
bSampleStartFromChain (0/1): 1: Use this chain for sampling start configs
339+
0: Ignore for sampling starts
340+
bSampleGoalFromChain (0/1): 1: Use this chain for sampling goal configs
341+
0: Ignore for sampling goals
342+
bConstrainToChain (0/1): 1: Use this chain for constraining configs
343+
0: Ignore for constraining
344+
numTSRs (int): Number of TSRs in this chain (must be > 0)
345+
allTSRstring (str): string of concatenated TSRs from SerializeTSR.
346+
Should be like [TSRstring 1 ' ' TSRstring2 ...]
347+
mimicbodyname (str): name of associated mimicbody for this chain
348+
(NULL if none associated)
349+
mimicbodyjoints (int [1xn]): 0-indexed indices of mimicbody's joints that
350+
are mimiced (INCREASING AND CONSECUTIVE)
351+
352+
Output:
353+
outstring (str): string to include in call to cbirrt planner
354+
"""
355+
allTSRstring = ' '.join([SerializeTSR(tsr) for tsr in self.TSRs])
356+
numTSRs = len(self.TSRs)
357+
outstring = '%d %d %d' % (int(self.sample_start),
358+
int(self.sample_goal),
359+
int(self.constrain))
360+
outstring += ' %d %s' % (numTSRs, allTSRstring)
361+
outstring += ' ' + self.mimicbodyname
362+
if len(self.mimicbodyjoints) > 0:
363+
outstring += ' %d %s' % (len(self.mimicbodyjoints),
364+
SerializeArray(self.mimicbodyjoints))
365+
return outstring

src/prpy/serialization.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@ def serialize(obj):
7070
elif isinstance(obj, TSR):
7171
return {
7272
TYPE_KEY: TSR.__name__,
73-
'data': obj.serialize_dict()
73+
'data': obj.to_dict()
7474
}
7575
elif isinstance(obj, TSRChain):
7676
return {
7777
TYPE_KEY: TSRChain.__name__,
78-
'data': obj.serialize_dict()
78+
'data': obj.to_dict()
7979
}
8080
else:
8181
raise UnsupportedTypeSerializationException(obj)
@@ -261,9 +261,9 @@ def _deserialize_internal(env, data, data_type):
261261
traj.deserialize(data['data'])
262262
return traj
263263
elif data_type == TSR.__name__:
264-
return TSR.deserialize_dict(data['data'])
264+
return TSR.from_dict(data['data'])
265265
elif data_type == TSRChain.__name__:
266-
return TSRChain.deserialize_dict(data['data'])
266+
return TSRChain.from_dict(data['data'])
267267
else:
268268
raise UnsupportedTypeDeserializationException(data_type)
269269

src/prpy/tsr/tsr.py

Lines changed: 82 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -25,72 +25,14 @@
2525
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2626
# POSSIBILITY OF SUCH DAMAGE.
2727

28-
#!/usr/bin/env python
29-
# -*- coding: utf-8 -*-
30-
31-
# @package libherb.tsr Utilities for TSRs and TSR chains.
32-
3328
import openravepy
3429
import numpy
3530
import numpy.random
3631
import kin
3732

38-
"""
39-
Functions for Serializing TSRs and TSR Chains
40-
41-
SerializeTSR(manipindex,bodyandlink,T0_w,Tw_e,Bw)
42-
43-
Input:
44-
manipindex (int): the 0-indexed index of the robot's manipulator
45-
bodyandlink (str): body and link which is used as the 0 frame. Format
46-
'body_name link_name'. To use world frame, specify 'NULL'
47-
T0_w (double 4x4): transform matrix of the TSR's reference frame relative to
48-
the 0 frame
49-
Tw_e (double 4x4): transform matrix of the TSR's offset frame relative to the
50-
w frame
51-
Bw (double 1x12): bounds in x y z roll pitch yaw.
52-
Format: [x_min, x_max, y_min, y_max ...]
53-
54-
Output:
55-
outstring (str): string to use for SerializeTSRChain function
56-
57-
SerializeTSRChain(bSampleFromChain,
58-
bConstrainToChain,
59-
numTSRs,
60-
allTSRstring,
61-
mimicbodyname,
62-
mimicbodyjoints)
63-
64-
Input:
65-
bSampleStartFromChain (0/1): 1: Use this chain for sampling start configs
66-
0: Ignore for sampling starts
67-
bSampleGoalFromChain (0/1): 1: Use this chain for sampling goal configs
68-
0: Ignore for sampling goals
69-
bConstrainToChain (0/1): 1: Use this chain for constraining configs
70-
0: Ignore for constraining
71-
numTSRs (int): Number of TSRs in this chain (must be > 0)
72-
allTSRstring (str): string of concetenated TSRs generated using SerializeTSR.
73-
Should be like [TSRstring 1 ' ' TSRstring2 ...]
74-
mimicbodyname (str): name of associated mimicbody for this chain
75-
(NULL if none associated)
76-
mimicbodyjoints (int [1xn]): 0-indexed indices of the mimicbody's joints that
77-
are mimiced (MUST BE INCREASING AND CONSECUTIVE)
78-
79-
Output:
80-
outstring (str): string to include in call to cbirrt planner
81-
"""
82-
83-
84-
def SerializeTransform12Col(tm, format='%.5f'):
85-
return ' '.join([(format % (i,)) for i in tm[0:3, :].T.reshape(12)])
86-
87-
88-
def SerializeArray(a, format='%.5f'):
89-
return ' '.join([(format % (i,)) for i in a.reshape(-1)])
90-
91-
92-
class TSR(object): # force new-style class
9333

34+
class TSR(object):
35+
""" A Task-Space-Region (TSR) represents a motion constraint. """
9436
def __init__(self, T0_w=None, Tw_e=None, Bw=None,
9537
manip=None, bodyandlink='NULL'):
9638
if T0_w is None:
@@ -140,13 +82,8 @@ def sample(self, vals=None):
14082
trans = numpy.dot(numpy.dot(self.T0_w, Tw), self.Tw_e)
14183
return trans
14284

143-
def serialize(self):
144-
return '%d %s %s %s %s' % (self.manipindex, self.bodyandlink,
145-
SerializeTransform12Col(self.T0_w),
146-
SerializeTransform12Col(self.Tw_e),
147-
SerializeArray(self.Bw))
148-
149-
def serialize_dict(self):
85+
def to_dict(self):
86+
""" Convert this TSR to a python dict. """
15087
return {
15188
'T0_w': self.T0_w.tolist(),
15289
'Tw_e': self.Tw_e.tolist(),
@@ -156,15 +93,49 @@ def serialize_dict(self):
15693
}
15794

15895
@staticmethod
159-
def deserialize_dict(x):
96+
def from_dict(x):
97+
""" Construct a TSR from a python dict. """
16098
return TSR(
161-
T0_w = numpy.array(x['T0_w']),
162-
Tw_e = numpy.array(x['Tw_e']),
163-
Bw = numpy.array(x['Bw']),
164-
manip = numpy.array(x['manipindex']),
165-
bodyandlink = numpy.array(x['bodyandlink'])
99+
T0_w=numpy.array(x['T0_w']),
100+
Tw_e=numpy.array(x['Tw_e']),
101+
Bw=numpy.array(x['Bw']),
102+
manip=numpy.array(x.get('manipindex', -1)),
103+
bodyandlink=numpy.array(x.get('bodyandlink', 'NULL'))
166104
)
167105

106+
def to_json(self):
107+
""" Convert this TSR to a JSON string. """
108+
import json
109+
return json.dumps(self.to_dict())
110+
111+
@staticmethod
112+
def from_json(x, *args, **kw_args):
113+
"""
114+
Construct a TSR from a JSON string.
115+
116+
This method internally forwards all arguments to `json.loads`.
117+
"""
118+
import json
119+
x_dict = json.loads(x, *args, **kw_args)
120+
return TSR.from_dict(x_dict)
121+
122+
def to_yaml(self):
123+
""" Convert this TSR to a YAML string. """
124+
import yaml
125+
return yaml.dumps(self.to_dict())
126+
127+
@staticmethod
128+
def from_yaml(x, *args, **kw_args):
129+
"""
130+
Construct a TSR from a YAML string.
131+
132+
This method internally forwards all arguments to `yaml.safe_load`.
133+
"""
134+
import yaml
135+
x_dict = yaml.safe_load(x, *args, **kw_args)
136+
return TSR.from_dict(x_dict)
137+
138+
168139
class TSRChain(object):
169140

170141
def __init__(self, sample_start=False, sample_goal=False, constrain=False,
@@ -205,41 +176,61 @@ def __init__(self, sample_start=False, sample_goal=False, constrain=False,
205176
def append(self, tsr):
206177
self.TSRs.append(tsr)
207178

208-
def serialize(self):
209-
allTSRstring = ' '.join([tsr.serialize() for tsr in self.TSRs])
210-
numTSRs = len(self.TSRs)
211-
outstring = '%d %d %d' % (int(self.sample_start),
212-
int(self.sample_goal),
213-
int(self.constrain))
214-
outstring += ' %d %s' % (numTSRs, allTSRstring)
215-
outstring += ' ' + self.mimicbodyname
216-
if len(self.mimicbodyjoints) > 0:
217-
outstring += ' %d %s' % (len(self.mimicbodyjoints),
218-
SerializeArray(self.mimicbodyjoints))
219-
return outstring
220-
221-
def serialize_dict(self):
179+
def to_dict(self):
180+
""" Construct a TSR chain from a python dict. """
222181
return {
223182
'sample_goal': self.sample_goal,
224183
'sample_start': self.sample_start,
225184
'constrain': self.constrain,
226185
'mimicbodyname': self.mimicbodyname,
227186
'mimicbodyjoints': self.mimicbodyjoints,
228-
'tsrs': [ tsr.serialize_dict() for tsr in self.TSRs ],
187+
'tsrs': [tsr.to_dict() for tsr in self.TSRs],
229188
}
230189

231-
232190
@staticmethod
233-
def deserialize_dict(x):
191+
def from_dict(x):
192+
""" Construct a TSR chain from a python dict. """
234193
return TSRChain(
235194
sample_start=x['sample_start'],
236195
sample_goal=x['sample_goal'],
237196
constrain=x['constrain'],
238-
TSRs=[ TSR.deserialize_dict(tsr) for tsr in x['tsrs'] ],
197+
TSRs=[TSR.from_dict(tsr) for tsr in x['tsrs']],
239198
mimicbodyname=x['mimicbodyname'],
240199
mimicbodyjoints=x['mimicbodyjoints'],
241200
)
242201

202+
def to_json(self):
203+
""" Convert this TSR chain to a JSON string. """
204+
import json
205+
return json.dumps(self.to_dict())
206+
207+
@staticmethod
208+
def from_json(x, *args, **kw_args):
209+
"""
210+
Construct a TSR chain from a JSON string.
211+
212+
This method internally forwards all arguments to `json.loads`.
213+
"""
214+
import json
215+
x_dict = json.loads(x, *args, **kw_args)
216+
return TSR.from_dict(x_dict)
217+
218+
def to_yaml(self):
219+
""" Convert this TSR chain to a YAML string. """
220+
import yaml
221+
return yaml.dumps(self.to_dict())
222+
223+
@staticmethod
224+
def from_yaml(x, *args, **kw_args):
225+
"""
226+
Construct a TSR chain from a YAML string.
227+
228+
This method internally forwards all arguments to `yaml.safe_load`.
229+
"""
230+
import yaml
231+
x_dict = yaml.safe_load(x, *args, **kw_args)
232+
return TSR.from_dict(x_dict)
233+
243234
def sample(self):
244235
if len(self.TSRs) == 0:
245236
return None

0 commit comments

Comments
 (0)