WUT Velma robot API
int_markers_jimp.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 
6 
7 import roslib; roslib.load_manifest('velma_common')
8 
9 import rospy
10 import math
11 
12 import xml.dom.minidom as minidom
13 
14 from std_msgs.msg import ColorRGBA
17 from visualization_msgs.msg import *
18 from geometry_msgs.msg import *
19 from tf.transformations import *
20 import tf_conversions.posemath as pm
21 import PyKDL
22 import actionlib
23 
24 from velma_common import VelmaInterface
25 from rcprg_ros_utils import exitError, marker_publisher
26 
28  class JointInfo:
29  def __init__(self, name, parent_link, orig, ax, limit_lo, limit_up, rot):
30  self.name = name
31  self.parent_link = parent_link
32  self.orig = orig
33  self.ax = ax
34  self.limit_lo = limit_lo
35  self.limit_up = limit_up
36  self.rot = rot
37 
38  def getMarkerSize(self, joint_name):
39  if joint_name in self.size_map:
40  return self.size_map[joint_name]
41  return self.default_size
42 
43  def __init__(self, velma_interface):
44  # Size of individual markers
45  self.size_map = {'torso_0_joint':1.0}
46  self.default_size = 0.2
47 
48  # Create Velma interface class
49  self.velma = velma_interface
50 
51  # Get joint infor from robot_description
52  robot_description = rospy.get_param("/robot_description")
53 
54  # Create marker publisher for joint limits
55  self.pub = marker_publisher.MarkerPublisher('/joints_vis')
56 
57  # Parse robot_description URDF
58  dom = minidom.parseString(robot_description)
59  robot = dom.getElementsByTagName("robot")
60  if len(robot) != 1:
61  print "robot_description does not contain 'robot' node"
62  exit(1)
63 
64  # Gather information about all joints
65  self.joints = []
66  for j in robot[0].childNodes:
67  if j.localName != "joint":
68  continue
69  name = j.getAttribute("name")
70  joint_type = j.getAttribute("type")
71  if joint_type == "fixed":
72  continue
73  origin = j.getElementsByTagName("origin")
74  if len(origin) != 1:
75  print "joint '" + name + "' does contain wrong number of 'origin' nodes: " + str(len(origin))
76  exit(1)
77  axis = j.getElementsByTagName("axis")
78  if len(axis) != 1:
79  print "joint '" + name + "' contain wrong number of 'axis' nodes: " + str(len(axis))
80  exit(1)
81  limit = j.getElementsByTagName("limit")
82  if len(limit) != 1:
83  print "joint '" + name + "' contain wrong number of 'limit' nodes: " + str(len(limit))
84  exit(1)
85  parent = j.getElementsByTagName("parent")
86  if len(parent) != 1:
87  print "joint '" + name + "' contain wrong number of 'parent' nodes: " + str(len(parent))
88  exit(1)
89 
90  xyz = origin[0].getAttribute("xyz")
91  rpy = origin[0].getAttribute("rpy")
92  xyz = xyz.split()
93  rpy = rpy.split()
94  orig = PyKDL.Frame(PyKDL.Rotation.RPY(float(rpy[0]), float(rpy[1]), float(rpy[2])), PyKDL.Vector(float(xyz[0]), float(xyz[1]), float(xyz[2])))
95 
96  axis_xyz = axis[0].getAttribute("xyz")
97  axis_xyz = axis_xyz.split()
98  ax = PyKDL.Vector(float(axis_xyz[0]), float(axis_xyz[1]), float(axis_xyz[2]))
99 
100  limit_lo = float(limit[0].getAttribute("lower"))
101  limit_up = float(limit[0].getAttribute("upper"))
102  print name + ": " + str(limit_lo) + " " + str(limit_up) + " axis: " + str(ax.x()) + " " + str(ax.y()) + " " + str(ax.z()) + " "
103 
104  parent_link = parent[0].getAttribute("link")
105 
106  axis_z = ax
107  if abs(axis_z.z()) > 0.7:
108  axis_x = PyKDL.Vector(1,0,0)
109  else:
110  axis_x = PyKDL.Vector(0,0,1)
111  axis_y = axis_z * axis_x
112  axis_x = axis_y * axis_z
113  axis_x.Normalize()
114  axis_y.Normalize()
115  axis_z.Normalize()
116  rot = PyKDL.Frame(PyKDL.Rotation(axis_z,axis_x,axis_y))
117 
118  self.joints.append( IntMarkersJimp.JointInfo(name, parent_link, orig, ax,
119  limit_lo, limit_up, rot) )
120 
121  # Create meshes for joint limits visualization
122  self.points_list = {}
123  for joint in self.joints:
124  scale = self.getMarkerSize(joint.name)*0.5
125  pl = []
126  rot = joint.rot
127  angle = joint.limit_lo
128  while angle < joint.limit_up-0.15:
129  angle_prev = angle
130  angle += 0.1
131  pl.append(PyKDL.Vector())
132  pl.append(rot*PyKDL.Vector(0, math.cos(angle_prev), math.sin(angle_prev))*scale)
133  pl.append(rot*PyKDL.Vector(0, math.cos(angle), math.sin(angle))*scale)
134  pl.append(PyKDL.Vector())
135  pl.append(rot*PyKDL.Vector(0, math.cos(angle), math.sin(angle))*scale)
136  pl.append(rot*PyKDL.Vector(0, math.cos(joint.limit_up), math.sin(joint.limit_up))*scale)
137  self.points_list[joint.name] = pl
138 
139  # Create an interactive marker server on the topic namespace int_markers_jimp
140  self.server = InteractiveMarkerServer('int_markers_jimp')
141  self.insertMarkers()
142  self.server.applyChanges();
143 
144  def insertMarkers(self):
145  imp_joints = self.velma.getJointGroup('impedance_joints')
146  head_joints = self.velma.getJointGroup('head')
147  js = self.velma.getLastJointState()[1]
148 
149  self.initial_q = {}
150  self.prev_q = {}
151  self.desired_q = {}
152  for joint in self.joints:
153  if (not joint.name in imp_joints) and (not joint.name in head_joints):
154  continue
155  self.initial_q[joint.name] = js[joint.name]
156  self.prev_q[joint.name] = js[joint.name]
157  self.desired_q[joint.name] = js[joint.name]
158 
159  int_position_marker = InteractiveMarker()
160  int_position_marker.header.frame_id = joint.parent_link
161  int_position_marker.name = joint.name
162  int_position_marker.scale = self.getMarkerSize(joint.name)
163  int_position_marker.pose = pm.toMsg(joint.orig)
164 
165  int_position_marker.controls.append(self.createInteractiveMarkerControl1DOF(joint.rot));
166 
167  box = self.createAxisMarkerControl(0.02, self.getMarkerSize(joint.name)*0.5, joint.rot,
168  js[joint.name] )
169  box.interaction_mode = InteractiveMarkerControl.BUTTON
170  box.name = 'button'
171  int_position_marker.controls.append( box )
172  self.server.insert(int_position_marker, self.processFeedback);
173 
174  self.server.applyChanges();
175 
176  def getImpCmd(self):
177  joint_names = self.velma.getJointGroup('impedance_joints')
178  pos_changed = False
179  result = {}
180  for joint_name in joint_names:
181  if abs(self.desired_q[joint_name] - self.prev_q[joint_name]) > 0.0001:
182  pos_changed = True
183  result[joint_name] = self.desired_q[joint_name]
184  if pos_changed:
185  return result
186  return None
187 
188  def getHeadCmd(self):
189  joint_names = self.velma.getJointGroup('head')
190  pos_changed = False
191  result = {}
192  for joint_name in joint_names:
193  if abs(self.desired_q[joint_name] - self.prev_q[joint_name]) > 0.0001:
194  pos_changed = True
195  result[joint_name] = self.desired_q[joint_name]
196  if pos_changed:
197  return result
198  return None
199 
200  def processFeedback(self, feedback):
201  joint_name = feedback.marker_name
202  #print "feedback", feedback.marker_name, feedback.control_name, feedback.event_type
203  T_B_Td = pm.fromMsg(feedback.pose)
204  rot_diff = PyKDL.diff(PyKDL.Frame(), T_B_Td).rot
205  axis = None
206  for joint in self.joints:
207  if joint_name == joint.name:
208  axis = joint.ax
209  break
210  diff_q = PyKDL.dot(axis, rot_diff)
211 
212  self.desired_q[joint.name] = self.initial_q[joint.name] + diff_q
213  if ( feedback.control_name == 'button' ) and\
214  ( feedback.event_type == InteractiveMarkerFeedback.BUTTON_CLICK ):
215  imp_cmd = self.getImpCmd()
216  head_cmd = self.getHeadCmd()
217  if not imp_cmd is None:
218  self.velma.moveJoint(imp_cmd, 3.0, start_time=0.5, position_tol=15.0/180.0*math.pi)
219  if not head_cmd is None:
220  head_dst_q = [head_cmd["head_pan_joint"], head_cmd["head_tilt_joint"]]
221  self.velma.moveHead(head_dst_q, 3.0, start_time=0.5, position_tol=15.0/180.0*math.pi)
222  for joint_name in self.desired_q:
223  self.prev_q[joint_name] = self.desired_q[joint_name]
224 
225  def createAxisMarkerControl(self, width, length, rot, init_q):
226  marker = Marker()
227  marker.type = Marker.ARROW
228  marker.scale = Point(width, width*2, width*2)
229  marker.color = ColorRGBA(0,1,0,1)
230  marker.points.append( Point(0,0,0) )
231  v = rot*PyKDL.Vector(0, math.cos(init_q), math.sin(init_q))*length
232  marker.points.append( Point(v.x(), v.y(), v.z()) )
233 
234  control = InteractiveMarkerControl()
235  control.always_visible = True;
236  control.markers.append( marker );
237 
238  return control
239 
241  pose = pm.toMsg(T)
242  control = InteractiveMarkerControl()
243  control.orientation_mode = InteractiveMarkerControl.FIXED
244  control.name = 'control'
245  control.orientation = pose.orientation
246  control.interaction_mode = InteractiveMarkerControl.ROTATE_AXIS
247  return control
248 
249  def spin(self):
250  # Visualize the current position and joint limits
251  imp_joints = self.velma.getJointGroup('impedance_joints')
252  head_joints = self.velma.getJointGroup('head')
253 
254  while not rospy.is_shutdown():
255  js = self.velma.getLastJointState()[1]
256  m_id = 0
257  for joint in self.joints:
258  if (not joint.name in imp_joints) and (not joint.name in head_joints):
259  continue
260 
261  m_id = self.pub.publishTriangleListMarker(self.points_list[joint.name], m_id,
262  r=0, g=1, b=0, a=0.5, namespace="limits",
263  frame_id=joint.parent_link, T=joint.orig)
264  if joint.name in js:
265  q = js[joint.name]
266  vec = joint.rot*PyKDL.Vector(0, math.cos(q), math.sin(q))
267  m_id = self.pub.publishVectorMarker(joint.orig*PyKDL.Vector(),
268  joint.orig*(vec*0.75*self.getMarkerSize(joint.name)), m_id,
269  1, 0, 0, a=1.0, namespace="limits", frame=joint.parent_link, scale=0.01)
270  try:
271  rospy.sleep(0.05)
272  except:
273  break
274 
275 if __name__ == "__main__":
276  rospy.init_node('int_markers_jimp', anonymous=False)
277 
278  rospy.sleep(0.5)
279 
280  velma = VelmaInterface()
281  print "waiting for init..."
282 
283  velma.waitForInit()
284  print "init ok"
285 
286  print "Switch to jnt_imp mode (no trajectory)..."
287  if not velma.moveJointImpToCurrentPos(start_time=0.2):
288  exitError(1)
289  if velma.waitForJoint() != 0:
290  exitError(2)
291 
292  print "Switched to jnt_imp mode."
293 
294  int_jnt = IntMarkersJimp(velma)
295 
296  int_jnt.spin()
def __init__(self, name, parent_link, orig, ax, limit_lo, limit_up, rot)
def createAxisMarkerControl(self, width, length, rot, init_q)
def __init__(self, velma_interface)