Skip to content
Open
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/prpy/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2129,3 +2129,50 @@ def GetPointFrom(focus):
raise ValueError('Focus of the point is an unknown object')

return coord

def concatenateTrajectories(traj_list):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We follow OpenRAVE's naming convention by using PascalCase instead of camelCase.

"""
Given a list of trajectories for a single manipulator,
concatenate them into a single trajectory

@param traj_list List of consective trajectories for a given manipulator
@return base_traj Combined trajectory
"""
from planning.base import Tags

if len(traj_list) == 0:
raise ValueError('Trajectory list is empty')

base_traj = traj_list[0]
base_cspec = base_traj.GetConfigurationSpecification()
base_robot = base_cspec.ExtractUsedBodies(base_traj.GetEnv())[0]
traj_indices = GetTrajectoryIndices(base_traj)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest strictly handling the case where all of the trajectories have exactly the same ConfigurationSpecification. Anything else opens a huge can of worms.


offset = base_traj.GetNumWaypoints()
for i in xrange(1, len(traj_list)):
traj_i = traj_list[i]
cspec_i = traj_i.GetConfigurationSpecification()
robot_i = cspec_i.ExtractUsedBodies(traj_i.GetEnv())[0]
if robot_i != base_robot:
raise ValueError('Trajectories are not on the same robot')

sub = numpy.subtract(GetTrajectoryIndices(traj_i), traj_indices)
if sub.sum() != 0:
raise ValueError('Trajectories are not on the same manipulator.')

tags_i = GetTrajectoryTags(traj_i)
# If one segment is not smooth, the entire trajectory is not (?)
if 'smooth' in tags_i and not tags_i['smooth']:
SetTrajectoryTags(base_traj, {TAGS.SMOOTH: True}, append=True)

# The entire trajectory gets tagged as constrained if one of
# the segments is constrained.
if 'constrained' in tags_i and tags_i['constrained']:
SetTrajectoryTags(base_traj, {TAGS.CONSTRAINED: True}, append=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace these repeated calls to SetTrajectoryTags with one call at the end. The current logic is incorrect because it will tag a trajectory as SMOOTH if any of its components are smooth, instead of only when all of its components are smooth.

We're also missing a few cases. To be complete, here are all of the tags we should handle:

  • SMOOTH: True if all trajectories have this flag set
  • CONSTRAINED: True if any trajectory has this flag set
  • DETERMINISTIC_TRAJECTORY: True if all trajectories have this flag set
  • DETERMINISTIC_ENDPOINT: True if the last trajectory has this flag set

All of the flags should default to False if they are not set on a trajectory.

Also, note that setting these tags is a surprisingly expensive operation. It requires parsing XML, parsing JSON, re-serializing JSON, and re-serializing XML.


# Add trajectory in by inserting each waypoint
for j in xrange(traj_i.GetNumWaypoints()):
waypoint = traj_i.GetWaypoint(j)
base_traj.Insert(offset, waypoint)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, this would break if the trajectories did not already have the same ConfigurationSpecification.

offset += 1
return base_traj