Skip to content

Commit 03ed480

Browse files
committed
Merge pull request #166 from personalrobotics/feature/bodypoint_acceleration_helper_functions
Helper functions for computing body point acceleration twists.
2 parents 8d308d8 + efa120a commit 03ed480

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed

src/prpy/util.py

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -900,3 +900,195 @@ def IsInCollision(traj, robot, selfcoll_only=False):
900900
return True
901901

902902
return False
903+
904+
905+
def JointStatesFromTraj(robot, traj, times, derivatives=[0, 1, 2]):
906+
"""
907+
Helper function to extract the joint position, velocity and acceleration
908+
from an OpenRAVE trajectory.
909+
@param robot The OpenRAVE robot
910+
@param traj An OpenRAVE trajectory
911+
@param times List of times in seconds
912+
@param derivatives list of desired derivatives defaults to [0, 1, 2]
913+
@return pva_list List of list of derivatives at specified times.
914+
Inserts 'None' for unavailable or undesired fields
915+
The i-th element is the derivatives[i]-th derivative
916+
of position of size |times| x |derivatives|
917+
918+
"""
919+
duration = traj.GetDuration()
920+
921+
times = numpy.array(times)
922+
if any(times > duration):
923+
raise ValueError('Input times {0:} exceed duration {1:.2f}'
924+
.format(times, duration))
925+
926+
cspec = traj.GetConfigurationSpecification()
927+
num_dofs = robot.GetDOF()
928+
dof_indices = range(num_dofs)
929+
930+
pva_list = []
931+
for t in times:
932+
pva = [None] * len(derivatives)
933+
trajdata = traj.Sample(t)
934+
for i, deriv in enumerate(derivatives):
935+
pva[i] = cspec.ExtractJointValues(trajdata, robot, dof_indices, deriv)
936+
pva_list.append(pva)
937+
938+
return pva_list
939+
940+
941+
def JointStateFromTraj(robot, traj, time, derivatives=[0, 1, 2]):
942+
"""
943+
Helper function to extract the joint position, velocity and acceleration
944+
from an OpenRAVE trajectory.
945+
@param robot The OpenRAVE robot
946+
@param traj An OpenRAVE trajectory
947+
@param time time in seconds
948+
@param derivatives list of desired derivatives defaults to [0, 1, 2]
949+
@return pva_list List of list of derivatives at specified times.
950+
Inserts 'None' for unavailable or undesired fields
951+
The i-th element is the derivatives[i]-th derivative
952+
of position of size |times| x |derivatives|
953+
"""
954+
return JointStatesFromTraj(robot, traj, (time,), derivatives)[0]
955+
956+
957+
def BodyPointsStatesFromJointStates(bodypoints,
958+
jointstates,
959+
derivatives=[0, 1, 2]):
960+
"""
961+
Computes the derivatives body points given jointstates.
962+
Currently only supports derivatives up to 2.
963+
@param bodypoints List of bodypoints where each bodypoint
964+
is a list comprising of:
965+
(1) the OpenRAVE link the bodypoint is on
966+
(2) position of the body point in the link frame
967+
@param jointstates List of list of joint derivatives.
968+
Unavailable fields are input as 'None'
969+
@param derivatives list of desired derivatives defaults to [0, 1, 2]
970+
@return bodypoint_list List of list of derivatives at specified times.
971+
Inserts 'None' for unavailable or undesired fields
972+
The i-th element is the derivatives[i]-th derivative
973+
of position of size |times| x |derivatives|
974+
"""
975+
976+
# Convert derivatives to numpy array
977+
derivatives = numpy.array(derivatives)
978+
maxd = max(derivatives)
979+
numd = len(derivatives)
980+
981+
if any(derivatives > 2):
982+
raise ValueError("Can only support derivatives up to 2.")
983+
984+
# Assume everything belongs to the same robot and env
985+
robot = bodypoints[0][0].manipulator.GetRobot()
986+
env = robot.GetEnv()
987+
988+
bpstate_list = []
989+
990+
with env:
991+
with robot:
992+
for js in jointstates:
993+
# Make all unavailable and undesired derivatives None
994+
q, qd, qdd = [js[x] if x < len(js) and x <= maxd
995+
else None for x in range(3)]
996+
if q is not None:
997+
robot.SetDOFValues(q)
998+
else:
999+
bpstate_list.append([[[None] * numd] * len(bodypoints)])
1000+
continue
1001+
for bp in bodypoints:
1002+
bp_state = [None] * numd
1003+
link, local_pos = bp
1004+
link_index = link.GetIndex()
1005+
link_transform = link.GetTransform()
1006+
world_pos = (numpy.dot(link_transform[0:3, 0:3],
1007+
local_pos) +
1008+
link_transform[0:3, 3])
1009+
bp_state[0] = world_pos
1010+
if qd is not None:
1011+
Jpos = robot.CalculateJacobian(link_index, world_pos)
1012+
Jang = robot.CalculateAngularVelocityJacobian(
1013+
link_index)
1014+
vpos = numpy.dot(Jpos, qd)
1015+
vang = numpy.dot(Jang, qd)
1016+
bp_state[1] = numpy.hstack((vpos, vang))
1017+
else:
1018+
continue
1019+
if qdd is not None:
1020+
Hpos = robot.ComputeHessianTranslation(
1021+
link_index, world_pos)
1022+
Hang = robot.ComputeHessianAxisAngle(link_index)
1023+
apos = (numpy.dot(Jpos, qdd) +
1024+
numpy.dot(qd, numpy.dot(Hpos, qd)))
1025+
aang = (numpy.dot(Jang, qdd) +
1026+
numpy.dot(qd, numpy.dot(Hang, qd)))
1027+
bp_state[2] = numpy.hstack((apos, aang))
1028+
bpstate_list.append(bp_state)
1029+
return bpstate_list
1030+
1031+
1032+
def BodyPointsStatesFromJointState(bodypoints, jointstate,
1033+
derivatives=[0, 1, 2]):
1034+
"""
1035+
Computes the pos, vel, acc of body points given the
1036+
pos, vel, acc of jointstates
1037+
@param bodypoints List of bodypoints where each bodypoint
1038+
is a list comprising of:
1039+
(1) the OpenRAVE link the bodypoint is on
1040+
(2) position of the body point in the link frame
1041+
@param jointstate List of joint position,
1042+
velocity and acceleration.
1043+
Unavailable fields are input as 'None'
1044+
@param derivatives list of desired derivatives defaults to [0, 1, 2]
1045+
@return bodypoint_list List of list of derivatives at specified times.
1046+
Inserts 'None' for unavailable or undesired fields
1047+
The i-th element is the derivatives[i]-th derivative
1048+
of position of size |times| x |derivatives|
1049+
"""
1050+
return BodyPointsStatesFromJointStates(bodypoints, (jointstate,),
1051+
derivatives)[0]
1052+
1053+
1054+
def BodyPointsStatesFromTraj(bodypoints, traj, times, derivatives=[0, 1, 2]):
1055+
"""
1056+
Computes the pos, vel, acc of body points from a joint space trajectory
1057+
at specified times
1058+
@param bodypoints List of bodypoints where each bodypoint
1059+
is a list comprising of:
1060+
(1) the OpenRAVE link the bodypoint is on
1061+
(2) position of the body point in the link frame
1062+
@param traj An OpenRAVE trajectory
1063+
@param time List of times in seconds
1064+
@param derivatives list of desired derivatives defaults to [0, 1, 2]
1065+
@return bodypoint_list List of list of derivatives at specified times.
1066+
Inserts 'None' for unavailable or undesired fields
1067+
The i-th element is the derivatives[i]-th derivative
1068+
of position of size |times| x |derivatives|
1069+
"""
1070+
# Assume everything belongs to the same robot
1071+
robot = bodypoints[0][0].manipulator.GetRobot()
1072+
jointstates = JointStatesFromTraj(robot, traj, times,
1073+
range(max(derivatives)))
1074+
1075+
return BodyPointsStatesFromJointStates(bodypoints, jointstates,
1076+
derivatives)
1077+
1078+
1079+
def BodyPointsStateFromTraj(bodypoints, traj, time, derivatives=[0, 1, 2]):
1080+
"""
1081+
Computes the pos, vel, acc of body points from a joint space trajectory
1082+
at a specified time
1083+
@param bodypoints List of bodypoints where each bodypoint
1084+
is a list comprising of:
1085+
(1) the OpenRAVE link the bodypoint is on
1086+
(2) position of the body point in the link frame
1087+
@param traj An OpenRAVE trajectory
1088+
@param derivatives list of desired derivatives defaults to [0, 1, 2]
1089+
@return bodypoint_list List of list of derivatives at specified times.
1090+
Inserts 'None' for unavailable or undesired fields
1091+
The i-th element is the derivatives[i]-th derivative
1092+
of position of size |times| x |derivatives|
1093+
"""
1094+
return BodyPointsStatesFromTraj(bodypoints, traj, (time,), derivatives)[0]

0 commit comments

Comments
 (0)