urdf.py
Go to the documentation of this file.
00001 # Based on the python URDF implementation by Antonio El Khoury
00002 # Available at https://github.com/laas/robot_model_py
00003 
00004 import string
00005 from naoqi_tools.gazeboUrdf import *
00006 from xml.dom.minidom import Document
00007 from xml.dom import minidom
00008 import sys
00009 from numpy import array,pi
00010 import re, copy
00011 
00012 HUBO_JOINT_SUFFIX_MASK=r'([HKASEWF][RPY12345])'
00013 
00014 class Collision(object):
00015     """Collision node stores collision geometry for a link."""
00016     def __init__(self, geometry=None, origin=None):
00017         self.geometry = geometry
00018         self.origin = origin
00019 
00020     @staticmethod
00021     def parse(node, verbose=True):
00022         c = Collision()
00023         for child in children(node):
00024             if child.localName == 'geometry':
00025                 c.geometry = Geometry.parse(child, verbose)
00026             elif child.localName == 'origin':
00027                 c.origin = Pose.parse(child)
00028             else:
00029                 print("Unknown collision element '%s'"%child.localName)
00030         return c
00031 
00032     def to_xml(self, doc):
00033         xml = doc.createElement("collision")
00034         add(doc, xml, self.geometry)
00035         add(doc, xml, self.origin)
00036         return xml
00037 
00038     def to_openrave_xml(self, doc):
00039 
00040         xml = self.geometry.to_openrave_xml(doc)
00041         add_openrave(doc,xml, self.origin)
00042         return xml
00043 
00044     def __str__(self):
00045         s =  "Origin:\n{0}\n".format(reindent(str(self.origin), 1))
00046         s += "Geometry:\n{0}\n".format(reindent(str(self.geometry), 1))
00047         return s
00048 
00049 class Color(object):
00050     """Color node stores color definition for a material or a visual."""
00051     def __init__(self, r=0.0, g=0.0, b=0.0, a=0.0):
00052         self.rgba=(r,g,b,a)
00053 
00054     @staticmethod
00055     def parse(node):
00056         rgba = node.getAttribute("rgba").split()
00057         (r,g,b,a) = [ float(x) for x in rgba ]
00058         return Color(r,g,b,a)
00059 
00060     def to_xml(self, doc):
00061         xml = doc.createElement("color")
00062         set_attribute(xml, "rgba", self.rgba)
00063         return xml
00064 
00065     def to_openrave_xml(self,doc):
00066         return None
00067 
00068     def __str__(self):
00069         return "r: {0}, g: {1}, b: {2}, a: {3},".format(
00070             self.rgba[0], self.rgba[1], self.rgba[2], self.rgba[3])
00071 
00072 class Dynamics(object):
00073     """Dynamics node stores coefficients that define the dynamics of a joint"""
00074     def __init__(self, damping=None, friction=None):
00075         self.damping = damping
00076         self.friction = friction
00077 
00078     @staticmethod
00079     def parse(node):
00080         d = Dynamics()
00081         if node.hasAttribute('damping'):
00082             d.damping = node.getAttribute('damping')
00083         if node.hasAttribute('friction'):
00084             d.friction = node.getAttribute('friction')
00085         return d
00086 
00087     def to_xml(self, doc):
00088         xml = doc.createElement('dynamics')
00089         set_attribute(xml, 'damping', self.damping)
00090         set_attribute(xml, 'friction', self.friction)
00091         return xml
00092 
00093     def to_openrave_xml(self,doc):
00094         return None
00095 
00096     def __str__(self):
00097         return "Damping: {0}\nFriction: {1}\n".format(self.damping,
00098                                                       self.friction)
00099 
00100 class Geometry(object):
00101     """Geometry abstract class define the type of geomerical shape for a visual or collision element"""
00102     def __init__(self):
00103         None
00104 
00105     @staticmethod
00106     def parse(node, verbose=True):
00107         shape = children(node)[0]
00108         if shape.localName=='box':
00109             return Box.parse(shape)
00110         elif shape.localName=='cylinder':
00111             return Cylinder.parse(shape)
00112         elif shape.localName=='sphere':
00113             return Sphere.parse(shape)
00114         elif shape.localName=='mesh':
00115             return Mesh.parse(shape)
00116         else:
00117             if verbose:
00118                 print("Unknown shape %s"%shape.localName)
00119 
00120     def __str__(self):
00121         return "Geometry abstract class"
00122 
00123 class Box(Geometry):
00124     """Box node stores the dimensions for a rectangular geometry element"""
00125     def __init__(self, dims=None):
00126         if dims is None:
00127             self.dims = None
00128         else:
00129             self.dims = (dims[0], dims[1], dims[2])
00130 
00131     @staticmethod
00132     def parse(node):
00133         dims = node.getAttribute('size').split()
00134         return Box([float(a) for a in dims])
00135 
00136     def to_xml(self, doc):
00137         xml = doc.createElement("box")
00138         set_attribute(xml, "size", self.dims)
00139         geom = doc.createElement('geometry')
00140         geom.appendChild(xml)
00141         return geom
00142 
00143     def to_openrave_xml(self, doc):
00144         xml = short(doc, "geometry","type","box")
00145         xml.appendChild(create_element(xml, "extents", self.dims))
00146         return xml
00147 
00148     def __str__(self):
00149         return "Dimension: {0}".format(self.dims)
00150 
00151 
00152 class Cylinder(Geometry):
00153     """Cylinder node stores the dimensions for a z-rotation invariant geometry element"""
00154     def __init__(self, radius=0.0, length=0.0):
00155         self.radius = radius
00156         self.length = length
00157 
00158     @staticmethod
00159     def parse(node):
00160         r = node.getAttribute('radius')
00161         l = node.getAttribute('length')
00162         return Cylinder(float(r), float(l))
00163 
00164     def to_xml(self, doc):
00165         xml = doc.createElement("cylinder")
00166         set_attribute(xml, "radius", self.radius)
00167         set_attribute(xml, "length", self.length)
00168         geom = doc.createElement('geometry')
00169         geom.appendChild(xml)
00170         return geom
00171 
00172     def to_openrave_xml(self, doc):
00173         xml = short(doc, "geometry","type","cylinder")
00174         xml.appendChild(create_element(doc, "height", self.length))
00175         xml.appendChild(create_element(doc, "radius", self.radius))
00176         return xml
00177 
00178     def __str__(self):
00179         return "Radius: {0}\nLength: {1}".format(self.radius,
00180                                                  self.length)
00181 
00182 class Sphere(Geometry):
00183     """Sphere node stores the dimensions for a rotation invariant geometry element"""
00184     def __init__(self, radius=0.0):
00185         self.radius = radius
00186 
00187     @staticmethod
00188     def parse(node):
00189         r = node.getAttribute('radius')
00190         return Sphere(float(r))
00191 
00192     def to_xml(self, doc):
00193         xml = doc.createElement("sphere")
00194         set_attribute(xml, "radius", self.radius)
00195         geom = doc.createElement('geometry')
00196         geom.appendChild(xml)
00197         return geom
00198 
00199     def to_openrave_xml(self, doc):
00200         xml = short(doc, "geometry","type","sphere")
00201         xml.create_child(xml, "radius", self.radius)
00202         return xml
00203 
00204     def __str__(self):
00205         return "Radius: {0}".format(self.radius)
00206 
00207 
00208 class Mesh(Geometry):
00209     """Mesh node stores the path of the mesh file to be displayed"""
00210     def __init__(self, filename=None, scale=1):
00211         self.filename = filename
00212         self.scale = scale
00213 
00214     @staticmethod
00215     def parse(node):
00216         fn = node.getAttribute('filename')
00217         s = node.getAttribute('scale')
00218         if s == "":
00219             s = 1
00220         else:
00221             xyz = node.getAttribute('scale').split()
00222             s = map(float, xyz)
00223         return Mesh(fn, s)
00224 
00225     def to_xml(self, doc):
00226         xml = doc.createElement("mesh")
00227         set_attribute(xml, "filename", self.filename)
00228         if self.scale != 1:
00229             set_attribute(xml, "scale", self.scale)
00230         geom = doc.createElement('geometry')
00231         geom.appendChild(xml)
00232         return geom
00233 
00234     def to_openrave_xml(self, doc):
00235         xml = short(doc, "geometry","type","trimesh")
00236         f='../meshes/'+self.filename.split('/')[-1]
00237         fhull=re.sub(r"Body","convhull",f)
00238         #xml.appendChild(create_element(doc, "render", [f, self.scale]))
00239         xml.appendChild(create_element(doc, "data", [fhull, self.scale]))
00240         #set_attribute(xml, "render","true")
00241         return xml
00242 
00243     def __str__(self):
00244         return "Filename: {0}\nScale: {1}".format(self.filename, self.scale)
00245 
00246 
00247 class Inertial(object):
00248     """Inertial node stores mecanical information of a Link : mass, inertia matrix and origin"""
00249     def __init__(self, ixx=0.0, ixy=0.0, ixz=0.0, iyy=0.0, iyz=0.0, izz=0.0,
00250                  mass=0.0, origin=None):
00251         self.matrix = {}
00252         self.matrix['ixx'] = ixx
00253         self.matrix['ixy'] = ixy
00254         self.matrix['ixz'] = ixz
00255         self.matrix['iyy'] = iyy
00256         self.matrix['iyz'] = iyz
00257         self.matrix['izz'] = izz
00258         self.mass = mass
00259         self.origin = origin
00260 
00261     @staticmethod
00262     def parse(node):
00263         inert = Inertial()
00264         for child in children(node):
00265             if child.localName=='inertia':
00266                 for v in ['ixx', 'ixy', 'ixz', 'iyy', 'iyz', 'izz']:
00267                     inert.matrix[v] = float(child.getAttribute(v))
00268             elif child.localName=='mass':
00269                 inert.mass = float(child.getAttribute('value'))
00270             elif child.localName == 'origin':
00271                 inert.origin = Pose.parse(child)
00272         return inert
00273 
00274 
00275     def to_xml(self, doc):
00276         xml = doc.createElement("inertial")
00277 
00278         xml.appendChild(short(doc, "mass", "value", self.mass))
00279 
00280         inertia = doc.createElement("inertia")
00281         for (n,v) in self.matrix.items():
00282             set_attribute(inertia, n, v)
00283         xml.appendChild(inertia)
00284 
00285         add(doc, xml, self.origin)
00286         return xml
00287 
00288     def to_openrave_xml(self, doc):
00289         xml = doc.createElement("mass")
00290         set_attribute(xml,"type","custom")
00291         xml.appendChild(create_element(doc, "total", self.mass))
00292         text='{ixx} {ixy} {ixz}\n{ixy} {iyy} {iyz}\n{ixz} {iyz} {izz}'.format(**self.matrix)
00293         xml.appendChild(create_element(doc,"inertia",text))
00294         add_openrave(doc, xml, self.origin)
00295         xml.getElementsByTagName('translation')[0].tagName="com"
00296         return xml
00297 
00298     def __str__(self):
00299         s =  "Origin:\n{0}\n".format(reindent(str(self.origin), 1))
00300         s += "Mass: {0}\n".format(self.mass)
00301         s += "ixx: {0}\n".format(self.matrix['ixx'])
00302         s += "ixy: {0}\n".format(self.matrix['ixy'])
00303         s += "ixz: {0}\n".format(self.matrix['ixz'])
00304         s += "iyy: {0}\n".format(self.matrix['iyy'])
00305         s += "iyz: {0}\n".format(self.matrix['iyz'])
00306         s += "izz: {0}\n".format(self.matrix['izz'])
00307         return s
00308 
00309 
00310 class Joint(object):
00311     """Joint node stores articulation information coupling two links"""
00312     UNKNOWN = 'unknown'
00313     REVOLUTE = 'revolute'
00314     CONTINUOUS = 'continuous'
00315     PRISMATIC = 'prismatic'
00316     FLOATING = 'floating'
00317     PLANAR = 'planar'
00318     FIXED = 'fixed'
00319 
00320 
00321     def __init__(self, name, parent, child, joint_type, axis=None, origin=None,
00322                  limits=None, dynamics=None, safety=None, calibration=None,
00323                  mimic=None):
00324         self.name = name
00325         self.parent = parent
00326         self.child = child
00327         self.joint_type = joint_type
00328         self.axis = axis
00329         self.origin = origin
00330         self.limits = limits
00331         self.dynamics = dynamics
00332         self.safety = safety
00333         self.calibration = calibration
00334         self.mimic = mimic
00335 
00336     @staticmethod
00337     def parse(node, verbose=True):
00338         joint = Joint(node.getAttribute('name'), None, None,
00339                       node.getAttribute('type'))
00340         for child in children(node):
00341             if child.localName == 'parent':
00342                 joint.parent = child.getAttribute('link')
00343             elif child.localName == 'child':
00344                 joint.child = child.getAttribute('link')
00345             elif child.localName == 'axis':
00346                 joint.axis = array([float(x) for x in child.getAttribute('xyz').split(' ')])
00347             elif child.localName == 'origin':
00348                 joint.origin = Pose.parse(child)
00349             elif child.localName == 'limit':
00350                 joint.limits = JointLimit.parse(child)
00351             elif child.localName == 'dynamics':
00352                 joint.dynamics = Dynamics.parse(child)
00353             elif child.localName == 'safety_controller':
00354                 joint.safety = SafetyController.parse(child)
00355             elif child.localName == 'calibration':
00356                 joint.calibration = JointCalibration.parse(child)
00357             elif child.localName == 'mimic':
00358                 joint.mimic = JointMimic.parse(child)
00359             else:
00360                 if verbose:
00361                    print("Unknown joint element '%s'"%child.localName)
00362         return joint
00363 
00364     def to_xml(self, doc):
00365         xml = doc.createElement("joint")
00366         set_attribute(xml, "name", self.name)
00367         set_attribute(xml, "type", self.joint_type)
00368         xml.appendChild( short(doc, "parent", "link", self.parent) )
00369         xml.appendChild( short(doc, "child" , "link", self.child ) )
00370         add(doc, xml, self.origin)
00371         if self.axis is not None:
00372             xml.appendChild( short(doc, "axis", "xyz", to_string(self.axis) ) )
00373         add(doc, xml, self.limits)
00374         add(doc, xml, self.dynamics)
00375         add(doc, xml, self.safety)
00376         add(doc, xml, self.calibration)
00377         add(doc, xml, self.mimic)
00378 
00379         return xml
00380 
00381     def to_openrave_xml(self, doc):
00382         xml = doc.createElement("joint")
00383         set_attribute(xml, "name", self.name)
00384         s=""
00385         if self.joint_type == Joint.UNKNOWN:
00386             s = "unknown"
00387         elif self.joint_type == Joint.REVOLUTE:
00388             s = "hinge"
00389         elif self.joint_type == Joint.CONTINUOUS:
00390             s = "hinge"
00391             set_attribute(xml, "circular", "true")
00392 
00393         elif self.joint_type == Joint.PRISMATIC:
00394             s = "slider"
00395         elif self.joint_type == Joint.FIXED:
00396             s = "hinge"
00397             set_attribute(xml, "enable", "false")
00398             xml.appendChild( create_element(doc, "limits", "0 0") )
00399 
00400         set_attribute(xml, "type", s)
00401         if self.mimic is not None:
00402             multiplier=self.mimic.multiplier if self.mimic.multiplier is not None else 1.0
00403             offset=self.mimic.offset if self.mimic.offset is not None else 0.0
00404             #1) Follow openrave mimic joint format, disable joint:
00405             set_attribute(xml,"enable","false")
00406             #2) Create the position equation
00407             set_attribute(xml,"mimic_pos","{0} * {1} + {2}".format(self.mimic.joint_name,multiplier,offset))
00408             set_attribute(xml,"mimic_vel","|{0} {1}".format(self.mimic.joint_name,multiplier))
00409 
00410         xml.appendChild( create_element(doc, "body", self.parent) )
00411         xml.appendChild( create_element(doc, "body" , self.child ) )
00412         xml.appendChild( create_element(doc, "offsetfrom" , self.parent) )
00413         add_openrave(doc, xml, self.origin)
00414         xml.getElementsByTagName('translation')[0].tagName="anchor"
00415         if self.axis is not None:
00416             xml.appendChild( create_element(doc, "axis", self.axis) )
00417         add_openrave(doc, xml, self.limits)
00418         return xml
00419 
00420 
00421     def __str__(self):
00422         s = "Name: {0}\n".format(self.name)
00423 
00424         s += "Child link name: {0}\n".format(self.child)
00425         s += "Parent link name: {0}\n".format(self.parent)
00426 
00427         if self.joint_type == Joint.UNKNOWN:
00428             s += "Type: unknown\n"
00429         elif self.joint_type == Joint.REVOLUTE:
00430             s += "Type: revolute\n"
00431         elif self.joint_type == Joint.CONTINUOUS:
00432             s += "Type: continuous\n"
00433         elif self.joint_type == Joint.PRISMATIC:
00434             s += "Type: prismatic\n"
00435         elif self.joint_type == Joint.FLOATING:
00436             s += "Type: floating\n"
00437         elif self.joint_type == Joint.PLANAR:
00438             s += "Type: planar\n"
00439         elif self.joint_type == Joint.FIXED:
00440             s += "Type: fixed\n"
00441         else:
00442             print("unknown joint type")
00443 
00444         s +=  "Axis: {0}\n".format(self.axis)
00445         s +=  "Origin:\n{0}\n".format(reindent(str(self.origin), 1))
00446         s += "Limits:\n"
00447         s += reindent(str(self.limits), 1) + "\n"
00448         s += "Dynamics:\n"
00449         s += reindent(str(self.dynamics), 1) + "\n"
00450         s += "Safety:\n"
00451         s += reindent(str(self.safety), 1) + "\n"
00452         s += "Calibration:\n"
00453         s += reindent(str(self.calibration), 1) + "\n"
00454         s += "Mimic:\n"
00455         s += reindent(str(self.mimic), 1) + "\n"
00456         return s
00457 
00458 
00459 #FIXME: we are missing the reference position here.
00460 class JointCalibration(object):
00461     def __init__(self, rising=None, falling=None):
00462         self.rising = rising
00463         self.falling = falling
00464 
00465     @staticmethod
00466     def parse(node):
00467         jc = JointCalibration()
00468         if node.hasAttribute('rising'):
00469             jc.rising = float( node.getAttribute('rising') )
00470         if node.hasAttribute('falling'):
00471             jc.falling = float( node.getAttribute('falling') )
00472         return jc
00473 
00474     def to_xml(self, doc):
00475         xml = doc.createElement('calibration')
00476         set_attribute(xml, 'rising', self.rising)
00477         set_attribute(xml, 'falling', self.falling)
00478         return xml
00479 
00480     def to_openrave_xml(self,doc):
00481         #No implementation
00482         return None
00483 
00484     def __str__(self):
00485         s = "Raising: {0}\n".format(self.rising)
00486         s += "Falling: {0}\n".format(self.falling)
00487         return s
00488 
00489 class JointLimit(object):
00490     """JointLimit node stores mechanical limits of a given joint"""
00491     def __init__(self, effort, velocity, lower=None, upper=None):
00492         self.effort = effort
00493         self.velocity = velocity
00494         self.lower = lower
00495         self.upper = upper
00496 
00497     @staticmethod
00498     def parse(node):
00499         jl = JointLimit( float( node.getAttribute('effort') ) ,
00500                          float( node.getAttribute('velocity')))
00501         if node.hasAttribute('lower'):
00502             jl.lower = float( node.getAttribute('lower') )
00503         if node.hasAttribute('upper'):
00504             jl.upper = float( node.getAttribute('upper') )
00505         return jl
00506 
00507     def get_from_table(self,node):
00508         jl = JointLimit( float( node.getAttribute('effort') ) ,
00509                          float( node.getAttribute('velocity')))
00510         if node.hasAttribute('lower'):
00511             jl.lower = float( node.getAttribute('lower') )
00512         if node.hasAttribute('upper'):
00513             jl.upper = float( node.getAttribute('upper') )
00514         return jl
00515 
00516     def to_xml(self, doc):
00517         xml = doc.createElement('limit')
00518         set_attribute(xml, 'effort', self.effort)
00519         set_attribute(xml, 'velocity', self.velocity)
00520         set_attribute(xml, 'lower', self.lower)
00521         set_attribute(xml, 'upper', self.upper)
00522         return xml
00523 
00524     def to_openrave_xml(self,doc):
00525         limit = create_element(doc,'limitsdeg',[round(self.lower*180/pi,1),round(self.upper*180/pi,1)])
00526         maxvel = create_element(doc,'maxvel',self.velocity)
00527         maxtrq = create_element(doc,'maxtorque',self.effort)
00528         return [limit,maxvel,maxtrq]
00529 
00530     def __str__(self):
00531         s = "Effort: {0}\n".format(self.effort)
00532         s += "Lower: {0}\n".format(self.lower)
00533         s += "Upper: {0}\n".format(self.upper)
00534         s += "Velocity: {0}\n".format(self.velocity)
00535         return s
00536 
00537 class JointMimic(object):
00538     """JointMimic node stores information coupling an actuated joint to a not controllable joint"""
00539     def __init__(self, joint_name, multiplier=None, offset=None):
00540         self.joint_name = joint_name
00541         self.multiplier = multiplier
00542         self.offset = offset
00543 
00544     @staticmethod
00545     def parse(node):
00546         mimic = JointMimic( node.getAttribute('joint') )
00547         if node.hasAttribute('multiplier'):
00548             mimic.multiplier = float( node.getAttribute('multiplier') )
00549         if node.hasAttribute('offset'):
00550             mimic.offset = float( node.getAttribute('offset') )
00551         return mimic
00552 
00553     def to_xml(self, doc):
00554         xml = doc.createElement('mimic')
00555         set_attribute(xml, 'joint', self.joint_name)
00556         set_attribute(xml, 'multiplier', self.multiplier)
00557         set_attribute(xml, 'offset', self.offset)
00558         return xml
00559 
00560     def __str__(self):
00561         s = "Joint: {0}\n".format(self.joint_name)
00562         s += "Multiplier: {0}\n".format(self.multiplier)
00563         s += "Offset: {0}\n".format(self.offset)
00564         return s
00565 
00566 
00567 class Link(object):
00568     """Link node stores information defining the mechanics and the visualization of a link"""
00569     def __init__(self, name, visual=None, inertial=None, collision=None, xacro=None):
00570         self.name = name
00571         self.visual = visual
00572         self.inertial = inertial
00573         self.collision = collision
00574         self.xacro = xacro
00575 
00576     @staticmethod
00577     def parse(node, verbose=True):
00578         link = Link(node.getAttribute('name'))
00579         for child in children(node):
00580             if child.localName == 'visual':
00581                 link.visual = Visual.parse(child, verbose)
00582             elif child.localName == 'collision':
00583                 link.collision = Collision.parse(child, verbose)
00584             elif child.localName == 'inertial':
00585                 link.inertial = Inertial.parse(child)
00586             elif child.localName.startswith('xacro'):
00587                 link.xacro = xacro
00588             else:
00589                 if verbose:
00590                     print("Unknown link element '%s'"%child.localName)
00591         return link
00592 
00593     def to_xml(self, doc):
00594         xml = doc.createElement("link")
00595         xml.setAttribute("name", self.name)
00596         add( doc, xml, self.visual)
00597         add( doc, xml, self.collision)
00598         add( doc, xml, self.inertial)
00599         if self.xacro is not None:
00600             text = doc.createElement(self.xacro)
00601             xml.appendChild(text)
00602         return xml
00603 
00604     def to_openrave_xml(self, doc):
00605         xml = doc.createElement("body")
00606         xml.setAttribute("name", self.name)
00607         add_openrave( doc, xml, self.collision)
00608         add_openrave( doc, xml, self.inertial)
00609         return xml
00610 
00611     def __str__(self):
00612         s = "Name: {0}\n".format(self.name)
00613         s += "Inertial:\n"
00614         s += reindent(str(self.inertial), 1) + "\n"
00615         s += "Visual:\n"
00616         s += reindent(str(self.visual), 1) + "\n"
00617         s += "Collision:\n"
00618         s += reindent(str(self.collision), 1) + "\n"
00619         s += "Xacro:\n"
00620         s += reindent(str(self.xacro),1) + "\n"
00621         return s
00622 
00623 class Material(object):
00624     """Material node stores visual information of a mechanical material : color, texture"""
00625     def __init__(self, name=None, color=None, texture=None):
00626         self.name = name
00627         self.color = color
00628         self.texture = texture
00629 
00630     @staticmethod
00631     def parse(node, verbose=True):
00632         material = Material()
00633         if node.hasAttribute('name'):
00634             material.name = node.getAttribute('name')
00635         for child in children(node):
00636             if child.localName == 'color':
00637                 material.color = Color.parse(child)
00638             elif child.localName == 'texture':
00639                 material.texture = child.getAttribute('filename')
00640             else:
00641                 if verbose:
00642                     print("Unknown material element '%s'"%child.localName)
00643 
00644         return material
00645 
00646     def to_xml(self, doc):
00647         xml = doc.createElement("material")
00648         set_attribute(xml, "name", self.name)
00649         add( doc, xml, self.color )
00650 
00651         if self.texture is not None:
00652             text = doc.createElement("texture")
00653             text.setAttribute('filename', self.texture)
00654             xml.appendChild(text)
00655         return xml
00656 
00657     def __str__(self):
00658         s = "Name: {0}\n".format(self.name)
00659         s += "Color: {0}\n".format(self.color)
00660         s += "Texture:\n"
00661         s += reindent(str(self.texture), 1)
00662         return s
00663 
00664 
00665 class Pose(object):
00666     """Pose node stores a cartesian 6-D pose :
00667     xyz : array
00668     rpy : array
00669     """
00670     def __init__(self, position=None, rotation=None):
00671         self.position = array(position)
00672         self.rotation = array(rotation)
00673 
00674     @staticmethod
00675     def parse(node):
00676         pose = Pose()
00677         if node.hasAttribute("xyz"):
00678             xyz = node.getAttribute('xyz').split()
00679             pose.position = array(map(float, xyz))
00680         if node.hasAttribute("rpy"):
00681             rpy = node.getAttribute('rpy').split()
00682             pose.rotation = array(map(float, rpy))
00683         return pose
00684 
00685     def to_xml(self, doc):
00686         xml = doc.createElement("origin")
00687         set_attribute(xml, 'xyz', self.position)
00688         set_attribute(xml, 'rpy', self.rotation)
00689         return xml
00690 
00691     def to_openrave_xml(self, doc):
00692         xml = doc.createElement("translation")
00693         set_content(doc,xml,self.position)
00694         elements=[xml]
00695         if not self.rotation[0] == 0:
00696             rotr = doc.createElement("rotationaxis")
00697             set_content(doc,rotr,[1,0,0,self.rotation[0]*180.0/pi])
00698             elements.append(rotr)
00699         if not self.rotation[1] == 0:
00700             rotp = doc.createElement("rotationaxis")
00701             set_content(doc,rotp,[0,1,0,self.rotation[1]*180.0/pi])
00702             elements.append(rotp)
00703         if not self.rotation[2] == 0:
00704             roty = doc.createElement("rotationaxis")
00705             set_content(doc,roty,[0,0,1,self.rotation[2]*180.0/pi])
00706             elements.append(roty)
00707 
00708         return elements
00709 
00710     def __str__(self):
00711         return "Position: {0}\nRotation: {1}".format(self.position,
00712                                                      self.rotation)
00713 
00714 
00715 class SafetyController(object):
00716     def __init__(self, velocity, position=None, lower=None, upper=None):
00717         self.velocity = velocity
00718         self.position = position
00719         self.lower = lower
00720         self.upper = upper
00721 
00722     @staticmethod
00723     def parse(node):
00724         sc = SafetyController( float(node.getAttribute('k_velocity')) )
00725         if node.hasAttribute('soft_lower_limit'):
00726             sc.lower = float( node.getAttribute('soft_lower_limit') )
00727         if node.hasAttribute('soft_upper_limit'):
00728             sc.upper = float( node.getAttribute('soft_upper_limit') )
00729         if node.hasAttribute('k_position'):
00730             sc.position = float( node.getAttribute('k_position') )
00731         return sc
00732 
00733     def to_xml(self, doc):
00734         xml = doc.createElement('safety_controller')
00735         set_attribute(xml, 'k_velocity', self.velocity)
00736         set_attribute(xml, 'k_position', self.position)
00737         set_attribute(xml, 'soft_upper_limit', self.upper)
00738         set_attribute(xml, 'soft_lower_limit', self.lower)
00739         return xml
00740 
00741     def __str__(self):
00742         s = "Safe lower limit: {0}\n".format(self.lower)
00743         s += "Safe upper limit: {0}\n".format(self.upper)
00744         s += "K position: {0}\n".format(self.position)
00745         s += "K velocity: {0}\n".format(self.velocity)
00746         return s
00747 
00748 
00749 class Visual(object):
00750     """Visual node stores information defining shape and material of the link to be displayed"""
00751     def __init__(self, geometry=None, material=None, origin=None):
00752         self.geometry = geometry
00753         self.material = material
00754         self.origin = origin
00755 
00756     @staticmethod
00757     def parse(node, verbose=True):
00758         v = Visual()
00759         for child in children(node):
00760             if child.localName == 'geometry':
00761                 v.geometry = Geometry.parse(child, verbose)
00762             elif child.localName == 'origin':
00763                 v.origin = Pose.parse(child)
00764             elif child.localName == 'material':
00765                 v.material = Material.parse(child, verbose)
00766             else:
00767                 if verbose:
00768                     print("Unknown visual element '%s'"%child.localName)
00769         return v
00770 
00771     def to_xml(self, doc):
00772         xml = doc.createElement("visual")
00773         add( doc, xml, self.geometry )
00774         add( doc, xml, self.origin )
00775         add( doc, xml, self.material )
00776         return xml
00777 
00778     def __str__(self):
00779         s =  "Origin:\n{0}\n".format(reindent(str(self.origin), 1))
00780         s += "Geometry:\n"
00781         s += reindent(str(self.geometry), 1) + "\n"
00782         s += "Material:\n"
00783         s += reindent(str(self.material), 1) + "\n"
00784         return s
00785 
00786 
00787 class Actuator(object):
00788     """Actuator node stores information about how a motor controls a joint : used in transmission tags"""
00789     def __init__(self,name=None,hardwareInterface=None,mechanicalReduction=1):
00790         self.name = name
00791         self.hardwareInterface = hardwareInterface
00792         self.mechanicalReduction = mechanicalReduction
00793 
00794     @staticmethod
00795     def parse(node, verbose=True):
00796         actuator = Actuator()
00797         if node.hasAttribute('name'):
00798             actuator.name = node.getAttribute('name')
00799         for child in children(node):
00800             if child.localName == 'hardwareInterface':
00801                 actuator.hardwareInterface = str(child.childNodes[0].nodeValue)
00802             if child.localName == 'mechanicalReduction':
00803                 actuator.mechanicalReduction = str(child.childNodes[0].nodeValue)
00804             else:
00805                 print'Unknown actuator element ' + str(child.localName)
00806         return actuator
00807 
00808     def to_xml(self, doc):
00809         xml = doc.createElement('actuator')
00810         set_attribute(xml, 'name', self.name)
00811         xml.appendChild(create_element(doc, 'hardwareInterface', self.hardwareInterface))
00812         xml.appendChild(create_element(doc,"mechanicalReduction",str(self.mechanicalReduction)))
00813         return xml
00814 
00815     def __str__(self):
00816         s = "Name: {0}\n".format(self.name)
00817         s += "HardwareInterface : {0}\n".format(self.hardwareInterface)
00818         s += "Mechanical Reduction: {0}\n".format(self.mechanicalReduction)
00819         return s
00820 
00821 
00822 class Transmission(object):
00823     """Transmission node stores information linking a joint to an actuator"""
00824     def __init__(self,name=None,type=None,joint=None,actuator=None):
00825         self.name = name
00826         self.joint = joint
00827         self.actuator = actuator
00828         self.type = type
00829     @staticmethod
00830     def parse(node, verbose=True):
00831         trans = Transmission()
00832         if node.hasAttribute('name'):
00833             trans.name = node.getAttribute('name')
00834         for child in children(node):
00835             if child.localName == 'joint':
00836                 trans.joint = child.getAttribute('name')
00837             if child.localName == 'actuator':
00838                 trans.actuator = Actuator.parse(child,verbose)
00839             if child.localName == 'type':
00840                 trans.type = str(child.childNodes[0].nodeValue)#str(child.getAttribute('type'))
00841         return trans
00842 
00843     def to_xml(self, doc):
00844         xml = doc.createElement('transmission')
00845         set_attribute(xml, 'name', self.name)
00846         xml.appendChild( short(doc, "joint", "name", self.joint) )
00847         xml.appendChild(create_element(doc, 'type', self.type))
00848         add(doc, xml, self.actuator)
00849 
00850         return xml
00851 
00852     def __str__(self):
00853         s = "Name: {0}\n".format(self.name)
00854         s += "Type: {0}\n".format(self.type)
00855         s += "Joint: {0}\n".format(self.joint)
00856         s += "Actuator:\n"
00857         s += reindent(str(self.actuator), 1) + "\n"
00858 
00859         return s
00860 
00861 ########################################
00862 ######### URDF Global Class ############
00863 ########################################
00864 class URDF(object):
00865     """URDF node stores every information about a robot's model"""
00866     ZERO_THRESHOLD=0.000000001
00867     def __init__(self, name=""):
00868         self.name = name
00869         self.elements = []
00870         self.gazebos = {}
00871         self.links = {}
00872         self.joints = {}
00873         self.materials = {}
00874         self.parent_map = {}
00875         self.child_map = {}
00876 
00877     @staticmethod
00878     def parse_xml_string(xml_string, verbose=True):
00879         """Parse a string to create a URDF robot structure."""
00880         urdf = URDF()
00881         base = minidom.parseString(xml_string)
00882         robot = children(base)[0]
00883         urdf.name = robot.getAttribute('name')
00884 
00885         for node in children(robot):
00886             if node.nodeType is node.TEXT_NODE:
00887                 continue
00888             if node.localName == 'joint':
00889                 urdf.add_joint( Joint.parse(node, verbose) )
00890             elif node.localName == 'link':
00891                 urdf.add_link( Link.parse(node, verbose) )
00892             elif node.localName == 'material':
00893                 urdf.add_material(Material.parse(node,verbose))
00894             elif node.localName == 'gazebo':
00895                 urdf.add_gazebo(Gazebo.parse(node,verbose))
00896             elif node.localName == 'transmission':
00897                 urdf.elements.append( Transmission.parse(node,verbose) )
00898             else:
00899                 if verbose:
00900                     print("Unknown robot element '%s'"%node.localName)
00901         return urdf
00902 
00903     @staticmethod
00904     def load_xml_file(filename, verbose=True):
00905         """Parse a file to create a URDF robot structure."""
00906         f = open(filename, 'r')
00907         return URDF.parse_xml_string(f.read(), verbose)
00908 
00909     @staticmethod
00910     def load_from_parameter_server(key = 'robot_description', verbose=True):
00911         """
00912         Retrieve the robot model on the parameter server
00913         and parse it to create a URDF robot structure.
00914 
00915         Warning: this requires roscore to be running.
00916         """
00917         import rospy
00918         return URDF.parse_xml_string(rospy.get_param(key), verbose)
00919 
00920     def add_link(self, link):
00921         self.elements.append(link)
00922         self.links[link.name] = link
00923 
00924     def add_joint(self, joint):
00925         self.elements.append(joint)
00926         self.joints[joint.name] = joint
00927 
00928         self.parent_map[ joint.child ] = (joint.name, joint.parent)
00929         if joint.parent in self.child_map:
00930             self.child_map[joint.parent].append( (joint.name, joint.child) )
00931         else:
00932             self.child_map[joint.parent] = [ (joint.name, joint.child) ]
00933 
00934     def add_material(self, material):
00935         """
00936         Add a material to the URDF.elements list
00937         """
00938         self.elements.append(material)
00939         self.materials[material.name] = material
00940 
00941     def add_gazebo(self, gazebo):
00942         """
00943         Add gazebo data to the URDF.elements list
00944         """
00945 
00946         self.elements.append(gazebo)
00947         self.gazebos[gazebo.reference] = gazebo
00948 
00949     def get_chain(self, root, tip, joints=True, links=True, fixed=True):
00950         """Based on given link names root and tip, return either a joint or link chain as a list of names."""
00951         chain = []
00952         if links:
00953             chain.append(tip)
00954         link = tip
00955         while link != root:
00956             (joint, parent) = self.parent_map[link]
00957             if joints:
00958                 if fixed or self.joints[joint].joint_type != 'fixed':
00959                     chain.append(joint)
00960             if links:
00961                 chain.append(parent)
00962             link = parent
00963         chain.reverse()
00964         return chain
00965 
00966     def get_root(self):
00967         root = None
00968         for link in self.links:
00969             if link not in self.parent_map:
00970                 assert root is None, "Multiple roots detected, invalid URDF."
00971                 root = link
00972         assert root is not None, "No roots detected, invalid URDF."
00973         return root
00974 
00975     def to_xml(self,orderbytree=False,orderbytype=False):
00976         doc = Document()
00977         root = doc.createElement("robot")
00978         doc.appendChild(root)
00979         root.setAttribute("name", self.name)
00980 
00981         baselink=self.parent_map
00982         if orderbytree:
00983             #Walk child map sequentially and export
00984             pass
00985         if orderbytype:
00986             pass
00987 
00988         for element in self.elements:
00989             root.appendChild(element.to_xml(doc))
00990 
00991         return doc.toprettyxml()
00992 
00993     def write_xml(self,outfile=None):
00994         if outfile is None:
00995             outfile=self.name+'.urdf'
00996 
00997         self.write_reformatted(self.to_xml(),outfile)
00998 
00999     def make_openrave_kinbody(self,doc):
01000         kinbody = doc.createElement("kinbody")
01001         doc.appendChild(kinbody)
01002         kinbody.setAttribute("name", self.name)
01003 
01004         for element in self.elements:
01005             kinbody.appendChild(element.to_openrave_xml(doc))
01006 
01007         #Post-processing to add offsetfrom statements
01008 
01009         for j in self.joints.keys():
01010             for l in kinbody.getElementsByTagName('body'):
01011                 if l.getAttribute('name')== self.joints[j].child:
01012                     #Add offsetfrom declarration and joint anchor as transform
01013                     l.appendChild( create_element(doc, "offsetfrom" , self.joints[j].parent) )
01014                     add_openrave(doc,l,self.joints[j].origin)
01015                     break
01016 
01017         #Add adjacencies
01018         for j in self.joints.values():
01019             kinbody.appendChild(create_element(doc,"adjacent",[j.parent, j.child]))
01020 
01021         #Add known extra adjacencies
01022         badjoints={'LAR':'LKP','LWR':'LWY','LSY':'LSP','LHY':'LHP',
01023                    'RAR':'RKP','RWR':'RWY','RSY':'RSP','RHY':'RHP',
01024                    'NK1':'Torso'}
01025         for k,v in badjoints.items():
01026             #TODO: search all bodies for above pairs and add extra adjacency tags
01027             b1=None
01028             b2=None
01029             for b in kinbody.getElementsByTagName('body'):
01030                 if re.search(k,b.getAttribute('name')):
01031                     b1=b.getAttribute('name')
01032                 if re.search(v,b.getAttribute('name')):
01033                     b2=b.getAttribute('name')
01034             if b1 and b2:
01035                 kinbody.appendChild(create_element(doc,"adjacent",[b1, b2]))
01036 
01037         return kinbody
01038 
01039     def to_openrave_xml(self):
01040         doc = Document()
01041         root = doc.createElement("robot")
01042         doc.appendChild(root)
01043         root.setAttribute("name", self.name)
01044         root.appendChild(self.make_openrave_kinbody(doc))
01045 
01046         return doc.toprettyxml()
01047 
01048     def write_reformatted(self,data,name):
01049         if name is None:
01050             name=self.name
01051         outdata=re.sub(r'\t','    ',data)
01052         with open(name,'w+') as f:
01053             f.write(outdata)
01054 
01055     def write_openrave_files(self,outname=None,writerobot=False):
01056         if outname is None:
01057             outname=self.name
01058 
01059         kinfile=outname+'.kinbody.xml'
01060 
01061         if writerobot:
01062             robotfile=outname+'.robot.xml'
01063             doc = Document()
01064             root = doc.createElement("robot")
01065             doc.appendChild(root)
01066             root.setAttribute("name", outname)
01067             kinbody = doc.createElement("kinbody")
01068             root.appendChild(kinbody)
01069             kinbody.setAttribute("name", outname)
01070             kinbody.setAttribute("file", kinfile)
01071             self.write_reformatted(doc.toprettyxml(),robotfile)
01072 
01073         doc2 = Document()
01074         doc2.appendChild(self.make_openrave_kinbody(doc2))
01075 
01076         self.write_reformatted(doc2.toprettyxml(),kinfile)
01077 
01078 
01079     def __str__(self):
01080         s = "Name: {0}\n".format(self.name)
01081         s += "\n"
01082         s += "Links:\n"
01083         if len(self.links) == 0:
01084             s += "None\n"
01085         else:
01086             for k, v in self.links.iteritems():
01087                 s += "- Link '{0}':\n{1}\n".format(k, reindent(str(v), 1))
01088         s += "\n"
01089         s += "Joints:\n"
01090         if len(self.joints) == 0:
01091             s += "None\n"
01092         else:
01093             for k, v in self.joints.iteritems():
01094                 s += "- Joint '{0}':\n{1}\n".format(k, reindent(str(v), 1))
01095         s += "\n"
01096         s += "Materials:\n"
01097         if len(self.materials) == 0:
01098             s += "None\n"
01099         else:
01100             for k, v in self.materials.iteritems():
01101                 s += "- Material '{0}':\n{1}\n".format(k, reindent(str(v), 1))
01102 
01103         return s
01104 
01105     def walk_chain(self,link,branchorder=None):
01106         """Walk along the first branch of urdf tree to find last link. Optionally specify which fork to take globally)."""
01107         child=link
01108         if branchorder is None:
01109             branchorder=0
01110 
01111         while self.child_map.has_key(child):
01112             children=self.child_map[link]
01113             l=len(children)
01114             child=children[min(branchorder,l-1)][1]
01115 
01116         return child
01117 
01118     def rename_link(self,link,newlink):
01119         """Rename a link, updating all internal references to the name, and
01120         removing the old name from the links dict."""
01121         self.links[link].name=newlink
01122         self.links[newlink]=self.links[link]
01123         self.links.pop(link)
01124         for k,v in self.parent_map.items():
01125             if k==link:
01126                 self.parent_map[newlink]=v
01127                 self.parent_map.pop(k)
01128                 k=newlink
01129             if v[0]==link:
01130                 new0=newlink
01131                 v=(new0,v[1])
01132             if v[1]==link:
01133                 new1=newlink
01134                 v=(v[0],new1)
01135             self.parent_map[k]=v
01136         for k,v in self.child_map.items():
01137             if k==link:
01138                 self.child_map[newlink]=v
01139                 self.child_map.pop(k)
01140                 k=newlink
01141             vnew=[]
01142             for el in v:
01143                 if el[1]==link:
01144                     el=(el[0],newlink)
01145                 vnew.append(el)
01146           #  print vnew
01147             self.child_map[k]=vnew
01148         for n,j in self.joints.items():
01149             if j.parent==link:
01150                 j.parent=newlink
01151             if j.child==link:
01152                 j.child=newlink
01153         #print self.child_map
01154 
01155     def rename_joint(self,joint,newjoint):
01156         """Find a joint and rename it to newjoint, updating all internal
01157         structures and mimic joints with the new name. Removes the old joint
01158         reference from the joints list."""
01159         self.joints[joint].name=newjoint
01160         self.joints[newjoint]=self.joints[joint]
01161         self.joints.pop(joint)
01162         for k,v in self.child_map.items():
01163             vnew=[]
01164             for el in v:
01165                 if el[0]==joint:
01166                     el=(newjoint,el[1])
01167                 print el
01168                 vnew.append(el)
01169             self.child_map[k]=vnew
01170         for k,v in self.parent_map.items():
01171             if v[0]==joint:
01172                 v=(newjoint,v[1])
01173             print el
01174             self.parent_map[k]=v
01175         for n,j in self.joints.items():
01176             if j.mimic is not None:
01177                 j.mimic.joint_name=newjoint if j.mimic.joint_name==joint else j.mimic.joint_name
01178 
01179     def copy_joint(self,joint,f,r):
01180         """Copy and rename a joint and it's parent/child by the f / r strings. Assumes links exist.
01181         Note that it renames the parent and child, so use this with copy_link"""
01182         newjoint=copy.deepcopy(self.joints[joint])
01183         newjoint.name=re.sub(f,r,newjoint.name)
01184         newjoint.parent=re.sub(f,r,newjoint.parent)
01185         newjoint.child=re.sub(f,r,newjoint.child)
01186 
01187         self.add_joint(newjoint)
01188         return newjoint
01189 
01190     def move_chain_with_rottrans(self,root,tip,rpy,xyz,f,r):
01191         """Find and rename a kinematic chain based on the given root and top
01192         names. Renames all links and joints according to find and replace
01193         terms.
01194         """
01195         linkchain=self.get_chain(root,tip,links=True,joints=False)
01196         jointchain=self.get_chain(root,tip,joints=True,links=False)
01197         print linkchain
01198         print jointchain
01199 
01200         for l in linkchain[1:]:
01201             newlink=re.sub(f,r,l)
01202             self.rename_link(l,newlink)
01203         for j in jointchain:
01204             newname=re.sub(f,r,j)
01205             self.rename_joint(j,newname)
01206             self.joints[newname].origin.position+=array(xyz)
01207             self.joints[newname].origin.rotation+=array(rpy)
01208             if self.joints[newname].mimic is not None:
01209                 self.joints[newname].mimic.joint_name=re.sub(f,r,self.joints[newname].mimic.joint_name)
01210 
01211     def copy_chain_with_rottrans(self,root,tip,rpy,xyz,f,r,mir_ax=None):
01212         """Copy a kinematic chain, renaming joints and links according to a regular expression.
01213 
01214         Note that this is designed to work with the Hubo joint / body
01215         convention, which has an easy pattern for joint and body names. If your
01216         model has joints and links that are not systematically named, this
01217         function won't be much use.
01218         """
01219 
01220         linkchain=self.get_chain(root,tip,links=True,joints=False)
01221         jointchain=self.get_chain(root,tip,joints=True,links=False)
01222         print linkchain
01223         print jointchain
01224         newjoints=[]
01225         newlinks=[]
01226         for l in linkchain[1:]:
01227             newlink=copy.deepcopy(self.links[l])
01228             newlink.name=re.sub(f,r,newlink.name)
01229             if newlink.collision is not None:
01230                 newlink.collision.geometry.filename=re.sub(f,r,newlink.collision.geometry.filename)
01231                 newlink.visual.geometry.filename=re.sub(f,r,newlink.visual.geometry.filename)
01232             self.add_link(newlink)
01233             newlinks.append(newlink)
01234             if mir_ax == 'x':
01235                 newlink.inertial.matrix['ixy']*=-1.
01236                 newlink.inertial.matrix['ixz']*=-1.
01237                 newlink.inertial.origin.position[0]*=-1.
01238             if mir_ax == 'y':
01239                 newlink.inertial.matrix['ixy']*=-1.
01240                 newlink.inertial.matrix['iyz']*=-1.
01241                 newlink.inertial.origin.position[1]*=-1.
01242             if mir_ax == 'z':
01243                 newlink.inertial.matrix['ixz']*=-1.
01244                 newlink.inertial.matrix['iyz']*=-1.
01245                 newlink.inertial.origin.position[2]*=-1.
01246         #Hack to rotate just first joint
01247         for j in jointchain:
01248             newjoints.append(self.copy_joint(j,f,r))
01249             if mir_ax == 'x':
01250                 newjoints[-1].origin.position[0]*=-1.0
01251                 newjoints[-1].origin.rotation[1]*=-1.0
01252                 newjoints[-1].origin.rotation[2]*=-1.0
01253             if mir_ax == 'y':
01254                 newjoints[-1].origin.position[1]*=-1.0
01255                 newjoints[-1].origin.rotation[0]*=-1.0
01256                 newjoints[-1].origin.rotation[2]*=-1.0
01257             if mir_ax == 'z':
01258                 newjoints[-1].origin.position[2]*=-1.0
01259                 newjoints[-1].origin.rotation[0]*=-1.0
01260                 newjoints[-1].origin.rotation[1]*=-1.0
01261 
01262         if mir_ax =='rotx':
01263             newjoints[0].origin.position[1]*=-1.0
01264 
01265         for j in newjoints:
01266             if j.mimic is not None:
01267                 j.mimic.joint_name=re.sub(f,r,j.mimic.joint_name)
01268 
01269         newjoints[0].origin.position+=array(xyz)
01270         newjoints[0].origin.rotation+=array(rpy)
01271 
01272     def fix_mesh_case(self):
01273         for l in self.links:
01274             fname=l.collision.geometry.filename
01275             l.collision.geometry.filename=re.sub(r'\.[Ss][Tt][Ll]','.stl',fname)
01276     #TODO: merge function to tie two chains together from disparate models
01277 
01278     def update_mesh_paths(self,package_name):
01279         """Search and replace package paths in urdf with chosen package name"""
01280         for n,l in self.links.items():
01281             #TODO: check if mesh
01282             for g in [l.collision.geometry,l.visual.geometry]:
01283                 #save STL file name only
01284                 meshfile=g.filename.split('/')[-1]
01285                 newpath=[package_name,'meshes',meshfile]
01286                 cleanpath=re.sub('/+','/','/'.join(newpath))
01287                 g.filename='package://'+cleanpath
01288             l.collision.geometry.filename=re.sub('Body','convhull',l.collision.geometry.filename)
01289 
01290     def apply_default_limits(self,effort,vel,lower,upper,mask=None):
01291         """Apply default limits to all joints and convert continous joints to revolute. Ignores fixed and other joint types."""
01292         for n,j in self.joints.items():
01293             if mask is None or re.search(mask,n):
01294                 if j.joint_type==Joint.CONTINUOUS or j.joint_type==Joint.REVOLUTE:
01295                     j.limits=JointLimit(effort,vel,lower,upper)
01296                     j.joint_type=Joint.REVOLUTE
01297 
01298 if __name__ == '__main__':
01299     #try:
01300         #from openhubo import startup
01301     #except ImportError:
01302         #pass
01303 
01304     try:
01305         filename=sys.argv[1]
01306     except IndexError:
01307         print "Please supply a URDF filename to convert!"
01308 
01309     try:
01310         outname=sys.argv[2]
01311     except IndexError:
01312         outname=None
01313 
01314     model=URDF.load_xml_file(filename)
01315 
01316     model.write_openrave_files(outname)
01317 


naoqi_tools
Author(s): Mikael Arguedas
autogenerated on Thu Aug 27 2015 14:05:48