From 19d414ae6bc6ec3f67669cbb877d563a6d40c099 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 17:11:57 +0200 Subject: [PATCH 01/23] Add first page of specification --- README.md | 2 +- specification/README.md | 33 +++++++++++++++++++++++++++++++++ specification/link.png | Bin 0 -> 95263 bytes 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 specification/README.md create mode 100644 specification/link.png diff --git a/README.md b/README.md index 875d5502..2e427565 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ urdfdom The URDF (U-Robot Description Format) library provides core data structures and a simple XML parsers for populating the class data structures from an URDF file. -For now, the details of the URDF specifications reside on http://ros.org/wiki/urdf +The details of the URDF specifications reside in the specification folder in this repo: [./specification]. ### Build Status [![Build Status](https://travis-ci.org/ros/urdfdom.png)](https://travis-ci.org/ros/urdfdom) diff --git a/specification/README.md b/specification/README.md new file mode 100644 index 00000000..fae2c65e --- /dev/null +++ b/specification/README.md @@ -0,0 +1,33 @@ +# XML Robot Description Format (URDF) + +The Unified Robot Description Format (URDF) is an XML specification to describe a robot. We attempt to keep this specification as general as possible, but obviously the specification cannot describe all robots. The main limitation at this point is that only tree structures can be represented, ruling out all parallel robots. Also, the specification assumes the robot consists of rigid links connected by joints; flexible elements are not supported. The specification covers: + + * Kinematic and dynamic description of the robot + * Visual representation of the robot + * Collision model of the robot + +![link](link.png) + +The description of a robot consists of a set of [link elements](./link.md), and a set of [joint elements](./joint.md) connecting the links together. So a typical robot description looks something like this: + +~~~xml + + + + ... + ... + ... + + .... + .... + .... + +~~~ + +You can see that the root element of the URDF format is a `` element. + +## `` element +For details on the link description format, check out the [link elements](./link.md) page. + +## `` element +For details on the joint description format, check out the [joint elements](./joint.md) page. diff --git a/specification/link.png b/specification/link.png new file mode 100644 index 0000000000000000000000000000000000000000..8f9fe064e3d853c37efd48793bd4b34c45935f20 GIT binary patch literal 95263 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 literal 0 HcmV?d00001 From 6dd05b658d38fc12ec1c41eeba9dcfd7fa1a7f53 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 17:15:06 +0200 Subject: [PATCH 02/23] Update README.md --- specification/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/README.md b/specification/README.md index fae2c65e..d3e6ad25 100644 --- a/specification/README.md +++ b/specification/README.md @@ -6,8 +6,8 @@ The Unified Robot Description Format (URDF) is an XML specification to describe * Visual representation of the robot * Collision model of the robot -![link](link.png) - + Link + The description of a robot consists of a set of [link elements](./link.md), and a set of [joint elements](./joint.md) connecting the links together. So a typical robot description looks something like this: ~~~xml From 1ce7ef7a0cecd08ed859a32313325619b15c78fa Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 17:33:21 +0200 Subject: [PATCH 03/23] Create joint.md --- specification/joint.md | 134 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 specification/joint.md diff --git a/specification/joint.md b/specification/joint.md new file mode 100644 index 00000000..9b2f25cd --- /dev/null +++ b/specification/joint.md @@ -0,0 +1,134 @@ +# Link + +## `` element + +The link element describes a rigid body with an inertia, visual features, and collision properties. + +Here is an example of a link element: + +~~~xml + + + + + + + + + + + + + + + + + + + + + + + + +~~~ +Inertial + +## Attributes + . '''name''' ''(required)'' + . The name of the link itself. + +== Elements == + . '''''' ''(optional: defaults to a zero mass and zero inertia if not specified)'' + . The link’s mass, position of its center of mass, and its central inertia properties. + '''''' ''(optional: defaults to identity if not specified)'' + . This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. + . '''xyz''' ''(optional: defaults to zero vector)'' + . Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as '''x L̂x + y L̂y + z L̂z''', where '''L̂x, L̂y, L̂z''' are link-frame L's orthogonal unit vectors. + '''rpy''' ''(optional: defaults to identity if not specified)'' + . Represents the orientation of C's unit vectors '''Ĉx, Ĉy, Ĉz''' relative to link-frame L as a sequence of Euler rotations (r p y) in radians. Note: '''Ĉx, Ĉy, Ĉz''' do not need to be aligned with the link’s principal axes of inertia. + '''''' + . The mass of the link is represented by the '''value''' attribute of this element + '''''' + . This link's moments of inertia '''ixx, iyy, izz''' and products of inertia '''ixy, ixz, iyz''' about Co (the link’s center of mass) for the unit vectors '''Ĉx, Ĉy, Ĉz''' fixed in the center-of-mass frame C. Note: the orientation of '''Ĉx, Ĉy, Ĉz''' relative to '''L̂x, L̂y, L̂z''' is specified by the rpy values in the tag. The attributes '''ixx, ixy, ixz, iyy, iyz, izz''' for some primitive shapes are [[https://en.wikipedia.org/wiki/List_of_moments_of_inertia#List_of_3D_inertia_tensors|here]]. URDF assumes a negative product of inertia convention (for more info, see [[https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia.html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c|these MathWorks docs]] for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align '''Ĉx, Ĉy, Ĉz''' with principal inertia directions so that all the products of inertia are zero. + '''''' ''(optional)'' + . The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. '''Note:''' multiple instances of tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. + + '''name''' ''(optional)'' + . Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. + + '''''' ''(optional: defaults to identity if not specified)'' + . The reference frame of the visual element with respect to the reference frame of the link. + '''xyz''' ''(optional: defaults to zero vector)'' + . Represents the '''x''', '''y''', '''z''' offset. + '''rpy''' ''(optional: defaults to identity if not specified)'' + . Represents the fixed axis roll, pitch and yaw angles in radians. + '''''' ''(required)'' + . The shape of the visual object. This can be ''one'' of the following: + . '''''' + . '''size''' attribute contains the three side lengths of the box. The origin of the box is in its center. + '''''' + . Specify the '''radius''' and '''length'''. The origin of the cylinder is in its center. {{attachment:cylinder_coordinates.png||height="10%",width="10%"}} + '''''' + . Specify the '''radius'''. The origin of the sphere is in its center. + '''''' + . A trimesh element specified by a '''filename''', and an optional '''scale''' that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with '''package:///''' to make the path to the mesh file relative to the package . + '''''' ''(optional)'' + . The material of the visual element. It is allowed to specify a material element outside of the 'link' object, in the top level 'robot' element. From within a link element you can then reference the material by name. + .'''name''' name of the material + .'''''' ''(optional)'' + '''rgba''' The color of a material specified by set of four numbers representing red/green/blue/alpha, each in the range of [0,1]. + '''''' ''(optional)'' + . The texture of a material is specified by a '''filename''' + + '''''' ''(optional)'' + . The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time. '''Note:''' multiple instances of tags can exist for the same link. The union of the geometry they define forms the collision representation of the link. + + '''name''' ''(optional)'' + . Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. + '''''' ''(optional: defaults to identity if not specified)'' + . The reference frame of the collision element, relative to the reference frame of the link. + '''xyz''' ''(optional: defaults to zero vector)'' + . Represents the '''x''', '''y''', '''z''' offset. + '''rpy''' ''(optional: defaults to identity if not specified)'' + . Represents the fixed axis roll, pitch and yaw angles in radians. + '''''' + . See the geometry description in the above visual element. + +# Recommended Mesh Resolution + * For collision checking using the [[moveit| ROS motion planning]] packages, as few faces per link as possible are recommended for the collision meshes that you put into the URDF (ideally less than 1000). If possible, approximating the meshes with other primitives is encouraged. + +# Multiple Collision Bodies + +It was decided that URDFs should not support multiple groups of collision bodies, even though there are sometimes applications for this. The URDF is intended to only represent the actual robot's properties, and not collisions used for external things like controller collision checking. In a URDF, the elements should be as accurate as possible to the real robot, and the elements should still be a close approximation, albeit with far fewer triangles in the meshes. + +If you do need coarser-grain, over sized collision geometries for things like collision checking and controllers, you can move these meshes/geometries to custom XML elements. For example, if your controllers need some special rough collision checking geometry, you could add the tag after the element: + +~~~xml + + + + + + + + + + + + + + + + + + + + + ... + + +~~~ + +A URDF will ignore these custom elements like "collision_checking", and your particular program can parse the XML itself to get this information. + From 740f78ebecf915b88fd6721a06194b5fa513b5da Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 17:34:38 +0200 Subject: [PATCH 04/23] Rename joint.md to link.md --- specification/{joint.md => link.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename specification/{joint.md => link.md} (100%) diff --git a/specification/joint.md b/specification/link.md similarity index 100% rename from specification/joint.md rename to specification/link.md From 7a616d9eaaf572b911b5bfd019d667ce5ef24975 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 17:35:54 +0200 Subject: [PATCH 05/23] Add files via upload --- specification/inertial.png | Bin 0 -> 83691 bytes specification/joint.png | Bin 0 -> 75034 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 specification/inertial.png create mode 100644 specification/joint.png diff --git a/specification/inertial.png b/specification/inertial.png new file mode 100644 index 0000000000000000000000000000000000000000..71048119180398ccc19fb72160462218099a31cc GIT binary patch literal 83691 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≫9hx<380H! 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 z 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­F_NpWql&uyZ=mFPFwFO_{KRM26+b04vxw!vBBPrQwZ-5k+iUDlD94<9uq40F z^bF}iBzd*_ZVIZ9tgfK3u1p?J@yQoqhJ4D4E760pJ5c8T$gnZS%y#|I>d&MRIZaxa z1U-GA?~Ck-!}c1f7(~_|4M52nedn=IC4Z@a+hgx|^yS{^_kV|tHl`MxdzV^hFt0yPSSiUpi)ZU^%gK2>r(tj3%AKlD zYABZqbk~3~EqDw@HwIgLgl^a=%Q?Q9*ZdwxQ#L*0hD|995XqfZ8ZZ2zGe$cNm@`eA zZA7F?2BCHi;_~GrNTQgRJQLqV8}T$SJ@HOo%u~Wjka3|ayzTMUO9}dYxGY+6Hdtgr zxL?17IsqJDF-`OXUp`m69eAcze#jN{o14@yrB4@MQ38#V;Ktd^Djlg|R}z>^av00y5hQTiI`>UYm>?Q(bad3&xXNX8 za6F>Huspix?KGZyiZ~)+$}LKtv(UTxm}Fa|b+i;1sY1D?MM|Gos>yKTueGV2 zwz4%QrIk#63OCD%U91i|sw?C_IM{(z*3Px-1w|%}GaL#ngkU`PU*)C9XAXtxrSu8t zAup^RI=)90m9C!LL(g`Tvax%6pt#WRB^q7U&zMLZyQr}8X~t7?0E=;n2l;*ll+wPY zcOF9fP>UBKn8`SI>HxA2*3&CIH=NVVCe`eTY4emmwPDMEH?BT8`L5r#KGF=Lk7>Ei zy&*M7j=BEtJ&GQ9SCW<@j7VdQ;{6GtII<_Wp_I^Up({6xQ#M;a zU;^uuih@^h-Q{jM7ed0@Yc#kz0zd3)v>|i_Uk--))rpMjHtg|#aAlagf+>=J-I^HY z7+G;7`SLTOUD4)p{_K44J#gFBNu#UKimso|k59TKiI4)Z=1A00lesuubc{>$n=+yZ z_@2oe&Eu&N6Hm27p>Qu!9h6J9(y>V+ z5p%0Dic((9Q5A!3j(DV6Ip=UWaTb;_Rxh}&fs#zH1+Kan3v8cL$HDCA3#BV)f+85m zzAugd4{6v^(AQm0E+%mmq6>YD33ugLMfNvkIR%mZut-6zOU1AULWE>P3>W2FeoV#} zx{~s1v&@~Z@Yj=kw7_btrWFG{H6AeBJ^bJb6sW`6?-7jw>etz6Fr*|CuJSlT8kCnx21x@Z;I-Fg3sIdub7S#A6X#;VQ@>7!I;Gh%pjc%l8j7OZilx0f}r* zq%Naspaj+I(Kz}NH>SlVWrbtT1jcJk4%sXbTbOedp%{gk^WLCL-*cpO?IItg-+Vu8 zd9F}C0d@7og(^wc<;3h3zY7E>!3C&PlovDtVX8ibQ0UnVX4qlM_&#Ne}7c4{M?Sp72D{K)obgNH0U0 zZt{WXl<{f`fsIUo%5?G<`=1jq&>5}w;PHwdri7WfH`b=3{+OzL_Ocr^fzeO!ndgDHBi~Z zQThU2RDIJ_JIqd0m$}a5y5St^NLI?9oSOtuS^C{H`IIlp^X(Q1vZa5lfN3!B3hy^= z#Nyewrx*(mzu07KPuG}>AE_n>s(McsSUp@M(=u>9QTg?)%C31jD))-QL~TFqZnrGW z;uYp=l4-n6sEJ}LDe|k(y1YwrohQmet z6TQ!X=1tITmPnN$0&2F^RUI=kByL;zS@CjQ#Dm6KTUWM_xP<+m9STjWQ88H!h>4i! z`?40d@r2V{PgGWPCN>z{r7#(X`O)2YmBD zikO87C*GBlaHur^IS%K(e*tAe+iv0Gw92rTUWm6?s7d0EQBaz=Q#k1)NFy{-4Sf?qK41K>OIt?U`5M9zlSatZ+Rl~iiDN&kl zMSeW=b;=~hbae}MAj6V>`DzYvbs!U9OnVD}zqwPDkbN+df|Nrs2k?^n>j7yr0;Jag zvR^YlbKUzvdWy39xuR=w1!m>BL{C+cU@1mk3SAPNE_qx%I66}bj&T2e8CFvnMsNOt z6JYq5b5R61SVn!njV@h?D9)iYS%W2)JHg4EX-eNi@CAd5hvLh`l@{Pn9xS9)dq=!) zDX4bJ@;?!AGhjtfgbPpDW_>r=Fm*+Z3L z+-X#~dX%i%VlA|o^ckLa>n*Jmm9$hKb=Z0$EO13fg?k##EyCbVI!B3QIOiE@wRDkC z(d9llY2@{L)yk7WK^zgEy?WG%C3ea;KfjrWn?bF}3wi0aik`CSD`l7tZ6}m>0av%1 zEWF0EfT*jbMm)>7gtr zLjGdypkGQcz_ji62#Ib0(W9(tAJ`^@C3H}8BqHyho41-&(jx>%0gNHM3kNusa9`xW zACQk!wGwzkNeDlu1m!v!xK239Y`e=47DiL;M>tuyr?!xw#ZFpuO`CZrW5h9zHAR7U z+=BxXommg;n+f?lXVh#uzB45HZ1*nLg+jSGni>=rNl7ZL80p#{tSJVd>!zw+C^Dk< zCl3F0Jr_-%S%pzorKQ^(HJM*kHRd~+mx@qLcSdf-VOm<21k2~cafA<>1tJMVy`iG*5Jy&k>NB8~W6xt7c7(FXl{xqI!jB{8WGG&84QX%7F5baZev zo}`}aTyBXu9?jOm(=aj2|DY^?{A?PK9&+s);jk7V$BpUV^1!imz*~h@c#dw2ahGfA zL_dt9{ZXu!Kr9T&tlrtkTx-OA=JU}x$9%mwvR}`s4pjKb<_fANdnWiOPs5jEQYP1; zn&DwP?(4S-CqtO;0!AGDiSn(}BtO>0WJ-@ogr^4tKL5{)X6nC3hG69+GC6U3-_gy@ zw|uQwj^_^O#^m4r`}w{@wG@kOnlo|mXzH0ILmEDw>*zLxX5~*EnxUYC?-IH z@X|TY{FAO+MIZd>C@1#^avFx&X@XzkuyRqGH^U8$7wcK)HK<1OwGpQ zOw=lgtjXhGr`+s5P94c3Bq2}oTKWoKIVA=Y5%0eDzW!9MWj|;=pJ9o9dvwDH5Rebv zmf#nS>6+CyQ1XW^7<-l=RT}4p!E?dOnHkLP?`#05r^#cCm{DMP8Yx_)4}qU^YuY` zAHZD&NrjPC=(ywz>Gq+WJ=@Jw*-0O(wS7}tRRk|BF`t&3m->9_($Hd@e+n_(k>|a* z`Vo0jZGNiBnEUR3x+Cc~5g+<=H2Lkw{az_bHJ&R<)iQH6I4z{I$Gt{rw5R5&WAe~_ zj3&05qfjVIpR-jedA8o8N)>eTCgh|96z z=zWSlXL(Es-_#fX%|vgDBZ9@Scbx^&1=VEd0v}eaXj(qyElC_5GSJCqTyrW(v~9+r z7yt9C>VTZhfeZ_huH8qD3VB;jG=Q;#je3;#Kd*aZh$%zd7Qc6eWjpzaH>)Z)YK*Dd zO@Q=*4Ttx8*%9L!7#PLqD_)Hbj(CE4^AKyp?|-WM+D{Ngh9@L)Wk`WL=SbF1F;oZ< z6Y6Hzdt;7yK~GK5@vDl)8X>v2j>fa~-)&mE!nRdbf_w-M75J_Jjd}5&xASwcb%WE_ z_!aG$v}{4wOqqJnU3vuD1M)W zIDZ()#P9Im^tI<$_xRsvG%YP)DDhN*mb9Po>p%mTt$$u0tLKkz;SM38<7%4ym36|L z?vJvT=0zs^FV5%G6<2HIk24`czI_Rvx7J8Y0_tQ%Ha0r&JXBFwKrLEUl76c>KH48* zo5Y0Fk+o|kL}>=sbNUa)$B_8FA~&if8DoAIKS2;j63G|I<{|O#v|w*8BQfimnL?}n z+jDaK{fXe0!v21E|;#fHeav)sQmu9DpKG@3irIJ=^1Thgi3o= zUh+5Tw`b49n+Ey?xZKuV4IiQFPcIvKR3hKnkt123i>hV~>Dh&=n2K7rkny*=;Sq(i zXf?Ig_`UcH9pWvq)(v)B1O4(AxztZ<;F`<*Tkf zg!Ln;Fh%fgM@vWdX#$czjeIcs(!1CF%x7+nJXNm>sRmu>hVJ@RfI5JQ#e(^YLLtOc84lim6of|DlH^r?hSH=f_O#kmO zVepue6hV|XHGgc6n}@xC4cM9uzN3#1>~R4V>`K#o`e_kv-9JdaaWM_aW zvqMsaLZ#MzvM?)}VQIY(*3YKsLRJ;V-n6{c@6BlI!kA6a3*PhbUfbL4j}JE zjv;;LY)}%w82|@z_~EyrgPZ=X?b5BTo$Mp@WW0>|mh@sX;}`n=;~`ysJTx98N<7Hu zro+AvOvcp?*}+0RYGVnrx^*r3B!($Sl0UsCrBp&pBxC7B4DRjY%7LuEx)mm7F+}m3 zo2;@vHT)m&v;w#0+a7R63YMTgrNQ6FZ-wW)m|jsf9K6Rp`NZ#5+MEnRUPv^vF)Bp@ zo!R>r6aTRb9pY@K?KW{5{=cTKJRGX;jn874kw$h|%T}Vz)R+`wpGaa%Y9!f3*$GW* zCR6r(kYr!WPBJo>kjW4VCB`x`5wfpIev|J%zxzD*ulwBRJ?CA{=X2io-uImUP8HO; z%F^b8A$+W^iAQ1M-ox>T^nIY$F*%){cAO=$0WOxm=NjkiUsOUNElM#wM)&aX|-1t7hke6xgWjH2xl#=pKCb+c)uNo!1)Kr$tI3xg0wr&H(97-(BqY%O3vcLb zzFKR^m<3vDwb^_=_NFF!CSUziBj!l(vZ%^sSI*xn^(G9qq>98+)5%LduR@+amgKgL zZT^7_3IOeXl(*n}ck{kdi;s+iF!XzzQ3v>;0Q16`t@yKvC$C*JetSB0-PAcIh^`rH zb5izYQcIPg%br-FbM^xAL$ap$;B{XPODtEJPQv;Y5D9D|9Ns7dEK5Xt81?uBv zM~{A9;aE%6K=2Bfn+eB@`3cC{1q5pNwb&P`g!iC3^D(xirB3G1VFmQ{{-JipMH1iD zWlp_>YRj`Tj&kI=0eToHhgRo>RlY4r--^|@IAao_)0RqS{av4s*W=j2_l(Ktc|1iT z+g-AGEeI;7*@n{^QR^L?dyXgud`K;b^q#9%RXuRbVMGQr3i9mbX+(ASp=1g^g|u!V zyL2gHENSwV4sXjyP`#Dc7cl@%bxPrZIC9@2XaTTc{!wG~{B!@^$bMrb#)jZ%90tsF z;2yB&JIlJP?&Hdy8~sEcOtFi}SDmljPQS}ef@r)iHzWr7bar&>A%&5a?rcBo%C+Az zGBz#<6QJy<03j|8R0jecQg>2wYQ)y0oF}X}roJWC3A%vg^fu%BO%w)7r4XrbX^3MiJYpQmdBovW96|S0@m(m4E**UPK&?fRspK>6X*U)#ylXlx z&BVRJ`{(`rRY@QVg=+;OWmvj)k|x6QekYAyDzzNLDY#m+iwk9G>Qo_a3tDKa_e!$GDIIj!1)GZs zhC|s=FAF7#-|xH&K8~+f`w3xu#pBa%;5u5P#C%tBpWJx#_4o!l&^QXLwMGkWSb(cX11~I!w+6i}q3wdl%J+NUNzbzXt$>e?8;5bfvU zT~pmTzYZf`zKBIPx|`nT zF;}#3va}y2F+!@% zQpOj3?08!EMKn5+h?ZZ#rH(uls1>L}k@{**pU1YDyej*(OZTgmT14YayZx=tkKj3H z#qK2A99DX3JdECM+H)h9%A~_U3-WoMQRpuU9)7R4U99oi_Jmi;rGjwKyiR?%0bFOP zd3#;`$t3hcCh1y*9fB_OWY~gvoW;4nHVsNFDd3-FO{V_>L%3^eTte@@D=QS;er^E7 zqQ|h>W^Y^V-w+zOqMUjZj7}t}FH`o_IXp{0)`pthJQsJ$(l~{{b@5)j{gp>H_e*3C zvSoL(OY|0}24a{#-k@MJ3|1jN!{~x3~`_^~0&|Mw8cCDpWH(KX$N8q0&^W*EL zX}}9XgT+#7#Mi&0pxjsQAU@orq25&`QiSIYEOwfkk3AhMH99tf+#hxYaL6WGYVC@? zSAu46j|3*n^k)`(`E+PcoWEK49?LQA>8ONi1=#*BQI)w&egGKvHqz9e-aoY8GtGuv z)A#dEvAH>(aQW1-*O(#moWwx1(lfrhz`u>CE#wJUi9^M@l8Ls1LjD@FZ(`AX?&{%f zTxKnD58%y!MOL5|+QSGT+>xlK2*%pPJFO)7n>)M%WvQyp-Qj_3`rpb=k z0^#h6IEE>w7b=Hc%_!t#8`1mURmJS|O-8cdroN4vgo*+|hx=4&cVC}Ks^*9d3|Mif zzL(Wg_C*8+=WIaWm~%T1!eQe}v1YR1-od9Er;~_N^R1W6XPm~FVq4WBHE|7uCvGtb zJR`;SBx@Z(ZM6X3berR%`U^>#DrD=e#M0#1>H~%UblPRiA`gLc)BTJ3JANHa1>R9{ zjOk}o_>{pq^no;cMk^rq5$;gV~+Xw7)wKtVzX?MgZJ(x%073>5IAe6U1LMOWGTA^E`}d zRGdaRscJO$uS$J;mv-9twaXEF#1fbodM>;_cpec^~Ri%W`3P|;F)KyN=!lU1Hk`MPd z^%3v{8V3x8Nn^)xB;G{n($vJ;WGiOqMmOi!66c4gjDZ1WAG2%5Th21q!bCbiSR~-- z$NK@}nQqJeM~lPglJw%1Ql&V=xUZc$J+WL1lGWa7X;70&08AV00D}5)2`JKv4TRZXL6ZBTA5oE0K z6-lRKu~YYQQl=(<3x0E#s%P9#)f7F<$89H{|7*j B(_R1o literal 0 HcmV?d00001 From 84f6ca17ea07a96b35a1823d145a1979331cbb19 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 22:41:24 +0200 Subject: [PATCH 06/23] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e427565..c8f3f2df 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ urdfdom The URDF (U-Robot Description Format) library provides core data structures and a simple XML parsers for populating the class data structures from an URDF file. -The details of the URDF specifications reside in the specification folder in this repo: [./specification]. +The details of the URDF specifications reside in the [specification folder](specification) in this repo. ### Build Status [![Build Status](https://travis-ci.org/ros/urdfdom.png)](https://travis-ci.org/ros/urdfdom) From 5960e8a8ed3e6b8309106039c15c572818f017e0 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 22:52:44 +0200 Subject: [PATCH 07/23] Update link.md --- specification/link.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/specification/link.md b/specification/link.md index 9b2f25cd..3bc03d42 100644 --- a/specification/link.md +++ b/specification/link.md @@ -35,24 +35,24 @@ Here is an example of a link element: Inertial ## Attributes - . '''name''' ''(required)'' - . The name of the link itself. - -== Elements == - . '''''' ''(optional: defaults to a zero mass and zero inertia if not specified)'' - . The link’s mass, position of its center of mass, and its central inertia properties. - '''''' ''(optional: defaults to identity if not specified)'' - . This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. - . '''xyz''' ''(optional: defaults to zero vector)'' - . Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as '''x L̂x + y L̂y + z L̂z''', where '''L̂x, L̂y, L̂z''' are link-frame L's orthogonal unit vectors. - '''rpy''' ''(optional: defaults to identity if not specified)'' - . Represents the orientation of C's unit vectors '''Ĉx, Ĉy, Ĉz''' relative to link-frame L as a sequence of Euler rotations (r p y) in radians. Note: '''Ĉx, Ĉy, Ĉz''' do not need to be aligned with the link’s principal axes of inertia. - '''''' - . The mass of the link is represented by the '''value''' attribute of this element - '''''' - . This link's moments of inertia '''ixx, iyy, izz''' and products of inertia '''ixy, ixz, iyz''' about Co (the link’s center of mass) for the unit vectors '''Ĉx, Ĉy, Ĉz''' fixed in the center-of-mass frame C. Note: the orientation of '''Ĉx, Ĉy, Ĉz''' relative to '''L̂x, L̂y, L̂z''' is specified by the rpy values in the tag. The attributes '''ixx, ixy, ixz, iyy, iyz, izz''' for some primitive shapes are [[https://en.wikipedia.org/wiki/List_of_moments_of_inertia#List_of_3D_inertia_tensors|here]]. URDF assumes a negative product of inertia convention (for more info, see [[https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia.html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c|these MathWorks docs]] for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align '''Ĉx, Ĉy, Ĉz''' with principal inertia directions so that all the products of inertia are zero. - '''''' ''(optional)'' - . The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. '''Note:''' multiple instances of tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. + * **`name`** *(required)* + * The name of the link itself. + +## Elements + * **``** *(optional: defaults to a zero mass and zero inertia if not specified)* + * The link’s mass, position of its center of mass, and its central inertia properties. + * **``** *(optional: defaults to identity if not specified)* + * This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. + * **`xyz`** *(optional: defaults to zero vector)* + * Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as **x L̂x + y L̂y + z L̂z**, where **L̂x, L̂y, L̂z** are link-frame L's orthogonal unit vectors. + * **`rpy`** *(optional: defaults to identity if not specified)* + * Represents the orientation of C's unit vectors **Ĉx, Ĉy, Ĉz** relative to link-frame L as a sequence of Euler rotations (r p y) in radians. Note: **Ĉx, Ĉy, Ĉz** do not need to be aligned with the link’s principal axes of inertia. + * **``** + * The mass of the link is represented by the '''value''' attribute of this element + * **``** + * This link's moments of inertia **ixx, iyy, izz** and products of inertia **ixy, ixz, iyz** about Co (the link’s center of mass) for the unit vectors **Ĉx, Ĉy, Ĉz** fixed in the center-of-mass frame C. Note: the orientation of **Ĉx, Ĉy, Ĉz** relative to **L̂x, L̂y, L̂z** is specified by the rpy values in the tag. The attributes **ixx, ixy, ixz, iyy, iyz, izz** for some primitive shapes are [here](https://en.wikipedia.org/wiki/List_of_moments_of_inertia#List_of_3D_inertia_tensors). URDF assumes a negative product of inertia convention (for more info, see [these MathWorks docs](https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia.html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c) for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align **Ĉx, Ĉy, Ĉz** with principal inertia directions so that all the products of inertia are zero. + **``** *(optional)* + . The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. **Note:** multiple instances of tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. '''name''' ''(optional)'' . Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. From 8724dc5fa99a69105f86c2d32668ded6a804bdec Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 23:02:19 +0200 Subject: [PATCH 08/23] Update --- specification/cylinder_coordinates.png | Bin 0 -> 5530 bytes specification/link.md | 114 ++++++++++++------------- 2 files changed, 57 insertions(+), 57 deletions(-) create mode 100644 specification/cylinder_coordinates.png diff --git a/specification/cylinder_coordinates.png b/specification/cylinder_coordinates.png new file mode 100644 index 0000000000000000000000000000000000000000..828b9ba6aa568454a8856b9224fe2569d3c200e3 GIT binary patch literal 5530 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

Y>GZ7S4Rs`lg$w=TvL>QB%O$4~7a8 zGZ>Wp8!MdJpr62t@&3De?IwVg!iwTY13_%Y(V{Y~CXe!uEb%OHfl)RlRiSQc_Y9 zs7pjetKPi1SO+0)&{P3d4c5QMLnk}>ZDho;&O$;$0_O4cN%19@z)bG6395!SDvBB^ zZW34&bLs>Yp_r;jDh5$@p=^M|)=l}}ZnE?4+n4?yy8juw_k8T2vxH8Epl{@51ALUa zUsKuogi6#EWo10XGx?^kg3dlH_RnD#$67ofFeKv910$n$r&>@*;yu{B*^8vm>x)_F99c3~QUurJ`Z-H=vT>#wDAD%klQS)nm9|nV6Ki4PR{Ie24YYk7&ilJq9 z50B#w^d<;1(u*oU5Z*m3{{g>HB$X`$>IP3Yx2N6nDGGaL6Gf%=K!8`m_Cd*wxuu`S z6YKcLAB|Qb32H{x*1C|g^76#)d2l`|(PeUU5K?9q7CAXNyvH7J#WPSzlnj*VRv}_j zOG-)#HBdi|8C2! zlD|nE+%nxT6Co$_lNUQUn5@S2%Tf;l;04r>|1G;$C2f@1DdIe&K$XtI#Pq?UB26pS z%d~uyo}RwAxHz;WLIkm0qCgn_023&>64&mW7ZOkX4I~;sAwas<1H*!XVCz3VU#J1x z=^}~8@^V;qgj7?RLi;K%kPlO`o z_3PIkKKOtV6%=MGu;;I?5!AWTU^55_D8+E3I@d5xUnv|W@ely5hg6Wi|F@=qK1Xr< z`raMt+)g8YsCeeH?s?$dpsHWq;ibEh(mlT&Oqbwz_=`Y9wAqQV0`{dLk7+aDU)VqD znETK@e`E7$GPtN%+x-}ncsEf;68+0!;nM|gov$8&D!&cxfIPnop%X>{>_AWbE+~@r z`7TB&^Fy7SoW6*@(&7PS%?KMDOS)DJh%K@6jddKjbD$yvnJ-{)bN?1{;f`VX=*Q)( zW7L3Chm^)*;nj^P^5*SX-$sjyKw}iYz2loq$~d@J!{qsW$c2W0DoGz*fZJVfY~0@p0T)oF?KX`o4-P1b5&`+bS{e<9ZYaUCgvI=e)xS>dQ3 Tlzbc9tCHMP*Hf#6+eQBeV7TMG literal 0 HcmV?d00001 diff --git a/specification/link.md b/specification/link.md index 3bc03d42..4209f953 100644 --- a/specification/link.md +++ b/specification/link.md @@ -35,65 +35,65 @@ Here is an example of a link element: Inertial ## Attributes - * **`name`** *(required)* - * The name of the link itself. + * **`name`** *(required)* + * The name of the link itself. ## Elements - * **``** *(optional: defaults to a zero mass and zero inertia if not specified)* - * The link’s mass, position of its center of mass, and its central inertia properties. - * **``** *(optional: defaults to identity if not specified)* - * This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. - * **`xyz`** *(optional: defaults to zero vector)* - * Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as **x L̂x + y L̂y + z L̂z**, where **L̂x, L̂y, L̂z** are link-frame L's orthogonal unit vectors. - * **`rpy`** *(optional: defaults to identity if not specified)* - * Represents the orientation of C's unit vectors **Ĉx, Ĉy, Ĉz** relative to link-frame L as a sequence of Euler rotations (r p y) in radians. Note: **Ĉx, Ĉy, Ĉz** do not need to be aligned with the link’s principal axes of inertia. - * **``** - * The mass of the link is represented by the '''value''' attribute of this element - * **``** - * This link's moments of inertia **ixx, iyy, izz** and products of inertia **ixy, ixz, iyz** about Co (the link’s center of mass) for the unit vectors **Ĉx, Ĉy, Ĉz** fixed in the center-of-mass frame C. Note: the orientation of **Ĉx, Ĉy, Ĉz** relative to **L̂x, L̂y, L̂z** is specified by the rpy values in the tag. The attributes **ixx, ixy, ixz, iyy, iyz, izz** for some primitive shapes are [here](https://en.wikipedia.org/wiki/List_of_moments_of_inertia#List_of_3D_inertia_tensors). URDF assumes a negative product of inertia convention (for more info, see [these MathWorks docs](https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia.html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c) for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align **Ĉx, Ĉy, Ĉz** with principal inertia directions so that all the products of inertia are zero. - **``** *(optional)* - . The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. **Note:** multiple instances of tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. - - '''name''' ''(optional)'' - . Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. - - '''''' ''(optional: defaults to identity if not specified)'' - . The reference frame of the visual element with respect to the reference frame of the link. - '''xyz''' ''(optional: defaults to zero vector)'' - . Represents the '''x''', '''y''', '''z''' offset. - '''rpy''' ''(optional: defaults to identity if not specified)'' - . Represents the fixed axis roll, pitch and yaw angles in radians. - '''''' ''(required)'' - . The shape of the visual object. This can be ''one'' of the following: - . '''''' - . '''size''' attribute contains the three side lengths of the box. The origin of the box is in its center. - '''''' - . Specify the '''radius''' and '''length'''. The origin of the cylinder is in its center. {{attachment:cylinder_coordinates.png||height="10%",width="10%"}} - '''''' - . Specify the '''radius'''. The origin of the sphere is in its center. - '''''' - . A trimesh element specified by a '''filename''', and an optional '''scale''' that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with '''package:///''' to make the path to the mesh file relative to the package . - '''''' ''(optional)'' - . The material of the visual element. It is allowed to specify a material element outside of the 'link' object, in the top level 'robot' element. From within a link element you can then reference the material by name. - .'''name''' name of the material - .'''''' ''(optional)'' - '''rgba''' The color of a material specified by set of four numbers representing red/green/blue/alpha, each in the range of [0,1]. - '''''' ''(optional)'' - . The texture of a material is specified by a '''filename''' - - '''''' ''(optional)'' - . The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time. '''Note:''' multiple instances of tags can exist for the same link. The union of the geometry they define forms the collision representation of the link. - - '''name''' ''(optional)'' - . Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. - '''''' ''(optional: defaults to identity if not specified)'' - . The reference frame of the collision element, relative to the reference frame of the link. - '''xyz''' ''(optional: defaults to zero vector)'' - . Represents the '''x''', '''y''', '''z''' offset. - '''rpy''' ''(optional: defaults to identity if not specified)'' - . Represents the fixed axis roll, pitch and yaw angles in radians. - '''''' - . See the geometry description in the above visual element. + * **``** *(optional: defaults to a zero mass and zero inertia if not specified)* + * The link’s mass, position of its center of mass, and its central inertia properties. + * **``** *(optional: defaults to identity if not specified)* + * This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. + * **`xyz`** *(optional: defaults to zero vector)* + * Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as **x L̂x + y L̂y + z L̂z**, where **L̂x, L̂y, L̂z** are link-frame L's orthogonal unit vectors. + * **`rpy`** *(optional: defaults to identity if not specified)* + * Represents the orientation of C's unit vectors **Ĉx, Ĉy, Ĉz** relative to link-frame L as a sequence of Euler rotations (r p y) in radians. Note: **Ĉx, Ĉy, Ĉz** do not need to be aligned with the link’s principal axes of inertia. + * **``** + * The mass of the link is represented by the **`value`** attribute of this element + * **``** + * This link's moments of inertia **ixx, iyy, izz** and products of inertia **ixy, ixz, iyz** about Co (the link’s center of mass) for the unit vectors **Ĉx, Ĉy, Ĉz** fixed in the center-of-mass frame C. Note: the orientation of **Ĉx, Ĉy, Ĉz** relative to **L̂x, L̂y, L̂z** is specified by the rpy values in the tag. The attributes **ixx, ixy, ixz, iyy, iyz, izz** for some primitive shapes are [here](https://en.wikipedia.org/wiki/ List_of_moments_of_inertia#List_of_3D_inertia_tensors). URDF assumes a negative product of inertia convention (for more info, see [these MathWorks docs](https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia. html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c) for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align **Ĉx, Ĉy, Ĉz** with principal inertia directions so that all the products of inertia are zero. + * **``** *(optional)* + * The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. + + * **name** *(optional)* + * Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. + + * **``** *(optional: defaults to identity if not specified)* + * The reference frame of the visual element with respect to the reference frame of the link. + * **`xyz`** *(optional: defaults to zero vector)* + * Represents the **x**, **y**, **z** offset. + * **rpy** *(optional: defaults to identity if not specified)* + * Represents the fixed axis roll, pitch and yaw angles in radians. + * **``** *(required)* + * The shape of the visual object. This can be *one* of the following: + * **``** + * **`size`** attribute contains the three side lengths of the box. The origin of the box is in its center. + * **``** + * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Inertial + * **``** + * Specify the **`radius`**. The origin of the sphere is in its center. + * **``** + * A trimesh element specified by a **filename**, and an optional **scale** that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with **`package:// /`** to make the path to the mesh file relative to the package ``. + * **``** *(optional)* + * The material of the visual element. It is allowed to specify a material element outside of the 'link' object, in the top level 'robot' element. From within a link element you can then reference the material by name. + * **`name`** name of the material + * **``** *(optional)* + * **`rgba`** The color of a material specified by set of four numbers representing red/green/blue/alpha, each in the range of [0,1]. + * **``** *(optional)* + * The texture of a material is specified by a **filename** + + * **``** *(optional)* + * The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the collision representation of the link. + + * **`name`** *(optional)* + * Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. + * **``** *(optional: defaults to identity if not specified)* + * The reference frame of the collision element, relative to the reference frame of the link. + * **`xyz`** *(optional: defaults to zero vector)* + * Represents the **x**, **y**, **z** offset. + * **`rpy`** *(optional: defaults to identity if not specified)* + * Represents the fixed axis roll, pitch and yaw angles in radians. + * **``** + * See the geometry description in the above visual element. # Recommended Mesh Resolution * For collision checking using the [[moveit| ROS motion planning]] packages, as few faces per link as possible are recommended for the collision meshes that you put into the URDF (ideally less than 1000). If possible, approximating the meshes with other primitives is encouraged. From 7f760db03757514f7528c847bae93f45297eea15 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 23:03:01 +0200 Subject: [PATCH 09/23] Update link.md --- specification/link.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/link.md b/specification/link.md index 4209f953..5e60b74e 100644 --- a/specification/link.md +++ b/specification/link.md @@ -68,7 +68,7 @@ Here is an example of a link element: * **``** * **`size`** attribute contains the three side lengths of the box. The origin of the box is in its center. * **``** - * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Inertial + * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Cylinder Coordinates * **``** * Specify the **`radius`**. The origin of the sphere is in its center. * **``** From ce500215c067a2e2e2154c430e5adadb86b58ab2 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 23:04:16 +0200 Subject: [PATCH 10/23] Update link.md --- specification/link.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/link.md b/specification/link.md index 5e60b74e..b51f2776 100644 --- a/specification/link.md +++ b/specification/link.md @@ -68,7 +68,7 @@ Here is an example of a link element: * **``** * **`size`** attribute contains the three side lengths of the box. The origin of the box is in its center. * **``** - * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Cylinder Coordinates + * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Cylinder Coordinates * **``** * Specify the **`radius`**. The origin of the sphere is in its center. * **``** From 26e3b0cc5696782a141f007c3d9b86ec9e383375 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 23:04:55 +0200 Subject: [PATCH 11/23] Update link.md --- specification/link.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/specification/link.md b/specification/link.md index b51f2776..2aa07161 100644 --- a/specification/link.md +++ b/specification/link.md @@ -68,7 +68,7 @@ Here is an example of a link element: * **``** * **`size`** attribute contains the three side lengths of the box. The origin of the box is in its center. * **``** - * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Cylinder Coordinates + * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Cylinder Coordinates * **``** * Specify the **`radius`**. The origin of the sphere is in its center. * **``** From b63f71570dda653a6c10d69774cba77f41ab1069 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Tue, 9 May 2023 23:06:06 +0200 Subject: [PATCH 12/23] Update link.md --- specification/link.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/specification/link.md b/specification/link.md index 2aa07161..97bd17ed 100644 --- a/specification/link.md +++ b/specification/link.md @@ -72,14 +72,14 @@ Here is an example of a link element: * **``** * Specify the **`radius`**. The origin of the sphere is in its center. * **``** - * A trimesh element specified by a **filename**, and an optional **scale** that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with **`package:// /`** to make the path to the mesh file relative to the package ``. + * A trimesh element specified by a **`filename`**, and an optional **`scale`** that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with **`package:///`** to make the path to the mesh file relative to the package ``. * **``** *(optional)* * The material of the visual element. It is allowed to specify a material element outside of the 'link' object, in the top level 'robot' element. From within a link element you can then reference the material by name. * **`name`** name of the material * **``** *(optional)* * **`rgba`** The color of a material specified by set of four numbers representing red/green/blue/alpha, each in the range of [0,1]. * **``** *(optional)* - * The texture of a material is specified by a **filename** + * The texture of a material is specified by a **`filename`** * **``** *(optional)* * The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the collision representation of the link. From e317633083996a6cef7072c9c1cb48f282d8cdd9 Mon Sep 17 00:00:00 2001 From: harleylara Date: Thu, 15 Feb 2024 11:24:10 +0100 Subject: [PATCH 13/23] add robot and link --- specification/README.md | 8 +- specification/joint.md | 132 +++++++++++++++++++ specification/link.md | 278 +++++++++++++++++++++++++++------------- specification/robot.md | 27 ++++ xsd/urdf.xsd | 14 +- 5 files changed, 368 insertions(+), 91 deletions(-) create mode 100644 specification/joint.md create mode 100644 specification/robot.md diff --git a/specification/README.md b/specification/README.md index d3e6ad25..303e81a0 100644 --- a/specification/README.md +++ b/specification/README.md @@ -12,7 +12,7 @@ The description of a robot consists of a set of [link elements](./link.md), and ~~~xml - + ... ... @@ -26,8 +26,14 @@ The description of a robot consists of a set of [link elements](./link.md), and You can see that the root element of the URDF format is a `` element. +## `` element + +The robot element describes all properties of a robot. For details on the root description format, check out the [robot elements](./robot.md) page. + ## `` element + For details on the link description format, check out the [link elements](./link.md) page. ## `` element + For details on the joint description format, check out the [joint elements](./joint.md) page. diff --git a/specification/joint.md b/specification/joint.md new file mode 100644 index 00000000..a6fd4fe7 --- /dev/null +++ b/specification/joint.md @@ -0,0 +1,132 @@ +# `` element + +The joint element describes the kinematics and dynamics of the joint and also specifies the [safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits) of the joint. + +![example-joint](./joint.png) + +## Attributes + +| attribute | type | use | default value | description | +| --------- | ----------- | -------- | ------------- | ------------------------------------------------------------------------------ | +| `name` | `string` | required | NA | Specifies a unique name of the join. | +| `type` | `JointType` | required | NA | Specifies the type of joint, see "Type: `JointType`" section for more details. | + +### Type: `JointType` + +where type can be one of the following: +- `revolute`: a hinge joint that rotates along the axis and has a limited range specified by the upper and lower limits. +- `continuous`: a continuous hinge joint that rotates around the axis and has no upper and lower limits. +- `prismatic`: a sliding joint that slides along the axis, and has a limited range specified by the upper and lower limits. +- `fixed`: this is not really a joint because it cannot move. All degrees of freedom are locked. This type of joint does not require the ``, ``, ``, `` or ``. +- `floating`: this joint allows motion for all 6 degrees of freedom. +- `planar`: this joint allows motion in a plane perpendicular to the axis. + +## Elements + +The joint element has following elements: + +| element | use | +| ------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| [``](#parent) | required | +| [``](#child) | required | +| [``](#origin) | optional: defaults to identity if not specified | +| [``](#axis) | optional: defaults to (1,0,0) | +| [``](#calibration) | optional | +| [``](#dynamics) | optional | +| [``](#limit) | required only for revolute and prismatic joint | +| [``](#mimic) | optional (New with ROS Groovy. See [issue](https://github.com/ros/robot_state_publisher/issues/1)) | +| [``](#safety_controller) | optional | + +### `` + +This is the transform from the parent link to the child link. The joint is located at the origin of the child link, as shown in the figure above. + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `xyz` | `string` | optional | zero vector | Represents the x, y, z offset. All positions are specified in metres. | +| `rpy` | `string` | optional | zero vector | Represents the rotation around fixed axis: first roll around x, then pitch around y and finally yaw around z. All angles are specified in radians. | + +### `` + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | --------------------------------------------------------------------------------- | +| `link` | `string` | required | NA | The name of the link that is the parent of this link in the robot tree structure. | + +### `` + +| attribute | type | use | default value | description | +| --------- | ------ | -------- | ------------- | -------------------------------------------- | +| `link` | `string` | required | NA | The name of the link that is the child link. | + +### `` + +The joint axis specified in the joint frame. This is the axis of rotation for revolute joints, the axis of translation for prismatic joints, and the surface normal for planar joints. The axis is specified in the joint frame of reference. Fixed and floating joints do not use the axis field. + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | --------------------------------------------------------------------------------- | +| `xyz` | `string` | required | NA | Represents the (x, y, z) components of a vector. The vector should be normalized. | + +### `` + +The reference positions of the joint, used to calibrate the absolute position of the joint. + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------- | +| `rising` | `double` | optional | ??? | When the joint moves in a positive direction, this reference position will trigger a rising edge. | +| `falling` | `double` | optional | ??? | When the joint moves in a positive direction, this reference position will trigger a falling edge. | + +### `` + +An element specifying physical properties of the joint. These values are used to specify modeling properties of the joint, particularly useful for simulation. + +| attribute | type | use | default value | description | +| ---------- | -------- | -------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `damping` | `double` | optional | defaults to 0 | The physical damping value of the joint (in newton-seconds per metre [N∙s/m] for prismatic joints, in newton-metre-seconds per radian [N∙m∙s/rad] for revolute joints). | +| `friction` | `double` | optional | defaults to 0 | The physical static friction value of the joint (in newtons [N] for prismatic joints, in newton-metres [N∙m] for revolute joints). | + +### `` + +(required only for revolute and prismatic joint) + +| attribute | type | use | default value | description | +| ---------- | -------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `effort` | `double` | required | NA | An attribute for enforcing the maximum joint effort (\|applied effort\| < \|effort\|). See safety limits. | +| `velocity` | `double` | required | NA | An attribute for enforcing the maximum joint velocity (in radians per second [rad/s] for revolute joints, in metres per second [m/s] for prismatic joints). [See safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits). | +| `lower` | `double` | optional | defaults to 0 | An attribute specifying the lower joint limit (in radians for revolute joints, in metres for prismatic joints). Omit if joint is continuous. | +| `upper` | `double` | optional | defaults to 0 | An attribute specifying the upper joint limit (in radians for revolute joints, in metres for prismatic joints). Omit if joint is continuous. | + +### `` + +(optional) (New with ROS Groovy. See issue) + +This tag is used to specify that the defined joint mimics another existing joint. The value of this joint can be computed as value = multiplier * other_joint_value + offset. + +| attribute | type | use | default value | description | +| ------------ | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `joint` | `string` | required | NA | This specifies the name of the joint to mimic. | +| `multiplier` | `double` | optional | defaults to 1 | Specifies the multiplicative factor in the formula above. | +| `offset` | `double` | optional | defaults to 0 | Specifies the offset to add in the formula above. Defaults to 0 (radians for revolute joints, meters for prismatic joints) | + +### `` + +| attribute | type | use | default value | description | +| ------------------ | -------- | -------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `k_velocity` | `double` | required | NA | An attribute specifying the relation between effort and velocity limits. See See safety limits for more details. | +| `soft_lower_limit` | `double` | optional | defaults to 0 | An attribute specifying the lower joint boundary where the safety controller starts limiting the position of the joint. This limit needs to be larger than the lower joint limit (see above). See [safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits) for more details. | +| `soft_upper_limit` | `double` | optional | defaults to 0 | An attribute specifying the upper joint boundary where the safety controller starts limiting the position of the joint. This limit needs to be smaller than the upper joint limit (see above). See [safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits) for more details. | +| `k_position` | `double` | optional | defaults to 0 | An attribute specifying the relation between position and velocity limits. See [safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits) for more details. | + +## Example + +```xml + + + + + + + + + + +``` \ No newline at end of file diff --git a/specification/link.md b/specification/link.md index 97bd17ed..8df5f94a 100644 --- a/specification/link.md +++ b/specification/link.md @@ -1,104 +1,174 @@ -# Link - -## `` element +# `` element The link element describes a rigid body with an inertia, visual features, and collision properties. -Here is an example of a link element: - -~~~xml - - - - - - - - - - - - - - - - - - - - - - - - -~~~ Inertial ## Attributes - * **`name`** *(required)* - * The name of the link itself. + +| `` attr | type | use | default value | description | +| ------------- | -------- | -------- | ------------- | ---------------------------- | +| `name` | `string` | required | NA | The name of the link itself. | ## Elements - * **``** *(optional: defaults to a zero mass and zero inertia if not specified)* - * The link’s mass, position of its center of mass, and its central inertia properties. - * **``** *(optional: defaults to identity if not specified)* - * This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. - * **`xyz`** *(optional: defaults to zero vector)* - * Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as **x L̂x + y L̂y + z L̂z**, where **L̂x, L̂y, L̂z** are link-frame L's orthogonal unit vectors. - * **`rpy`** *(optional: defaults to identity if not specified)* - * Represents the orientation of C's unit vectors **Ĉx, Ĉy, Ĉz** relative to link-frame L as a sequence of Euler rotations (r p y) in radians. Note: **Ĉx, Ĉy, Ĉz** do not need to be aligned with the link’s principal axes of inertia. - * **``** - * The mass of the link is represented by the **`value`** attribute of this element - * **``** - * This link's moments of inertia **ixx, iyy, izz** and products of inertia **ixy, ixz, iyz** about Co (the link’s center of mass) for the unit vectors **Ĉx, Ĉy, Ĉz** fixed in the center-of-mass frame C. Note: the orientation of **Ĉx, Ĉy, Ĉz** relative to **L̂x, L̂y, L̂z** is specified by the rpy values in the tag. The attributes **ixx, ixy, ixz, iyy, iyz, izz** for some primitive shapes are [here](https://en.wikipedia.org/wiki/ List_of_moments_of_inertia#List_of_3D_inertia_tensors). URDF assumes a negative product of inertia convention (for more info, see [these MathWorks docs](https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia. html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c) for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align **Ĉx, Ĉy, Ĉz** with principal inertia directions so that all the products of inertia are zero. - * **``** *(optional)* - * The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. - - * **name** *(optional)* - * Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. - - * **``** *(optional: defaults to identity if not specified)* - * The reference frame of the visual element with respect to the reference frame of the link. - * **`xyz`** *(optional: defaults to zero vector)* - * Represents the **x**, **y**, **z** offset. - * **rpy** *(optional: defaults to identity if not specified)* - * Represents the fixed axis roll, pitch and yaw angles in radians. - * **``** *(required)* - * The shape of the visual object. This can be *one* of the following: - * **``** - * **`size`** attribute contains the three side lengths of the box. The origin of the box is in its center. - * **``** - * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Cylinder Coordinates - * **``** - * Specify the **`radius`**. The origin of the sphere is in its center. - * **``** - * A trimesh element specified by a **`filename`**, and an optional **`scale`** that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with **`package:///`** to make the path to the mesh file relative to the package ``. - * **``** *(optional)* - * The material of the visual element. It is allowed to specify a material element outside of the 'link' object, in the top level 'robot' element. From within a link element you can then reference the material by name. - * **`name`** name of the material - * **``** *(optional)* - * **`rgba`** The color of a material specified by set of four numbers representing red/green/blue/alpha, each in the range of [0,1]. - * **``** *(optional)* - * The texture of a material is specified by a **`filename`** + +The link element has following child elements: + +| `` element | use | description | +| --------------------------- | -------------------------------------------------------------------- | ----------------------------------- | +| [``](#visual) | optional | The visual properties of the link. | +| [``](#collision) | optional | The collision properties of a link. | +| [``](#inertial) | optional: defaults to a zero mass and zero inertial if not specified | The visual properties of the link. | + +### `` + +The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. + +> [!NOTE] +> multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. + +| `` attr | type | use | default value | description | +| --------------- | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `name` | `string` | optional | none | Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. | + +Child elements of a `visual` element: +| `` element | use | description | +| -------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------ | +| [``](#visual-geometry) | required | The shape of the visual object. | +| [``](#visual-origin) | optional: defaults to identity if not specified | The reference frame of the visual element with respect to the reference frame of the link. | +| [``](#visual-material) | optional | The material of the visual element. | + +#### visual: `` + +The reference frame of the visual element with respect to the reference frame of the link. + +| `` attr | type | use | default value | description | +| --------------- | -------- | -------- | ------------------------------------- | ---------------------------------------------------------------- | +| `xyz` | `string` | optional | defaults to zero vector | Represents the **x**, **y**, **z** offset. | +| `rpy` | `string` | optional | defaults to identity if not specified | Represents the fixed axis roll, pitch and yaw angles in radians. | + +#### visual: `` + +The shape of the visual object. + +This element **may contain one** of the following elements: +| `` element | use | description | +| ---------------------------------- | -------- | --------------------------- | +| [``](#geometry-box) | optional | Defines a cubic mesh. | +| [``](#geometry-cylinder) | optional | Defines a cylindrical mesh. | +| [``](#geometry-sphere) | optional | Defines a spherical mesh. | +| [``](#geometry-mesh) | optional | Defines a custom mesh. | + +##### geometry: `` + +| `` attr | type | use | default value | description | +| ------------ | -------- | -------- | ------------- | ------------------------------------------------------------------------------------------------ | +| `size` | `string` | optional | zero vector | The three side lengths of the box in the form `"x y z"`. The origin of the box is in its center. | + +##### geometry: `` + +The origin of the cylinder is in its center. Cylinder Coordinates + +| `` attr | type | use | default value | description | +| ----------------- | -------- | -------- | ---------------- | ----------- | +| `radius` | `double` | required | Cylinder radius. | +| `length` | `double` | required | Cylinder lenght. | + +##### geometry: `` + +The origin of the sphere is in its center. + +| `` attr | type | use | default value | description | +| --------------- | -------- | -------- | ------------- | -------------- | +| `radius` | `double` | required | NA | Sphere radius. | + +##### geometry: `` + +A trimesh element specified by a **`filename`**, and an optional **`scale`** that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with **`package:///`** to make the path to the mesh file relative to the package ``. + +| `` attr | type | use | default value | description | +| ------------- | -------- | -------- | ------------- | ------------------------------------------------- | +| `filename` | `anyURI` | required | NA | Absolute path to the mesh file. | +| `scale` | `double` | optional | unit vector | Scale factor for the mesh in form `"x y z"` axis. | + +#### visual: `` + +The material of the visual element. It is allowed to specify a material element outside of the 'link' object, in the top level 'robot' element. From within a link element you can then reference the material by name. + +| `` attr | type | use | default value | description | +| ----------------- | -------- | -------- | ------------- | --------------------- | +| `name` | `string` | optional | none | Name of the material. | + +Child elements of a `material` element: +| `` element | use | description | +| -------------------------------- | -------- | ----------------------------------- | +| [``](#material-color) | optional | Defines the color of the material. | +| [``](#material-texture) | optional | Defines the texture of the material | + +##### material: `` + +| `` attr | type | use | default value | description | +| -------------- | -------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------ | +| `rgba` | `string` | optional | `"0 0 0 0"` | The color of a material specified by set of four numbers representing red/green/blue/alpha, each in the range of [0,1]. | + +##### material: `` + +| `` attr | type | use | default value | description | +| ---|---|----|----|----| +| `filename` | `anyURI` | required | NA | Path to rhe texture of a material. | + +### `` + +The link’s mass, position of its center of mass, and its central inertia properties. + +Child elements of a `` element: +| `` element | use | description | +| -------------------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------- | +| [``](#inertial-origin) | optional: defaults to identity if not specified | This pose (translation, rotation) of the link’s center of mass w.r.t. link-frame | +| [``](#inertial-mass) | required | The mass of the link is represented by the value attribute of this element | +| [``](#inertial-inertia) | ??? | interia matrix, see [``](#inertial-inertia) element for more details. | + + - * **``** *(optional)* - * The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the collision representation of the link. +#### inertial: `` + +(optional: defaults to identity if not specified)* + +This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. + +| `` attr | type | use | default value | description | +| ----------------- | -------- | -------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `xyz` | `string` | optional | defaults to zero vector | Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as **x L̂x + y L̂y + z L̂z**, where **L̂x, L̂y, L̂z** are link-frame L's orthogonal unit vectors. | +| `rpy` | `string` | optional | defaults to identity if not specified | Represents the orientation of C's unit vectors **Ĉx, Ĉy, Ĉz** relative to link-frame L as a sequence of Euler rotations (r p y) in radians. *Note*: **Ĉx, Ĉy, Ĉz** do not need to be aligned with the link’s principal axes of inertia. | + +#### inertial: `` + +The mass of the link is represented by the **`value`** attribute of this element. + +#### inertial: `` - * **`name`** *(optional)* - * Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. - * **``** *(optional: defaults to identity if not specified)* - * The reference frame of the collision element, relative to the reference frame of the link. - * **`xyz`** *(optional: defaults to zero vector)* - * Represents the **x**, **y**, **z** offset. - * **`rpy`** *(optional: defaults to identity if not specified)* - * Represents the fixed axis roll, pitch and yaw angles in radians. - * **``** - * See the geometry description in the above visual element. +This link's moments of inertia **ixx, iyy, izz** and products of inertia **ixy, ixz, iyz** about Co (the link’s center of mass) for the unit vectors **Ĉx, Ĉy, Ĉz** fixed in the center-of-mass frame C. Note: the orientation of **Ĉx, Ĉy, Ĉz** relative to **L̂x, L̂y, L̂z** is specified by the rpy values in the tag. The attributes **ixx, ixy, ixz, iyy, iyz, izz** for some primitive shapes are [here](https://en.wikipedia.org/wiki/List_of_moments_of_inertia#List_of_3D_inertia_tensors). URDF assumes a negative product of inertia convention (for more info, see [these MathWorks docs](https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia.html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c) for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align **Ĉx, Ĉy, Ĉz** with principal inertia directions so that all the products of inertia are zero. + + +### `` -# Recommended Mesh Resolution - * For collision checking using the [[moveit| ROS motion planning]] packages, as few faces per link as possible are recommended for the collision meshes that you put into the URDF (ideally less than 1000). If possible, approximating the meshes with other primitives is encouraged. +The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the collision representation of the link. -# Multiple Collision Bodies +| `` attr | type | use | default value | description | +| ------------------ | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `name` | `string` | optional | none | Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. | + +Child elements of a `` element: +| `` element | use | description | +| --------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | +| `` | optional: same as the [``](#visual-geometry) element in the [``](#visual) element. | The reference frame of the collision element, relative to the reference frame of the link. | +| `` | optional: same as the [``](#visual-geometry) element in the [``](#visual) element. | See the geometry description in the above [``](#visual) element. | + +## Recommended Mesh Resolution + +For collision checking using the [[moveit| ROS motion planning]] packages, as few faces per link as possible are recommended for the collision meshes that you put into the URDF (ideally less than 1000). If possible, approximating the meshes with other primitives is encouraged. + +## Multiple Collision Bodies It was decided that URDFs should not support multiple groups of collision bodies, even though there are sometimes applications for this. The URDF is intended to only represent the actual robot's properties, and not collisions used for external things like controller collision checking. In a URDF, the elements should be as accurate as possible to the real robot, and the elements should still be a close approximation, albeit with far fewer triangles in the meshes. @@ -132,3 +202,33 @@ If you do need coarser-grain, over sized collision geometries for things like co A URDF will ignore these custom elements like "collision_checking", and your particular program can parse the XML itself to get this information. +## Example + +Here is an example of a link element: + +~~~xml + + + + + + + + + + + + + + + + + + + + + + + + +~~~ \ No newline at end of file diff --git a/specification/robot.md b/specification/robot.md new file mode 100644 index 00000000..c4338de7 --- /dev/null +++ b/specification/robot.md @@ -0,0 +1,27 @@ +# `` element + +The root element in a robot description file must be a `` element, with all other elements must be encapsulated within. + +## Attributes + +| `` attr | type | use | default value | description | +| -------------- | ------ | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | string | required | NA | The master file must have a *name* attribute. The *name* attribute is optional in included files. If the attribute *name* is specified in an additional included file, it must have the same value as in the master file. | +| `version` | string | optional | "1.0" | version of the urdf specification in `.` format. | + +## Elements + +| `` element | description | +| ------------------------------------- | -------------------------------------------------------------------- | +| [``](./link.md) | defines a link with its own frame. | +| [``](./joint.md) | mandatory joint frame definition. | +| [``](./transmission.md) | (PR2 specific). | +| [``](./gazebo.md) | [Gazebo](http://wiki.ros.org/gazebo_ros_pkgs) simulation extensions. | + +## Example + +```xml + + + +``` diff --git a/xsd/urdf.xsd b/xsd/urdf.xsd index ccebfb26..f94ff12d 100644 --- a/xsd/urdf.xsd +++ b/xsd/urdf.xsd @@ -13,6 +13,18 @@ xmlns="http://www.ros.org" elementFormDefault="qualified"> + + + + + + + + + + + + @@ -293,7 +305,7 @@ type="mimic" minOccurs="0" maxOccurs="1" /> - + From 5e9b5b4eb2a3abc588904e0acd816ab2b5a1716c Mon Sep 17 00:00:00 2001 From: harleylara Date: Thu, 15 Feb 2024 14:04:49 +0100 Subject: [PATCH 14/23] add sensor and gazebo element --- specification/README.md | 14 +++-- specification/gazebo.md | 5 ++ specification/sensor.md | 111 ++++++++++++++++++++++++++++++++++++++++ xsd/urdf.xsd | 68 +++++++++++++++++++++++- 4 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 specification/gazebo.md create mode 100644 specification/sensor.md diff --git a/specification/README.md b/specification/README.md index 303e81a0..e192cb0f 100644 --- a/specification/README.md +++ b/specification/README.md @@ -28,12 +28,20 @@ You can see that the root element of the URDF format is a `` element. ## `` element -The robot element describes all properties of a robot. For details on the root description format, check out the [robot elements](./robot.md) page. +The `` element describes all properties of a robot. For details on the root description format, check out the [robot element](./robot.md) page. ## `` element -For details on the link description format, check out the [link elements](./link.md) page. +For details on the `` description format, check out the [link element](./link.md) page. ## `` element -For details on the joint description format, check out the [joint elements](./joint.md) page. +For details on the `` description format, check out the [joint element](./joint.md) page. + +## `` element + +For details on the `` description format, check out the [gazebo element](./gazebo.md) page. + +## `` element + +For details on the `` description format, check out the [sensor element](./sensor.md) page. \ No newline at end of file diff --git a/specification/gazebo.md b/specification/gazebo.md new file mode 100644 index 00000000..e8bdd9fe --- /dev/null +++ b/specification/gazebo.md @@ -0,0 +1,5 @@ +# `` element + +The gazebo element is an extension to the URDF robot description format, used for simulation purposes in the [Gazebo](https://gazebosim.org/) simulator. + +For full documentation of the Gazebo element, see [Using A URDF In Gazebo](http://gazebosim.org/tutorials?tut=ros_urdf&cat=connect_ros) (for Gazebo Classic) or [SDFormat extensions to URDF (the `` tag)](http://sdformat.org/tutorials?tut=sdformat_urdf_extensions&cat=specification&) (for new Gazebo). \ No newline at end of file diff --git a/specification/sensor.md b/specification/sensor.md new file mode 100644 index 00000000..71a3b920 --- /dev/null +++ b/specification/sensor.md @@ -0,0 +1,111 @@ +# `` element + +>[!WARNING] +> The sensor element has been implemented in the URDF Dom but has never really been used in application. This is a project that was dropped anyone is encouraged to pick it up and extend it to sensor hardware applications. Please contribute! + +The sensor element describes basic properties of a visual sensor (i.e. camera / ray sensor). + +Here is an example of a camera sensor element: +```xml + + + + + + + +``` + +And below is an example of a laser scan (ray) sensor element: + +```xml + + + + + + + + +``` + +## Attributes + +| attribute | type | use | default value | description | +| ------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| `name` | `string` | required | NA | The name of the sensor link | +| `update_rate` | `double` | optional | The frequency at which the sensor data is generated in `hz`. If left unspecified, the sensor will generate data every cycle. | + +## Elements + +| element | use | description | +| ---------------------- | -------- | -------------------------------------------------------------------------------------------- | +| [``](#origin)` | optional | This is the pose of the sensor optical frame, relative to the sensor parent reference frame. | +| [``](#camaera) | optional | Camera sensor definition. | +| [``](#ray) | optional | Laser sensor definition. | + +### `` + + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | ------------------------------------------------------- | +| `link` | `string` | required | NA | The name of the parent link this sensor is attached to. | + +### `` + +| attribute | type | use | default value | description | +| `xyz` | `string` | optional | zero vector | Represents the offset with respect to the parent frame. | +| `rpy` | `string` | optional | zero vector | Represents the fixed axis roll, pitch and yaw angles in radians. | + +### `` + +The `` element has following child elements: +| element | use | description | +| -------------------------- | -------- | ----------------------------- | +| [``](#camera-image) | required | Defines the image parameters. | + +#### camera: `` + +| attribute | type | use | default value | description | +| --------- | -------------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `width` | `unsigned int` | required | NA | Width of the camera in `pixels`. | +| `height` | `unsigned int` | required | NA | Height of the camera in `pixels`. | +| `format` | `string` | required | NA | Can be any of the strings defined in [image_encodings.h insdie sensor_msgs](https://code.ros.org/trac/ros-pkg/browser/stacks/common_msgs/trunk/sensor_msgs/include/sensor_msgs/image_encodings.h). | +| `hfov` | `double` | required | NA | Horizontal field of view of the camera in `radians`. | +| `near` | `double` | required | NA | Near clip distance of the camera in `meters`. | +| `far` | `double` | required | NA | Far clip distance of the camera in `meters`. This needs to be greater or equal to near clip. | + +### `` + +The `` element has following child elements: +| element | use | description | +| -------------- | -------- | ----------------------------------------------- | +| `` | optional | Defines the horizontal parameters of the laser. | +| `` | optional | Defines the vertical parameters of the laser. | + +#### ray: `` + +| attribute | type | use | default value | description | +| ------------ | -------------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `samples` | `unsigned int` | optional | 1 | The number of simulated rays to generate per complete laser sweep cycle. | +| `resolution` | `unsigned int` | optional | 1 | This number is multiplied by samples to determine the number of range data points returned. If resolution is less than one, range data is interpolated. If resolution is greater than one, range data is averaged. | +| `min_angle` | `double` | optional | Minimun angle in `radians`. | +| `max_angle` | `double` | optional | Maximum angle in `radian`. Must be greater or equal to `min_angle`. | + +#### ray: `` + +| attribute | type | use | default value | description | +| ------------ | -------------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `samples` | `unsigned int` | optional | 1 | The number of simulated rays to generate per complete laser sweep cycle. | +| `resolution` | `unsigned int` | optional | 1 | This number is multiplied by samples to determine the number of range data points returned. If resolution is less than one, range data is interpolated. If resolution is greater than one, range data is averaged. | +| `min_angle` | `double` | optional | Minimun angle in `radians`. | +| `max_angle` | `double` | optional | Maximum angle in `radian`. Must be greater or equal to `min_angle`. | + +## Recommended Camera or Ray Resolution + +In simulation, large sensors will slow down overall performance. Depending on update rates required, it is recommended to keep the camera or ray resolution and update rates as low as possible. + +## Proposal for New Type of Sensor + +TBD \ No newline at end of file diff --git a/xsd/urdf.xsd b/xsd/urdf.xsd index f94ff12d..130b64bd 100644 --- a/xsd/urdf.xsd +++ b/xsd/urdf.xsd @@ -154,7 +154,6 @@ - @@ -282,6 +281,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -326,6 +386,12 @@ type="transmission" minOccurs="0" maxOccurs="unbounded" /> + + + + From 134b839c1b4ded1aad3ba59df0c6623ac20d0691 Mon Sep 17 00:00:00 2001 From: Nick Walker Date: Mon, 28 Aug 2023 13:55:41 -0700 Subject: [PATCH 15/23] Support checking a URDF given on stdin (#171) Makes it easier to pipe results from xacro, and matches urdfdom_py's behavior Closes #170 Signed-off-by: harleylara --- urdf_parser/src/check_urdf.cpp | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/urdf_parser/src/check_urdf.cpp b/urdf_parser/src/check_urdf.cpp index f9888d46..42e0fdac 100644 --- a/urdf_parser/src/check_urdf.cpp +++ b/urdf_parser/src/check_urdf.cpp @@ -66,19 +66,27 @@ void printTree(LinkConstSharedPtr link,int level = 0) int main(int argc, char** argv) { if (argc < 2){ - std::cerr << "Expect URDF xml file to parse" << std::endl; + std::cerr << "Expect URDF xml file to parse. Use - for stdin" << std::endl; return -1; } std::string xml_string; - std::fstream xml_file(argv[1], std::fstream::in); - while ( xml_file.good() ) + if (strcmp(argv[1], "-") == 0) { - std::string line; - std::getline( xml_file, line); - xml_string += (line + "\n"); + // Read from stdin + for (std::string line; std::getline(std::cin, line);) + { + xml_string += (line + "\n"); + } + } else + { + std::ifstream xml_file(argv[1]); + for (std::string line; std::getline(xml_file, line);) + { + xml_string += (line + "\n"); + } + xml_file.close(); } - xml_file.close(); ModelInterfaceSharedPtr robot = parseURDF(xml_string); if (!robot){ From bde3e64f9b1422484a72aeb8bdacd6ee9c1b34fa Mon Sep 17 00:00:00 2001 From: Felix F Xu <84662027+felixf4xu@users.noreply.github.com> Date: Thu, 7 Dec 2023 03:57:24 +0800 Subject: [PATCH 16/23] Upgrade from tinyxml to tinyxml2 (#186) * upgrade from tinyxml to tinyxml2 * Remove 'using tinyxml2' * Update github actions. * Add in FindTinyXML2 for systems that don't have it. * Make sure that tinyxml2::tinyxml2 is available in downstream packages * Update urdfdom-config.cmake.in * Replace InsertNewChildElement with GetDocument()->NewElement. The former doesn't exist in older TinyXML2, and is just a convenience function anyway. * Fix generation of CMake config files. Use the provided CMake primitives for this, which should make it work in all situations. * Install the FindTinyXML2.cmake file. This is so downstream projects can always find it. * Backup and restore the CMAKE_MODULE_PATH. So we don't permanently manipulate it. Signed-off-by: Chris Lalancette Co-authored-by: Silvio Traversaro Signed-off-by: harleylara --- .github/workflows/ros1.yaml | 10 +- .github/workflows/ros2.yaml | 14 +- .github/workflows/{system.yml => system.yaml} | 6 +- CMakeLists.txt | 44 +++-- cmake/FindTinyXML.cmake | 74 ------- cmake/FindTinyXML2.cmake | 78 ++++++++ cmake/urdfdom-config.cmake.in | 10 +- package.xml | 8 +- urdf_parser/CMakeLists.txt | 5 +- urdf_parser/include/urdf_parser/urdf_parser.h | 24 +-- urdf_parser/src/joint.cpp | 124 ++++++------ urdf_parser/src/link.cpp | 180 +++++++++--------- urdf_parser/src/model.cpp | 55 +++--- urdf_parser/src/pose.cpp | 22 +-- urdf_parser/src/twist.cpp | 15 +- urdf_parser/src/urdf_model_state.cpp | 18 +- urdf_parser/src/urdf_sensor.cpp | 38 ++-- urdf_parser/src/world.cpp | 18 +- 18 files changed, 377 insertions(+), 366 deletions(-) rename .github/workflows/{system.yml => system.yaml} (92%) delete mode 100644 cmake/FindTinyXML.cmake create mode 100644 cmake/FindTinyXML2.cmake diff --git a/.github/workflows/ros1.yaml b/.github/workflows/ros1.yaml index adf18706..133baa9d 100644 --- a/.github/workflows/ros1.yaml +++ b/.github/workflows/ros1.yaml @@ -8,12 +8,12 @@ on: jobs: build_ros1: name: ROS1 CI - runs-on: ubuntu-18.04 + runs-on: ubuntu-20.04 steps: - - uses: ros-tooling/setup-ros@v0.2 + - uses: ros-tooling/setup-ros@v0.7 with: - required-ros-distributions: melodic - - uses: ros-tooling/action-ros-ci@v0.2 + required-ros-distributions: noetic + - uses: ros-tooling/action-ros-ci@v0.3 with: package-name: urdfdom - target-ros1-distro: melodic + target-ros1-distro: noetic diff --git a/.github/workflows/ros2.yaml b/.github/workflows/ros2.yaml index 0d7b3f07..7e1adbef 100644 --- a/.github/workflows/ros2.yaml +++ b/.github/workflows/ros2.yaml @@ -1,5 +1,5 @@ --- -name: urdfdom ROS2 CI +name: urdfdom ROS 2 CI on: push: @@ -8,13 +8,13 @@ on: jobs: build_ros2: - name: ROS2 CI - runs-on: ubuntu-20.04 + name: ROS 2 CI + runs-on: ubuntu-22.04 steps: - - uses: ros-tooling/setup-ros@v0.2 + - uses: ros-tooling/setup-ros@v0.7 with: - required-ros-distributions: galactic - - uses: ros-tooling/action-ros-ci@v0.2 + required-ros-distributions: rolling + - uses: ros-tooling/action-ros-ci@v0.3 with: package-name: urdfdom - target-ros2-distro: galactic + target-ros2-distro: rolling diff --git a/.github/workflows/system.yml b/.github/workflows/system.yaml similarity index 92% rename from .github/workflows/system.yml rename to .github/workflows/system.yaml index c255647a..1bd6dce9 100644 --- a/.github/workflows/system.yml +++ b/.github/workflows/system.yaml @@ -30,8 +30,8 @@ jobs: cxx: "g++", } - { - name: "Ubuntu Bionic GCC", - os: ubuntu-18.04, + name: "Ubuntu Focal GCC", + os: ubuntu-20.04, build_type: "Release", cc: "gcc", cxx: "g++", @@ -44,7 +44,7 @@ jobs: run: | sudo apt-get -qq update sudo apt-get -qq upgrade -y - sudo apt-get -qq install -y build-essential cmake libconsole-bridge-dev liburdfdom-headers-dev libtinyxml-dev + sudo apt-get -qq install -y build-essential cmake libconsole-bridge-dev liburdfdom-headers-dev libtinyxml2-dev cmake --version gcc --version diff --git a/CMakeLists.txt b/CMakeLists.txt index 04d38d8e..13ba51eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,16 +45,9 @@ endif (MSVC OR MSVC90 OR MSVC10) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -find_package(tinyxml_vendor QUIET) -find_package(TinyXML) -# bionic has not cmake module, workaround -if (NOT TinyXML_FOUND AND UNIX) - include(FindPkgConfig) - pkg_check_modules (TinyXML tinyxml) -else() - # Make it fail in platforms without pkgconfig - find_package(TinyXML REQUIRED) # bionic has not cmake module -endif() +find_package(tinyxml2_vendor QUIET) +find_package(TinyXML2 REQUIRED) + find_package(urdfdom_headers 1.0 REQUIRED) find_package(console_bridge_vendor QUIET) # Provides console_bridge 0.4.0 on platforms without it. find_package(console_bridge REQUIRED) @@ -78,17 +71,35 @@ add_subdirectory(urdf_parser) set(PKG_NAME ${PROJECT_NAME}) set(PKG_LIBRARIES urdfdom_sensor urdfdom_model_state urdfdom_model urdfdom_world) -set(PKG_DEPENDS urdfdom_headers console_bridge) +set(PKG_DEPENDS TinyXML2 urdfdom_headers console_bridge) set(PKG_EXPORTS urdfdom) -set(cmake_conf_file "cmake/urdfdom-config.cmake") -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${cmake_conf_file}.in" "${CMAKE_BINARY_DIR}/${cmake_conf_file}" @ONLY) +set(cmake_conf_file "cmake/urdfdom-config") +include(CMakePackageConfigHelpers) +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/${cmake_conf_file}Version.cmake" + VERSION ${URDF_VERSION} + COMPATIBILITY SameMajorVersion +) +configure_package_config_file("${cmake_conf_file}.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/${cmake_conf_file}.cmake" + INSTALL_DESTINATION ${CMAKE_CONFIG_INSTALL_DIR} +) +install(FILES + "${CMAKE_CURRENT_BINARY_DIR}/${cmake_conf_file}.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/${cmake_conf_file}Version.cmake" + DESTINATION ${CMAKE_CONFIG_INSTALL_DIR} +) + +# Some operating systems (like Ubuntu 22.04) do not provide a default +# way to find TinyXML2. For that reason, this package provides it +install(FILES cmake/FindTinyXML2.cmake + DESTINATION ${CMAKE_CONFIG_INSTALL_DIR}) + install(FILES package.xml DESTINATION share/${PROJECT_NAME}) -install(FILES ${CMAKE_BINARY_DIR}/${cmake_conf_file} - DESTINATION ${CMAKE_CONFIG_INSTALL_DIR} COMPONENT cmake) # Make the package config file set(PKG_DESC "Unified Robot Description Format") -set(PKG_DEPENDS "urdfdom_headers console_bridge") # make the list separated by spaces instead of ; +set(PKG_DEPENDS "tinyxml2 urdfdom_headers console_bridge") # make the list separated by spaces instead of ; set(PKG_URDF_LIBS "-lurdfdom_sensor -lurdfdom_model_state -lurdfdom_model -lurdfdom_world") set(pkg_conf_file "cmake/pkgconfig/urdfdom.pc") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${pkg_conf_file}.in" "${CMAKE_BINARY_DIR}/${pkg_conf_file}" @ONLY) @@ -96,7 +107,6 @@ install(FILES ${CMAKE_BINARY_DIR}/${pkg_conf_file} DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig/ COMPONENT pkgconfig) - # Add uninstall target # Ref: http://www.cmake.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F configure_file( diff --git a/cmake/FindTinyXML.cmake b/cmake/FindTinyXML.cmake deleted file mode 100644 index aabb323d..00000000 --- a/cmake/FindTinyXML.cmake +++ /dev/null @@ -1,74 +0,0 @@ -################################################################################################## -# -# CMake script for finding TinyXML. -# -# Input variables: -# -# - TinyXML_ROOT_DIR (optional): When specified, header files and libraries will be searched for in -# ${TinyXML_ROOT_DIR}/include -# ${TinyXML_ROOT_DIR}/libs -# respectively, and the default CMake search order will be ignored. When unspecified, the default -# CMake search order is used. -# This variable can be specified either as a CMake or environment variable. If both are set, -# preference is given to the CMake variable. -# Use this variable for finding packages installed in a nonstandard location, or for enforcing -# that one of multiple package installations is picked up. -# -# -# Cache variables (not intended to be used in CMakeLists.txt files) -# -# - TinyXML_INCLUDE_DIR: Absolute path to package headers. -# - TinyXML_LIBRARY: Absolute path to library. -# -# -# Output variables: -# -# - TinyXML_FOUND: Boolean that indicates if the package was found -# - TinyXML_INCLUDE_DIRS: Paths to the necessary header files -# - TinyXML_LIBRARIES: Package libraries -# -# -# Example usage: -# -# find_package(TinyXML) -# if(NOT TinyXML_FOUND) -# # Error handling -# endif() -# ... -# include_directories(${TinyXML_INCLUDE_DIRS} ...) -# ... -# target_link_libraries(my_target ${TinyXML_LIBRARIES}) -# -################################################################################################## - -# Get package location hint from environment variable (if any) -if(NOT TinyXML_ROOT_DIR AND DEFINED ENV{TinyXML_ROOT_DIR}) - set(TinyXML_ROOT_DIR "$ENV{TinyXML_ROOT_DIR}" CACHE PATH - "TinyXML base directory location (optional, used for nonstandard installation paths)") -endif() - -# Search path for nonstandard package locations -if(TinyXML_ROOT_DIR) - set(TinyXML_INCLUDE_PATH PATHS "${TinyXML_ROOT_DIR}/include" NO_DEFAULT_PATH) - set(TinyXML_LIBRARY_PATH PATHS "${TinyXML_ROOT_DIR}/lib" NO_DEFAULT_PATH) -endif() - -# Find headers and libraries -find_path(TinyXML_INCLUDE_DIR NAMES tinyxml.h PATH_SUFFIXES "tinyxml" ${TinyXML_INCLUDE_PATH}) -find_library(TinyXML_LIBRARY NAMES tinyxml PATH_SUFFIXES "tinyxml" ${TinyXML_LIBRARY_PATH}) - -mark_as_advanced(TinyXML_INCLUDE_DIR - TinyXML_LIBRARY) - -# Output variables generation -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(TinyXML DEFAULT_MSG TinyXML_LIBRARY - TinyXML_INCLUDE_DIR) - -set(TinyXML_FOUND ${TINYXML_FOUND}) # Enforce case-correctness: Set appropriately cased variable... -unset(TINYXML_FOUND) # ...and unset uppercase variable generated by find_package_handle_standard_args - -if(TinyXML_FOUND) - set(TinyXML_INCLUDE_DIRS ${TinyXML_INCLUDE_DIR}) - set(TinyXML_LIBRARIES ${TinyXML_LIBRARY}) -endif() diff --git a/cmake/FindTinyXML2.cmake b/cmake/FindTinyXML2.cmake new file mode 100644 index 00000000..7811863c --- /dev/null +++ b/cmake/FindTinyXML2.cmake @@ -0,0 +1,78 @@ +# TinyXML2_FOUND +# TinyXML2_INCLUDE_DIRS +# TinyXML2_LIBRARIES + +# try to find the CMake config file for TinyXML2 first +if(NOT TinyXML2_FOUND) + find_package(TinyXML2 CONFIG QUIET) +endif() +if(TinyXML2_FOUND) + message(STATUS "Found TinyXML2 via Config file: ${TinyXML2_DIR}") + if(NOT TINYXML2_LIBRARY) + # in this case, we're probably using TinyXML2 version 5.0.0 or greater + # in which case tinyxml2 is an exported target and we should use that + if(TARGET tinyxml2) + set(TINYXML2_LIBRARY tinyxml2) + elseif(TARGET tinyxml2::tinyxml2) + set(TINYXML2_LIBRARY tinyxml2::tinyxml2) + elseif(TinyXML2_FIND_REQUIRED) + message(FATAL_ERROR "Unable to determine target for TinyXML2") + endif() + list(APPEND TinyXML2_TARGETS ${TINYXML2_LIBRARY}) + else() + # Only perform that logic once + if(NOT TARGET tinyxml2::tinyxml2) + # TINYXML2_LIBRARY is composed of debug;;optimized; + # we have to extract the appropriate component based on the current configuration. + list(LENGTH TINYXML2_LIBRARY TINYXML_LIBRARY_LIST_LENGTH) + if(NOT ${TINYXML_LIBRARY_LIST_LENGTH} EQUAL 4) + message(FATAL_ERROR "Unable to extract the library file path from ${TINYXML2_LIBRARY}") + endif() + if(CMAKE_BUILD_TYPE MATCHES DEBUG) + list(GET TINYXML2_LIBRARY 0 ASSERT_DEBUG) + if(NOT ${ASSERT_DEBUG} STREQUAL "debug") + message(FATAL_ERROR "could not parse debug library path from ${TINYXML2_LIBRARY}") + endif() + list(GET TINYXML2_LIBRARY 1 TINYXML2_LIBRARY_PATH) + else() + list(GET TINYXML2_LIBRARY 2 ASSERT_OPTIMIZED) + if(NOT ${ASSERT_OPTIMIZED} STREQUAL "optimized") + message(FATAL_ERROR "could not parse library path from ${TINYXML2_LIBRARY}") + endif() + list(GET TINYXML2_LIBRARY 3 TINYXML2_LIBRARY_PATH) + endif() + if(NOT EXISTS ${TINYXML2_LIBRARY_PATH}) + message(FATAL_ERROR "library file path ${TINYXML2_LIBRARY_PATH} does not exist") + endif() + + add_library(tinyxml2::tinyxml2 UNKNOWN IMPORTED) + set_property(TARGET tinyxml2::tinyxml2 PROPERTY IMPORTED_LOCATION ${TINYXML2_LIBRARY_PATH}) + set_property(TARGET tinyxml2::tinyxml2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${TINYXML2_INCLUDE_DIR}) + list(APPEND TinyXML2_TARGETS tinyxml2::tinyxml2) + endif() + endif() +else() + find_path(TINYXML2_INCLUDE_DIR NAMES tinyxml2.h) + + find_library(TINYXML2_LIBRARY tinyxml2) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(TinyXML2 DEFAULT_MSG TINYXML2_LIBRARY TINYXML2_INCLUDE_DIR) + + mark_as_advanced(TINYXML2_INCLUDE_DIR TINYXML2_LIBRARY) + + if(NOT TARGET tinyxml2::tinyxml2) + add_library(tinyxml2::tinyxml2 UNKNOWN IMPORTED) + set_property(TARGET tinyxml2::tinyxml2 PROPERTY IMPORTED_LOCATION ${TINYXML2_LIBRARY}) + set_property(TARGET tinyxml2::tinyxml2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${TINYXML2_INCLUDE_DIR}) + list(APPEND TinyXML2_TARGETS tinyxml2::tinyxml2) + endif() +endif() + +# Set mixed case INCLUDE_DIRS and LIBRARY variables from upper case ones. +if(NOT TinyXML2_INCLUDE_DIRS) + set(TinyXML2_INCLUDE_DIRS ${TINYXML2_INCLUDE_DIR}) +endif() +if(NOT TinyXML2_LIBRARIES) + set(TinyXML2_LIBRARIES ${TINYXML2_LIBRARY}) +endif() diff --git a/cmake/urdfdom-config.cmake.in b/cmake/urdfdom-config.cmake.in index d8eb93d4..ee84f41d 100644 --- a/cmake/urdfdom-config.cmake.in +++ b/cmake/urdfdom-config.cmake.in @@ -1,9 +1,14 @@ +@PACKAGE_INIT@ + if (@PKG_NAME@_CONFIG_INCLUDED) return() endif() set(@PKG_NAME@_CONFIG_INCLUDED TRUE) -set(@PKG_NAME@_INCLUDE_DIRS "${@PROJECT_NAME@_DIR}/@RELATIVE_PATH_CMAKE_DIR_TO_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@" "@TinyXML_INCLUDE_DIRS@") +set(CMAKE_MODULE_PATH_BACKUP_URDFDOM ${CMAKE_MODULE_PATH}) +list(APPEND CMAKE_MODULE_PATH "${@PROJECT_NAME@_DIR}") + +set(@PKG_NAME@_INCLUDE_DIRS "${@PROJECT_NAME@_DIR}/@RELATIVE_PATH_CMAKE_DIR_TO_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@") foreach(lib @PKG_LIBRARIES@) set(onelib "${lib}-NOTFOUND") @@ -30,6 +35,7 @@ foreach(lib @PKG_LIBRARIES@) list(APPEND @PKG_NAME@_TARGETS @PROJECT_NAME@::${lib}) endforeach() +find_package(tinyxml2_vendor QUIET) foreach(dep @PKG_DEPENDS@) if(NOT ${dep}_FOUND) find_package(${dep}) @@ -41,3 +47,5 @@ endforeach() foreach(exp @PKG_EXPORTS@) include(${@PROJECT_NAME@_DIR}/${exp}Export.cmake) endforeach() + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH_BACKUP_URDFDOM}) diff --git a/package.xml b/package.xml index 3ac1d6ff..e34b5333 100644 --- a/package.xml +++ b/package.xml @@ -17,16 +17,16 @@ console_bridge_vendor libconsole-bridge-dev - tinyxml - tinyxml_vendor + tinyxml2 + tinyxml2_vendor urdfdom_headers cmake console_bridge_vendor libconsole-bridge-dev - tinyxml - tinyxml_vendor + tinyxml2 + tinyxml2_vendor urdfdom_headers python3 diff --git a/urdf_parser/CMakeLists.txt b/urdf_parser/CMakeLists.txt index ac7c0792..dba9ddab 100644 --- a/urdf_parser/CMakeLists.txt +++ b/urdf_parser/CMakeLists.txt @@ -5,8 +5,6 @@ macro(add_urdfdom_library) add_library(${add_urdfdom_library_LIBNAME} SHARED ${add_urdfdom_library_SOURCES}) - target_include_directories(${add_urdfdom_library_LIBNAME} SYSTEM PUBLIC - ${TinyXML_INCLUDE_DIRS}) target_include_directories(${add_urdfdom_library_LIBNAME} PUBLIC "$" "$") @@ -14,7 +12,8 @@ macro(add_urdfdom_library) ${add_urdfdom_library_LINK} ${console_bridge_link_libs} ${urdfdom_headers_link_libs} - ${TinyXML_LIBRARIES}) + tinyxml2::tinyxml2 + ) if(NOT CMAKE_CXX_STANDARD) target_compile_features(${add_urdfdom_library_LIBNAME} PUBLIC cxx_std_14) endif() diff --git a/urdf_parser/include/urdf_parser/urdf_parser.h b/urdf_parser/include/urdf_parser/urdf_parser.h index a293379e..b7419483 100644 --- a/urdf_parser/include/urdf_parser/urdf_parser.h +++ b/urdf_parser/include/urdf_parser/urdf_parser.h @@ -1,13 +1,13 @@ /********************************************************************* * Software License Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -41,7 +41,7 @@ #include #include -#include +#include #include #include #include @@ -143,13 +143,13 @@ namespace urdf{ URDFDOM_DLLAPI ModelInterfaceSharedPtr parseURDF(const std::string &xml_string); URDFDOM_DLLAPI ModelInterfaceSharedPtr parseURDFFile(const std::string &path); - URDFDOM_DLLAPI TiXmlDocument* exportURDF(ModelInterfaceSharedPtr &model); - URDFDOM_DLLAPI TiXmlDocument* exportURDF(const ModelInterface &model); - URDFDOM_DLLAPI bool parsePose(Pose&, TiXmlElement*); - URDFDOM_DLLAPI bool parseCamera(Camera&, TiXmlElement*); - URDFDOM_DLLAPI bool parseRay(Ray&, TiXmlElement*); - URDFDOM_DLLAPI bool parseSensor(Sensor&, TiXmlElement*); - URDFDOM_DLLAPI bool parseModelState(ModelState&, TiXmlElement*); + URDFDOM_DLLAPI tinyxml2::XMLDocument* exportURDF(ModelInterfaceSharedPtr &model); + URDFDOM_DLLAPI tinyxml2::XMLDocument* exportURDF(const ModelInterface &model); + URDFDOM_DLLAPI bool parsePose(Pose&, tinyxml2::XMLElement*); + URDFDOM_DLLAPI bool parseCamera(Camera&, tinyxml2::XMLElement*); + URDFDOM_DLLAPI bool parseRay(Ray&, tinyxml2::XMLElement*); + URDFDOM_DLLAPI bool parseSensor(Sensor&, tinyxml2::XMLElement*); + URDFDOM_DLLAPI bool parseModelState(ModelState&, tinyxml2::XMLElement*); } #endif diff --git a/urdf_parser/src/joint.cpp b/urdf_parser/src/joint.cpp index d12dcb7c..7668350f 100644 --- a/urdf_parser/src/joint.cpp +++ b/urdf_parser/src/joint.cpp @@ -1,13 +1,13 @@ /********************************************************************* * Software Ligcense Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -40,14 +40,14 @@ #include #include #include -#include +#include #include namespace urdf{ -bool parsePose(Pose &pose, TiXmlElement* xml); +bool parsePose(Pose &pose, tinyxml2::XMLElement* xml); -bool parseJointDynamics(JointDynamics &jd, TiXmlElement* config) +bool parseJointDynamics(JointDynamics &jd, tinyxml2::XMLElement* config) { jd.clear(); @@ -94,7 +94,7 @@ bool parseJointDynamics(JointDynamics &jd, TiXmlElement* config) } } -bool parseJointLimits(JointLimits &jl, TiXmlElement* config) +bool parseJointLimits(JointLimits &jl, tinyxml2::XMLElement* config) { jl.clear(); @@ -165,7 +165,7 @@ bool parseJointLimits(JointLimits &jl, TiXmlElement* config) return true; } -bool parseJointSafety(JointSafety &js, TiXmlElement* config) +bool parseJointSafety(JointSafety &js, tinyxml2::XMLElement* config) { js.clear(); @@ -239,7 +239,7 @@ bool parseJointSafety(JointSafety &js, TiXmlElement* config) return true; } -bool parseJointCalibration(JointCalibration &jc, TiXmlElement* config) +bool parseJointCalibration(JointCalibration &jc, tinyxml2::XMLElement* config) { jc.clear(); @@ -280,7 +280,7 @@ bool parseJointCalibration(JointCalibration &jc, TiXmlElement* config) return true; } -bool parseJointMimic(JointMimic &jm, TiXmlElement* config) +bool parseJointMimic(JointMimic &jm, tinyxml2::XMLElement* config) { jm.clear(); @@ -294,14 +294,14 @@ bool parseJointMimic(JointMimic &jm, TiXmlElement* config) } else jm.joint_name = joint_name_str; - + // Get mimic multiplier const char* multiplier_str = config->Attribute("multiplier"); if (multiplier_str == NULL) { CONSOLE_BRIDGE_logDebug("urdfdom.joint_mimic: no multiplier, using default value of 1"); - jm.multiplier = 1; + jm.multiplier = 1; } else { @@ -313,7 +313,7 @@ bool parseJointMimic(JointMimic &jm, TiXmlElement* config) } } - + // Get mimic offset const char* offset_str = config->Attribute("offset"); if (offset_str == NULL) @@ -334,7 +334,7 @@ bool parseJointMimic(JointMimic &jm, TiXmlElement* config) return true; } -bool parseJoint(Joint &joint, TiXmlElement* config) +bool parseJoint(Joint &joint, tinyxml2::XMLElement* config) { joint.clear(); @@ -348,7 +348,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) joint.name = name; // Get transform from Parent Link to Joint Frame - TiXmlElement *origin_xml = config->FirstChildElement("origin"); + tinyxml2::XMLElement *origin_xml = config->FirstChildElement("origin"); if (!origin_xml) { CONSOLE_BRIDGE_logDebug("urdfdom: Joint [%s] missing origin tag under parent describing transform from Parent Link to Joint Frame, (using Identity transform).", joint.name.c_str()); @@ -365,7 +365,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) } // Get Parent Link - TiXmlElement *parent_xml = config->FirstChildElement("parent"); + tinyxml2::XMLElement *parent_xml = config->FirstChildElement("parent"); if (parent_xml) { const char *pname = parent_xml->Attribute("link"); @@ -380,7 +380,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) } // Get Child Link - TiXmlElement *child_xml = config->FirstChildElement("child"); + tinyxml2::XMLElement *child_xml = config->FirstChildElement("child"); if (child_xml) { const char *pname = child_xml->Attribute("link"); @@ -401,7 +401,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) CONSOLE_BRIDGE_logError("joint [%s] has no type, check to see if it's a reference.", joint.name.c_str()); return false; } - + std::string type_str = type_char; if (type_str == "planar") joint.type = Joint::PLANAR; @@ -425,7 +425,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) if (joint.type != Joint::FLOATING && joint.type != Joint::FIXED) { // axis - TiXmlElement *axis_xml = config->FirstChildElement("axis"); + tinyxml2::XMLElement *axis_xml = config->FirstChildElement("axis"); if (!axis_xml){ CONSOLE_BRIDGE_logDebug("urdfdom: no axis element for Joint link [%s], defaulting to (1,0,0) axis", joint.name.c_str()); joint.axis = Vector3(1.0, 0.0, 0.0); @@ -445,7 +445,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) } // Get limit - TiXmlElement *limit_xml = config->FirstChildElement("limit"); + tinyxml2::XMLElement *limit_xml = config->FirstChildElement("limit"); if (limit_xml) { joint.limits.reset(new JointLimits()); @@ -463,12 +463,12 @@ bool parseJoint(Joint &joint, TiXmlElement* config) } else if (joint.type == Joint::PRISMATIC) { - CONSOLE_BRIDGE_logError("Joint [%s] is of type PRISMATIC without limits", joint.name.c_str()); + CONSOLE_BRIDGE_logError("Joint [%s] is of type PRISMATIC without limits", joint.name.c_str()); return false; } // Get safety - TiXmlElement *safety_xml = config->FirstChildElement("safety_controller"); + tinyxml2::XMLElement *safety_xml = config->FirstChildElement("safety_controller"); if (safety_xml) { joint.safety.reset(new JointSafety()); @@ -481,7 +481,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) } // Get calibration - TiXmlElement *calibration_xml = config->FirstChildElement("calibration"); + tinyxml2::XMLElement *calibration_xml = config->FirstChildElement("calibration"); if (calibration_xml) { joint.calibration.reset(new JointCalibration()); @@ -494,7 +494,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) } // Get Joint Mimic - TiXmlElement *mimic_xml = config->FirstChildElement("mimic"); + tinyxml2::XMLElement *mimic_xml = config->FirstChildElement("mimic"); if (mimic_xml) { joint.mimic.reset(new JointMimic()); @@ -507,7 +507,7 @@ bool parseJoint(Joint &joint, TiXmlElement* config) } // Get Dynamics - TiXmlElement *prop_xml = config->FirstChildElement("dynamics"); + tinyxml2::XMLElement *prop_xml = config->FirstChildElement("dynamics"); if (prop_xml) { joint.dynamics.reset(new JointDynamics()); @@ -524,71 +524,71 @@ bool parseJoint(Joint &joint, TiXmlElement* config) /* exports */ -bool exportPose(Pose &pose, TiXmlElement* xml); +bool exportPose(Pose &pose, tinyxml2::XMLElement* xml); -bool exportJointDynamics(JointDynamics &jd, TiXmlElement* xml) +bool exportJointDynamics(JointDynamics &jd, tinyxml2::XMLElement* xml) { - TiXmlElement *dynamics_xml = new TiXmlElement("dynamics"); - dynamics_xml->SetAttribute("damping", urdf_export_helpers::values2str(jd.damping) ); - dynamics_xml->SetAttribute("friction", urdf_export_helpers::values2str(jd.friction) ); + tinyxml2::XMLElement *dynamics_xml = xml->GetDocument()->NewElement("dynamics"); + dynamics_xml->SetAttribute("damping", urdf_export_helpers::values2str(jd.damping).c_str() ); + dynamics_xml->SetAttribute("friction", urdf_export_helpers::values2str(jd.friction).c_str() ); xml->LinkEndChild(dynamics_xml); return true; } -bool exportJointLimits(JointLimits &jl, TiXmlElement* xml) +bool exportJointLimits(JointLimits &jl, tinyxml2::XMLElement* xml) { - TiXmlElement *limit_xml = new TiXmlElement("limit"); - limit_xml->SetAttribute("effort", urdf_export_helpers::values2str(jl.effort) ); - limit_xml->SetAttribute("velocity", urdf_export_helpers::values2str(jl.velocity) ); - limit_xml->SetAttribute("lower", urdf_export_helpers::values2str(jl.lower) ); - limit_xml->SetAttribute("upper", urdf_export_helpers::values2str(jl.upper) ); + tinyxml2::XMLElement *limit_xml = xml->GetDocument()->NewElement("limit"); + limit_xml->SetAttribute("effort", urdf_export_helpers::values2str(jl.effort).c_str()); + limit_xml->SetAttribute("velocity", urdf_export_helpers::values2str(jl.velocity).c_str()); + limit_xml->SetAttribute("lower", urdf_export_helpers::values2str(jl.lower).c_str()); + limit_xml->SetAttribute("upper", urdf_export_helpers::values2str(jl.upper).c_str()); xml->LinkEndChild(limit_xml); return true; } -bool exportJointSafety(JointSafety &js, TiXmlElement* xml) +bool exportJointSafety(JointSafety &js, tinyxml2::XMLElement* xml) { - TiXmlElement *safety_xml = new TiXmlElement("safety_controller"); - safety_xml->SetAttribute("k_position", urdf_export_helpers::values2str(js.k_position) ); - safety_xml->SetAttribute("k_velocity", urdf_export_helpers::values2str(js.k_velocity) ); - safety_xml->SetAttribute("soft_lower_limit", urdf_export_helpers::values2str(js.soft_lower_limit) ); - safety_xml->SetAttribute("soft_upper_limit", urdf_export_helpers::values2str(js.soft_upper_limit) ); + tinyxml2::XMLElement *safety_xml = xml->GetDocument()->NewElement("safety_controller"); + safety_xml->SetAttribute("k_position", urdf_export_helpers::values2str(js.k_position).c_str()); + safety_xml->SetAttribute("k_velocity", urdf_export_helpers::values2str(js.k_velocity).c_str()); + safety_xml->SetAttribute("soft_lower_limit", urdf_export_helpers::values2str(js.soft_lower_limit).c_str()); + safety_xml->SetAttribute("soft_upper_limit", urdf_export_helpers::values2str(js.soft_upper_limit).c_str()); xml->LinkEndChild(safety_xml); return true; } -bool exportJointCalibration(JointCalibration &jc, TiXmlElement* xml) +bool exportJointCalibration(JointCalibration &jc, tinyxml2::XMLElement* xml) { if (jc.falling || jc.rising) { - TiXmlElement *calibration_xml = new TiXmlElement("calibration"); + tinyxml2::XMLElement *calibration_xml = xml->GetDocument()->NewElement("calibration"); if (jc.falling) - calibration_xml->SetAttribute("falling", urdf_export_helpers::values2str(*jc.falling) ); + calibration_xml->SetAttribute("falling", urdf_export_helpers::values2str(*jc.falling).c_str()); if (jc.rising) - calibration_xml->SetAttribute("rising", urdf_export_helpers::values2str(*jc.rising) ); + calibration_xml->SetAttribute("rising", urdf_export_helpers::values2str(*jc.rising).c_str()); //calibration_xml->SetAttribute("reference_position", urdf_export_helpers::values2str(jc.reference_position) ); xml->LinkEndChild(calibration_xml); } return true; } -bool exportJointMimic(JointMimic &jm, TiXmlElement* xml) +bool exportJointMimic(JointMimic &jm, tinyxml2::XMLElement* xml) { if (!jm.joint_name.empty()) { - TiXmlElement *mimic_xml = new TiXmlElement("mimic"); - mimic_xml->SetAttribute("offset", urdf_export_helpers::values2str(jm.offset) ); - mimic_xml->SetAttribute("multiplier", urdf_export_helpers::values2str(jm.multiplier) ); - mimic_xml->SetAttribute("joint", jm.joint_name ); + tinyxml2::XMLElement *mimic_xml = xml->GetDocument()->NewElement("mimic"); + mimic_xml->SetAttribute("offset", urdf_export_helpers::values2str(jm.offset).c_str()); + mimic_xml->SetAttribute("multiplier", urdf_export_helpers::values2str(jm.multiplier).c_str()); + mimic_xml->SetAttribute("joint", jm.joint_name.c_str()); xml->LinkEndChild(mimic_xml); } return true; } -bool exportJoint(Joint &joint, TiXmlElement* xml) +bool exportJoint(Joint &joint, tinyxml2::XMLElement* xml) { - TiXmlElement * joint_xml = new TiXmlElement("joint"); - joint_xml->SetAttribute("name", joint.name); + tinyxml2::XMLElement * joint_xml = xml->GetDocument()->NewElement("joint"); + joint_xml->SetAttribute("name", joint.name.c_str()); if (joint.type == urdf::Joint::PLANAR) joint_xml->SetAttribute("type", "planar"); else if (joint.type == urdf::Joint::FLOATING) @@ -608,18 +608,18 @@ bool exportJoint(Joint &joint, TiXmlElement* xml) exportPose(joint.parent_to_joint_origin_transform, joint_xml); // axis - TiXmlElement * axis_xml = new TiXmlElement("axis"); - axis_xml->SetAttribute("xyz", urdf_export_helpers::values2str(joint.axis)); + tinyxml2::XMLElement * axis_xml = joint_xml->GetDocument()->NewElement("axis"); + axis_xml->SetAttribute("xyz", urdf_export_helpers::values2str(joint.axis).c_str()); joint_xml->LinkEndChild(axis_xml); - // parent - TiXmlElement * parent_xml = new TiXmlElement("parent"); - parent_xml->SetAttribute("link", joint.parent_link_name); + // parent + tinyxml2::XMLElement * parent_xml = joint_xml->GetDocument()->NewElement("parent"); + parent_xml->SetAttribute("link", joint.parent_link_name.c_str()); joint_xml->LinkEndChild(parent_xml); // child - TiXmlElement * child_xml = new TiXmlElement("child"); - child_xml->SetAttribute("link", joint.child_link_name); + tinyxml2::XMLElement * child_xml = joint_xml->GetDocument()->NewElement("child"); + child_xml->SetAttribute("link", joint.child_link_name.c_str()); joint_xml->LinkEndChild(child_xml); if (joint.dynamics) diff --git a/urdf_parser/src/link.cpp b/urdf_parser/src/link.cpp index a09ce381..85dafd44 100644 --- a/urdf_parser/src/link.cpp +++ b/urdf_parser/src/link.cpp @@ -1,13 +1,13 @@ /********************************************************************* * Software License Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -45,14 +45,14 @@ #include #include #include -#include +#include #include namespace urdf{ -bool parsePose(Pose &pose, TiXmlElement* xml); +bool parsePose(Pose &pose, tinyxml2::XMLElement* xml); -bool parseMaterial(Material &material, TiXmlElement *config, bool only_name_is_ok) +bool parseMaterial(Material &material, tinyxml2::XMLElement *config, bool only_name_is_ok) { bool has_rgb = false; bool has_filename = false; @@ -64,11 +64,11 @@ bool parseMaterial(Material &material, TiXmlElement *config, bool only_name_is_o CONSOLE_BRIDGE_logError("Material must contain a name attribute"); return false; } - + material.name = config->Attribute("name"); // texture - TiXmlElement *t = config->FirstChildElement("texture"); + tinyxml2::XMLElement *t = config->FirstChildElement("texture"); if (t) { if (t->Attribute("filename")) @@ -79,7 +79,7 @@ bool parseMaterial(Material &material, TiXmlElement *config, bool only_name_is_o } // color - TiXmlElement *c = config->FirstChildElement("color"); + tinyxml2::XMLElement *c = config->FirstChildElement("color"); if (c) { if (c->Attribute("rgba")) { @@ -88,7 +88,7 @@ bool parseMaterial(Material &material, TiXmlElement *config, bool only_name_is_o material.color.init(c->Attribute("rgba")); has_rgb = true; } - catch (ParseError &e) { + catch (ParseError &e) { material.color.clear(); CONSOLE_BRIDGE_logError(std::string("Material [" + material.name + "] has malformed color rgba values: " + e.what()).c_str()); } @@ -107,7 +107,7 @@ bool parseMaterial(Material &material, TiXmlElement *config, bool only_name_is_o } -bool parseSphere(Sphere &s, TiXmlElement *c) +bool parseSphere(Sphere &s, tinyxml2::XMLElement *c) { s.clear(); @@ -130,10 +130,10 @@ bool parseSphere(Sphere &s, TiXmlElement *c) return true; } -bool parseBox(Box &b, TiXmlElement *c) +bool parseBox(Box &b, tinyxml2::XMLElement *c) { b.clear(); - + b.type = Geometry::BOX; if (!c->Attribute("size")) { @@ -153,7 +153,7 @@ bool parseBox(Box &b, TiXmlElement *c) return true; } -bool parseCylinder(Cylinder &y, TiXmlElement *c) +bool parseCylinder(Cylinder &y, tinyxml2::XMLElement *c) { y.clear(); @@ -187,7 +187,7 @@ bool parseCylinder(Cylinder &y, TiXmlElement *c) } -bool parseMesh(Mesh &m, TiXmlElement *c) +bool parseMesh(Mesh &m, tinyxml2::XMLElement *c) { m.clear(); @@ -216,19 +216,19 @@ bool parseMesh(Mesh &m, TiXmlElement *c) return true; } -GeometrySharedPtr parseGeometry(TiXmlElement *g) +GeometrySharedPtr parseGeometry(tinyxml2::XMLElement *g) { GeometrySharedPtr geom; if (!g) return geom; - TiXmlElement *shape = g->FirstChildElement(); + tinyxml2::XMLElement *shape = g->FirstChildElement(); if (!shape) { CONSOLE_BRIDGE_logError("Geometry tag contains no child element."); return geom; } - std::string type_name = shape->ValueStr(); + std::string type_name = shape->Value(); if (type_name == "sphere") { Sphere *s = new Sphere(); @@ -255,30 +255,30 @@ GeometrySharedPtr parseGeometry(TiXmlElement *g) Mesh *m = new Mesh(); geom.reset(m); if (parseMesh(*m, shape)) - return geom; + return geom; } else { CONSOLE_BRIDGE_logError("Unknown geometry type '%s'", type_name.c_str()); return geom; } - + return GeometrySharedPtr(); } -bool parseInertial(Inertial &i, TiXmlElement *config) +bool parseInertial(Inertial &i, tinyxml2::XMLElement *config) { i.clear(); // Origin - TiXmlElement *o = config->FirstChildElement("origin"); + tinyxml2::XMLElement *o = config->FirstChildElement("origin"); if (o) { if (!parsePose(i.origin, o)) return false; } - TiXmlElement *mass_xml = config->FirstChildElement("mass"); + tinyxml2::XMLElement *mass_xml = config->FirstChildElement("mass"); if (!mass_xml) { CONSOLE_BRIDGE_logError("Inertial element must have a mass element"); @@ -300,7 +300,7 @@ bool parseInertial(Inertial &i, TiXmlElement *config) return false; } - TiXmlElement *inertia_xml = config->FirstChildElement("inertia"); + tinyxml2::XMLElement *inertia_xml = config->FirstChildElement("inertia"); if (!inertia_xml) { CONSOLE_BRIDGE_logError("Inertial element must have inertia element"); @@ -318,7 +318,7 @@ bool parseInertial(Inertial &i, TiXmlElement *config) for (auto& attr : attrs) { - if (!inertia_xml->Attribute(attr.first)) + if (!inertia_xml->Attribute(attr.first.c_str())) { std::stringstream stm; stm << "Inertial: inertia element missing " << attr.first << " attribute"; @@ -346,19 +346,19 @@ bool parseInertial(Inertial &i, TiXmlElement *config) return true; } -bool parseVisual(Visual &vis, TiXmlElement *config) +bool parseVisual(Visual &vis, tinyxml2::XMLElement *config) { vis.clear(); // Origin - TiXmlElement *o = config->FirstChildElement("origin"); + tinyxml2::XMLElement *o = config->FirstChildElement("origin"); if (o) { if (!parsePose(vis.origin, o)) return false; } // Geometry - TiXmlElement *geom = config->FirstChildElement("geometry"); + tinyxml2::XMLElement *geom = config->FirstChildElement("geometry"); vis.geometry = parseGeometry(geom); if (!vis.geometry) return false; @@ -368,7 +368,7 @@ bool parseVisual(Visual &vis, TiXmlElement *config) vis.name = name_char; // Material - TiXmlElement *mat = config->FirstChildElement("material"); + tinyxml2::XMLElement *mat = config->FirstChildElement("material"); if (mat) { // get material name if (!mat->Attribute("name")) { @@ -376,7 +376,7 @@ bool parseVisual(Visual &vis, TiXmlElement *config) return false; } vis.material_name = mat->Attribute("name"); - + // try to parse material element in place vis.material.reset(new Material()); if (!parseMaterial(*vis.material, mat, true)) @@ -384,23 +384,23 @@ bool parseVisual(Visual &vis, TiXmlElement *config) vis.material.reset(); } } - + return true; } -bool parseCollision(Collision &col, TiXmlElement* config) -{ +bool parseCollision(Collision &col, tinyxml2::XMLElement* config) +{ col.clear(); // Origin - TiXmlElement *o = config->FirstChildElement("origin"); + tinyxml2::XMLElement *o = config->FirstChildElement("origin"); if (o) { if (!parsePose(col.origin, o)) return false; } - + // Geometry - TiXmlElement *geom = config->FirstChildElement("geometry"); + tinyxml2::XMLElement *geom = config->FirstChildElement("geometry"); col.geometry = parseGeometry(geom); if (!col.geometry) return false; @@ -412,9 +412,9 @@ bool parseCollision(Collision &col, TiXmlElement* config) return true; } -bool parseLink(Link &link, TiXmlElement* config) +bool parseLink(Link &link, tinyxml2::XMLElement* config) { - + link.clear(); const char *name_char = config->Attribute("name"); @@ -426,7 +426,7 @@ bool parseLink(Link &link, TiXmlElement* config) link.name = std::string(name_char); // Inertial (optional) - TiXmlElement *i = config->FirstChildElement("inertial"); + tinyxml2::XMLElement *i = config->FirstChildElement("inertial"); if (i) { link.inertial.reset(new Inertial()); @@ -438,7 +438,7 @@ bool parseLink(Link &link, TiXmlElement* config) } // Multiple Visuals (optional) - for (TiXmlElement* vis_xml = config->FirstChildElement("visual"); vis_xml; vis_xml = vis_xml->NextSiblingElement("visual")) + for (tinyxml2::XMLElement* vis_xml = config->FirstChildElement("visual"); vis_xml; vis_xml = vis_xml->NextSiblingElement("visual")) { VisualSharedPtr vis; @@ -459,14 +459,14 @@ bool parseLink(Link &link, TiXmlElement* config) // Assign the first visual to the .visual ptr, if it exists if (!link.visual_array.empty()) link.visual = link.visual_array[0]; - + // Multiple Collisions (optional) - for (TiXmlElement* col_xml = config->FirstChildElement("collision"); col_xml; col_xml = col_xml->NextSiblingElement("collision")) + for (tinyxml2::XMLElement* col_xml = config->FirstChildElement("collision"); col_xml; col_xml = col_xml->NextSiblingElement("collision")) { CollisionSharedPtr col; col.reset(new Collision()); if (parseCollision(*col, col_xml)) - { + { link.collision_array.push_back(col); } else @@ -476,8 +476,8 @@ bool parseLink(Link &link, TiXmlElement* config) return false; } } - - // Collision (optional) + + // Collision (optional) // Assign the first collision to the .collision ptr, if it exists if (!link.collision_array.empty()) link.collision = link.collision_array[0]; @@ -486,67 +486,67 @@ bool parseLink(Link &link, TiXmlElement* config) } /* exports */ -bool exportPose(Pose &pose, TiXmlElement* xml); +bool exportPose(Pose &pose, tinyxml2::XMLElement* xml); -bool exportMaterial(Material &material, TiXmlElement *xml) +bool exportMaterial(Material &material, tinyxml2::XMLElement *xml) { - TiXmlElement *material_xml = new TiXmlElement("material"); - material_xml->SetAttribute("name", material.name); + tinyxml2::XMLElement* material_xml = xml->GetDocument()->NewElement("material"); + material_xml->SetAttribute("name", material.name.c_str()); - TiXmlElement* texture = new TiXmlElement("texture"); + tinyxml2::XMLElement* texture = material_xml->GetDocument()->NewElement("texture"); if (!material.texture_filename.empty()) - texture->SetAttribute("filename", material.texture_filename); + texture->SetAttribute("filename", material.texture_filename.c_str()); material_xml->LinkEndChild(texture); - TiXmlElement* color = new TiXmlElement("color"); - color->SetAttribute("rgba", urdf_export_helpers::values2str(material.color)); + tinyxml2::XMLElement* color = material_xml->GetDocument()->NewElement("color"); + color->SetAttribute("rgba", urdf_export_helpers::values2str(material.color).c_str()); material_xml->LinkEndChild(color); xml->LinkEndChild(material_xml); return true; } -bool exportSphere(Sphere &s, TiXmlElement *xml) +bool exportSphere(Sphere &s, tinyxml2::XMLElement *xml) { // e.g. add - TiXmlElement *sphere_xml = new TiXmlElement("sphere"); - sphere_xml->SetAttribute("radius", urdf_export_helpers::values2str(s.radius)); + tinyxml2::XMLElement *sphere_xml = xml->GetDocument()->NewElement("sphere"); + sphere_xml->SetAttribute("radius", urdf_export_helpers::values2str(s.radius).c_str()); xml->LinkEndChild(sphere_xml); return true; } -bool exportBox(Box &b, TiXmlElement *xml) +bool exportBox(Box &b, tinyxml2::XMLElement *xml) { // e.g. add - TiXmlElement *box_xml = new TiXmlElement("box"); - box_xml->SetAttribute("size", urdf_export_helpers::values2str(b.dim)); + tinyxml2::XMLElement *box_xml = xml->GetDocument()->NewElement("box"); + box_xml->SetAttribute("size", urdf_export_helpers::values2str(b.dim).c_str()); xml->LinkEndChild(box_xml); return true; } -bool exportCylinder(Cylinder &y, TiXmlElement *xml) +bool exportCylinder(Cylinder &y, tinyxml2::XMLElement *xml) { // e.g. add - TiXmlElement *cylinder_xml = new TiXmlElement("cylinder"); - cylinder_xml->SetAttribute("radius", urdf_export_helpers::values2str(y.radius)); - cylinder_xml->SetAttribute("length", urdf_export_helpers::values2str(y.length)); + tinyxml2::XMLElement *cylinder_xml = xml->GetDocument()->NewElement("cylinder"); + cylinder_xml->SetAttribute("radius", urdf_export_helpers::values2str(y.radius).c_str()); + cylinder_xml->SetAttribute("length", urdf_export_helpers::values2str(y.length).c_str()); xml->LinkEndChild(cylinder_xml); return true; } -bool exportMesh(Mesh &m, TiXmlElement *xml) +bool exportMesh(Mesh &m, tinyxml2::XMLElement *xml) { // e.g. add - TiXmlElement *mesh_xml = new TiXmlElement("mesh"); + tinyxml2::XMLElement *mesh_xml = xml->GetDocument()->NewElement("mesh"); if (!m.filename.empty()) - mesh_xml->SetAttribute("filename", m.filename); - mesh_xml->SetAttribute("scale", urdf_export_helpers::values2str(m.scale)); + mesh_xml->SetAttribute("filename", m.filename.c_str()); + mesh_xml->SetAttribute("scale", urdf_export_helpers::values2str(m.scale).c_str()); xml->LinkEndChild(mesh_xml); return true; } -bool exportGeometry(GeometrySharedPtr &geom, TiXmlElement *xml) +bool exportGeometry(GeometrySharedPtr &geom, tinyxml2::XMLElement *xml) { - TiXmlElement *geometry_xml = new TiXmlElement("geometry"); + tinyxml2::XMLElement *geometry_xml = xml->GetDocument()->NewElement("geometry"); if (urdf::dynamic_pointer_cast(geom)) { exportSphere((*(urdf::dynamic_pointer_cast(geom).get())), geometry_xml); @@ -576,36 +576,36 @@ bool exportGeometry(GeometrySharedPtr &geom, TiXmlElement *xml) return true; } -bool exportInertial(Inertial &i, TiXmlElement *xml) +bool exportInertial(Inertial &i, tinyxml2::XMLElement *xml) { // adds // // // // - TiXmlElement *inertial_xml = new TiXmlElement("inertial"); + tinyxml2::XMLElement *inertial_xml = xml->GetDocument()->NewElement("inertial"); - TiXmlElement *mass_xml = new TiXmlElement("mass"); - mass_xml->SetAttribute("value", urdf_export_helpers::values2str(i.mass)); + tinyxml2::XMLElement *mass_xml = inertial_xml->GetDocument()->NewElement("mass"); + mass_xml->SetAttribute("value", urdf_export_helpers::values2str(i.mass).c_str()); inertial_xml->LinkEndChild(mass_xml); exportPose(i.origin, inertial_xml); - TiXmlElement *inertia_xml = new TiXmlElement("inertia"); - inertia_xml->SetAttribute("ixx", urdf_export_helpers::values2str(i.ixx)); - inertia_xml->SetAttribute("ixy", urdf_export_helpers::values2str(i.ixy)); - inertia_xml->SetAttribute("ixz", urdf_export_helpers::values2str(i.ixz)); - inertia_xml->SetAttribute("iyy", urdf_export_helpers::values2str(i.iyy)); - inertia_xml->SetAttribute("iyz", urdf_export_helpers::values2str(i.iyz)); - inertia_xml->SetAttribute("izz", urdf_export_helpers::values2str(i.izz)); + tinyxml2::XMLElement *inertia_xml = inertial_xml->GetDocument()->NewElement("inertia"); + inertia_xml->SetAttribute("ixx", urdf_export_helpers::values2str(i.ixx).c_str()); + inertia_xml->SetAttribute("ixy", urdf_export_helpers::values2str(i.ixy).c_str()); + inertia_xml->SetAttribute("ixz", urdf_export_helpers::values2str(i.ixz).c_str()); + inertia_xml->SetAttribute("iyy", urdf_export_helpers::values2str(i.iyy).c_str()); + inertia_xml->SetAttribute("iyz", urdf_export_helpers::values2str(i.iyz).c_str()); + inertia_xml->SetAttribute("izz", urdf_export_helpers::values2str(i.izz).c_str()); inertial_xml->LinkEndChild(inertia_xml); xml->LinkEndChild(inertial_xml); - + return true; } -bool exportVisual(Visual &vis, TiXmlElement *xml) +bool exportVisual(Visual &vis, tinyxml2::XMLElement *xml) { // // @@ -614,7 +614,7 @@ bool exportVisual(Visual &vis, TiXmlElement *xml) // // // - TiXmlElement * visual_xml = new TiXmlElement("visual"); + tinyxml2::XMLElement * visual_xml = xml->GetDocument()->NewElement("visual"); exportPose(vis.origin, visual_xml); @@ -628,8 +628,8 @@ bool exportVisual(Visual &vis, TiXmlElement *xml) return true; } -bool exportCollision(Collision &col, TiXmlElement* xml) -{ +bool exportCollision(Collision &col, tinyxml2::XMLElement* xml) +{ // // // @@ -637,7 +637,7 @@ bool exportCollision(Collision &col, TiXmlElement* xml) // // // - TiXmlElement * collision_xml = new TiXmlElement("collision"); + tinyxml2::XMLElement * collision_xml = xml->GetDocument()->NewElement("collision"); exportPose(col.origin, collision_xml); @@ -648,10 +648,10 @@ bool exportCollision(Collision &col, TiXmlElement* xml) return true; } -bool exportLink(Link &link, TiXmlElement* xml) +bool exportLink(Link &link, tinyxml2::XMLElement* xml) { - TiXmlElement * link_xml = new TiXmlElement("link"); - link_xml->SetAttribute("name", link.name); + tinyxml2::XMLElement * link_xml = xml->GetDocument()->NewElement("link"); + link_xml->SetAttribute("name", link.name.c_str()); if (link.inertial) exportInertial(*link.inertial, link_xml); diff --git a/urdf_parser/src/model.cpp b/urdf_parser/src/model.cpp index 2932eadf..e3592939 100644 --- a/urdf_parser/src/model.cpp +++ b/urdf_parser/src/model.cpp @@ -1,13 +1,13 @@ /********************************************************************* * Software License Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -43,9 +43,9 @@ namespace urdf{ -bool parseMaterial(Material &material, TiXmlElement *config, bool only_name_is_ok); -bool parseLink(Link &link, TiXmlElement *config); -bool parseJoint(Joint &joint, TiXmlElement *config); +bool parseMaterial(Material &material, tinyxml2::XMLElement *config, bool only_name_is_ok); +bool parseLink(Link &link, tinyxml2::XMLElement *config); +bool parseJoint(Joint &joint, tinyxml2::XMLElement *config); ModelInterfaceSharedPtr parseURDFFile(const std::string &path) { @@ -93,17 +93,17 @@ ModelInterfaceSharedPtr parseURDF(const std::string &xml_string) ModelInterfaceSharedPtr model(new ModelInterface); model->clear(); - TiXmlDocument xml_doc; + tinyxml2::XMLDocument xml_doc; xml_doc.Parse(xml_string.c_str()); if (xml_doc.Error()) { - CONSOLE_BRIDGE_logError(xml_doc.ErrorDesc()); + CONSOLE_BRIDGE_logError(xml_doc.ErrorStr()); xml_doc.ClearError(); model.reset(); return model; } - TiXmlElement *robot_xml = xml_doc.FirstChildElement("robot"); + tinyxml2::XMLElement *robot_xml = xml_doc.FirstChildElement("robot"); if (!robot_xml) { CONSOLE_BRIDGE_logError("Could not find the 'robot' element in the xml file"); @@ -137,7 +137,7 @@ ModelInterfaceSharedPtr parseURDF(const std::string &xml_string) } // Get all Material elements - for (TiXmlElement* material_xml = robot_xml->FirstChildElement("material"); material_xml; material_xml = material_xml->NextSiblingElement("material")) + for (tinyxml2::XMLElement* material_xml = robot_xml->FirstChildElement("material"); material_xml; material_xml = material_xml->NextSiblingElement("material")) { MaterialSharedPtr material; material.reset(new Material); @@ -166,7 +166,7 @@ ModelInterfaceSharedPtr parseURDF(const std::string &xml_string) } // Get all Link elements - for (TiXmlElement* link_xml = robot_xml->FirstChildElement("link"); link_xml; link_xml = link_xml->NextSiblingElement("link")) + for (tinyxml2::XMLElement* link_xml = robot_xml->FirstChildElement("link"); link_xml; link_xml = link_xml->NextSiblingElement("link")) { LinkSharedPtr link; link.reset(new Link); @@ -209,7 +209,7 @@ ModelInterfaceSharedPtr parseURDF(const std::string &xml_string) } // Get all Joint elements - for (TiXmlElement* joint_xml = robot_xml->FirstChildElement("joint"); joint_xml; joint_xml = joint_xml->NextSiblingElement("joint")) + for (tinyxml2::XMLElement* joint_xml = robot_xml->FirstChildElement("joint"); joint_xml; joint_xml = joint_xml->NextSiblingElement("joint")) { JointSharedPtr joint; joint.reset(new Joint); @@ -243,7 +243,7 @@ ModelInterfaceSharedPtr parseURDF(const std::string &xml_string) parent_link_tree.clear(); // building tree: name mapping - try + try { model->initTree(parent_link_tree); } @@ -265,19 +265,19 @@ ModelInterfaceSharedPtr parseURDF(const std::string &xml_string) model.reset(); return model; } - + return model; } -bool exportMaterial(Material &material, TiXmlElement *config); -bool exportLink(Link &link, TiXmlElement *config); -bool exportJoint(Joint &joint, TiXmlElement *config); -TiXmlDocument* exportURDF(const ModelInterface &model) +bool exportMaterial(Material &material, tinyxml2::XMLElement *config); +bool exportLink(Link &link, tinyxml2::XMLElement *config); +bool exportJoint(Joint &joint, tinyxml2::XMLElement *config); +tinyxml2::XMLDocument* exportURDF(const ModelInterface &model) { - TiXmlDocument *doc = new TiXmlDocument(); + tinyxml2::XMLDocument *doc = new tinyxml2::XMLDocument(); - TiXmlElement *robot = new TiXmlElement("robot"); - robot->SetAttribute("name", model.name_); + tinyxml2::XMLElement* robot = doc->NewElement("robot"); + robot->SetAttribute("name", model.name_.c_str()); doc->LinkEndChild(robot); @@ -287,13 +287,13 @@ TiXmlDocument* exportURDF(const ModelInterface &model) exportMaterial(*(m->second), robot); } - for (std::map::const_iterator l=model.links_.begin(); l!=model.links_.end(); ++l) + for (std::map::const_iterator l=model.links_.begin(); l!=model.links_.end(); ++l) { CONSOLE_BRIDGE_logDebug("urdfdom: exporting link [%s]\n",l->second->name.c_str()); exportLink(*(l->second), robot); } - - for (std::map::const_iterator j=model.joints_.begin(); j!=model.joints_.end(); ++j) + + for (std::map::const_iterator j=model.joints_.begin(); j!=model.joints_.end(); ++j) { CONSOLE_BRIDGE_logDebug("urdfdom: exporting joint [%s]\n",j->second->name.c_str()); exportJoint(*(j->second), robot); @@ -301,12 +301,11 @@ TiXmlDocument* exportURDF(const ModelInterface &model) return doc; } - -TiXmlDocument* exportURDF(ModelInterfaceSharedPtr &model) + +tinyxml2::XMLDocument* exportURDF(ModelInterfaceSharedPtr &model) { return exportURDF(*model); } } - diff --git a/urdf_parser/src/pose.cpp b/urdf_parser/src/pose.cpp index 56bedd48..87479f39 100644 --- a/urdf_parser/src/pose.cpp +++ b/urdf_parser/src/pose.cpp @@ -1,13 +1,13 @@ /********************************************************************* * Software License Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -40,7 +40,7 @@ #include #include #include -#include +#include #include namespace urdf_export_helpers { @@ -87,7 +87,7 @@ std::string values2str(double d) namespace urdf{ -bool parsePose(Pose &pose, TiXmlElement* xml) +bool parsePose(Pose &pose, tinyxml2::XMLElement* xml) { pose.clear(); if (xml) @@ -119,17 +119,15 @@ bool parsePose(Pose &pose, TiXmlElement* xml) return true; } -bool exportPose(Pose &pose, TiXmlElement* xml) +bool exportPose(Pose &pose, tinyxml2::XMLElement* xml) { - TiXmlElement *origin = new TiXmlElement("origin"); + tinyxml2::XMLElement* origin = xml->GetDocument()->NewElement("origin"); std::string pose_xyz_str = urdf_export_helpers::values2str(pose.position); std::string pose_rpy_str = urdf_export_helpers::values2str(pose.rotation); - origin->SetAttribute("xyz", pose_xyz_str); - origin->SetAttribute("rpy", pose_rpy_str); + origin->SetAttribute("xyz", pose_xyz_str.c_str()); + origin->SetAttribute("rpy", pose_rpy_str.c_str()); xml->LinkEndChild(origin); return true; } } - - diff --git a/urdf_parser/src/twist.cpp b/urdf_parser/src/twist.cpp index 694fc914..dd88794a 100644 --- a/urdf_parser/src/twist.cpp +++ b/urdf_parser/src/twist.cpp @@ -1,13 +1,13 @@ /********************************************************************* * Software License Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -39,12 +39,12 @@ #include #include #include -#include +#include #include namespace urdf{ -bool parseTwist(Twist &twist, TiXmlElement* xml) +bool parseTwist(Twist &twist, tinyxml2::XMLElement* xml) { twist.clear(); if (xml) @@ -79,6 +79,3 @@ bool parseTwist(Twist &twist, TiXmlElement* xml) } } - - - diff --git a/urdf_parser/src/urdf_model_state.cpp b/urdf_parser/src/urdf_model_state.cpp index 40169781..7f117ad1 100644 --- a/urdf_parser/src/urdf_model_state.cpp +++ b/urdf_parser/src/urdf_model_state.cpp @@ -1,13 +1,13 @@ /********************************************************************* * Software License Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -43,13 +43,13 @@ #include #include #include -#include +#include #include #include namespace urdf{ -bool parseModelState(ModelState &ms, TiXmlElement* config) +bool parseModelState(ModelState &ms, tinyxml2::XMLElement* config) { ms.clear(); @@ -72,7 +72,7 @@ bool parseModelState(ModelState &ms, TiXmlElement* config) } } - TiXmlElement *joint_state_elem = config->FirstChildElement("joint_state"); + tinyxml2::XMLElement *joint_state_elem = config->FirstChildElement("joint_state"); if (joint_state_elem) { JointStateSharedPtr joint_state; @@ -86,7 +86,7 @@ bool parseModelState(ModelState &ms, TiXmlElement* config) CONSOLE_BRIDGE_logError("No joint name given for the model_state."); return false; } - + // parse position const char *position_char = joint_state_elem->Attribute("position"); if (position_char) @@ -150,5 +150,3 @@ bool parseModelState(ModelState &ms, TiXmlElement* config) } - - diff --git a/urdf_parser/src/urdf_sensor.cpp b/urdf_parser/src/urdf_sensor.cpp index ee863944..8332920c 100644 --- a/urdf_parser/src/urdf_sensor.cpp +++ b/urdf_parser/src/urdf_sensor.cpp @@ -1,13 +1,13 @@ /********************************************************************* * Software License Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -42,21 +42,21 @@ #include #include #include -#include +#include #include #include namespace urdf{ -bool parsePose(Pose &pose, TiXmlElement* xml); +bool parsePose(Pose &pose, tinyxml2::XMLElement* xml); -bool parseCamera(Camera &camera, TiXmlElement* config) +bool parseCamera(Camera &camera, tinyxml2::XMLElement* config) { camera.clear(); camera.type = VisualSensor::CAMERA; - TiXmlElement *image = config->FirstChildElement("image"); + tinyxml2::XMLElement *image = config->FirstChildElement("image"); if (image) { const char* width_char = image->Attribute("width"); @@ -114,7 +114,7 @@ bool parseCamera(Camera &camera, TiXmlElement* config) { CONSOLE_BRIDGE_logError("Camera sensor needs an image format attribute"); return false; - } + } const char* hfov_char = image->Attribute("hfov"); if (hfov_char) @@ -163,7 +163,7 @@ bool parseCamera(Camera &camera, TiXmlElement* config) CONSOLE_BRIDGE_logError("Camera sensor needs an image far attribute"); return false; } - + } else { @@ -173,12 +173,12 @@ bool parseCamera(Camera &camera, TiXmlElement* config) return true; } -bool parseRay(Ray &ray, TiXmlElement* config) +bool parseRay(Ray &ray, tinyxml2::XMLElement* config) { ray.clear(); ray.type = VisualSensor::RAY; - TiXmlElement *horizontal = config->FirstChildElement("horizontal"); + tinyxml2::XMLElement *horizontal = config->FirstChildElement("horizontal"); if (horizontal) { const char* samples_char = horizontal->Attribute("samples"); @@ -233,8 +233,8 @@ bool parseRay(Ray &ray, TiXmlElement* config) } } } - - TiXmlElement *vertical = config->FirstChildElement("vertical"); + + tinyxml2::XMLElement *vertical = config->FirstChildElement("vertical"); if (vertical) { const char* samples_char = vertical->Attribute("samples"); @@ -292,12 +292,12 @@ bool parseRay(Ray &ray, TiXmlElement* config) return false; } -VisualSensorSharedPtr parseVisualSensor(TiXmlElement *g) +VisualSensorSharedPtr parseVisualSensor(tinyxml2::XMLElement *g) { VisualSensorSharedPtr visual_sensor; // get sensor type - TiXmlElement *sensor_xml; + tinyxml2::XMLElement *sensor_xml; if (g->FirstChildElement("camera")) { Camera *camera = new Camera(); @@ -322,7 +322,7 @@ VisualSensorSharedPtr parseVisualSensor(TiXmlElement *g) } -bool parseSensor(Sensor &sensor, TiXmlElement* config) +bool parseSensor(Sensor &sensor, tinyxml2::XMLElement* config) { sensor.clear(); @@ -344,7 +344,7 @@ bool parseSensor(Sensor &sensor, TiXmlElement* config) sensor.parent_link_name = std::string(parent_link_name_char); // parse origin - TiXmlElement *o = config->FirstChildElement("origin"); + tinyxml2::XMLElement *o = config->FirstChildElement("origin"); if (o) { if (!parsePose(sensor.origin, o)) @@ -358,5 +358,3 @@ bool parseSensor(Sensor &sensor, TiXmlElement* config) } - - diff --git a/urdf_parser/src/world.cpp b/urdf_parser/src/world.cpp index ce09c1c3..4aa6e3a9 100644 --- a/urdf_parser/src/world.cpp +++ b/urdf_parser/src/world.cpp @@ -1,13 +1,13 @@ /********************************************************************* * Software License Agreement (BSD License) -* +* * Copyright (c) 2008, Willow Garage, Inc. * All rights reserved. -* +* * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: -* +* * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above @@ -17,7 +17,7 @@ * * Neither the name of the Willow Garage nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. -* +* * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS @@ -41,12 +41,12 @@ #include #include #include -#include +#include #include namespace urdf{ -bool parseWorld(World &/*world*/, TiXmlElement* /*config*/) +bool parseWorld(World &/*world*/, tinyxml2::XMLElement* /*config*/) { // to be implemented @@ -54,10 +54,10 @@ bool parseWorld(World &/*world*/, TiXmlElement* /*config*/) return true; } -bool exportWorld(World &world, TiXmlElement* xml) +bool exportWorld(World &world, tinyxml2::XMLElement* xml) { - TiXmlElement * world_xml = new TiXmlElement("world"); - world_xml->SetAttribute("name", world.name); + tinyxml2::XMLElement * world_xml = xml->GetDocument()->NewElement("world"); + world_xml->SetAttribute("name", world.name.c_str()); // to be implemented // exportModels(*world.models, world_xml); From 3472d7ab53f28f42efb45d3f7e5a2ad13d753845 Mon Sep 17 00:00:00 2001 From: Silvio Traversaro Date: Thu, 7 Dec 2023 07:06:11 +0900 Subject: [PATCH 17/23] Do not install CMake config files in a different directory (#188) Signed-off-by: harleylara --- CMakeLists.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13ba51eb..c01d769f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,11 +59,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}" enable_testing() -if(WIN32 AND NOT CYGWIN) - set(CMAKE_CONFIG_INSTALL_DIR CMake) -else() - set(CMAKE_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake) -endif() +set(CMAKE_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}/cmake) string(REGEX REPLACE "[^/]+" ".." RELATIVE_PATH_CMAKE_DIR_TO_PREFIX "${CMAKE_CONFIG_INSTALL_DIR}") string(REGEX REPLACE "[^/]+" ".." RELATIVE_PATH_LIBDIR_TO_PREFIX "${CMAKE_INSTALL_LIBDIR}") From 89cd02f8cafb55062e3d9017bb070ecd8fe9228f Mon Sep 17 00:00:00 2001 From: Chris Lalancette Date: Fri, 8 Dec 2023 08:42:34 -0500 Subject: [PATCH 18/23] Remove tinyxml2 from public dependencies. (#190) That way, we don't have to export the tinyxml2 dependencies to downstream consumers. It is just a private dependency at that point. Signed-off-by: Chris Lalancette Signed-off-by: harleylara --- CMakeLists.txt | 9 ++------- urdf_parser/CMakeLists.txt | 4 +++- urdf_parser/include/urdf_parser/urdf_parser.h | 8 +++++++- urdf_parser/src/check_urdf.cpp | 2 ++ urdf_parser/src/model.cpp | 1 + 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c01d769f..20812842 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,7 +67,7 @@ add_subdirectory(urdf_parser) set(PKG_NAME ${PROJECT_NAME}) set(PKG_LIBRARIES urdfdom_sensor urdfdom_model_state urdfdom_model urdfdom_world) -set(PKG_DEPENDS TinyXML2 urdfdom_headers console_bridge) +set(PKG_DEPENDS urdfdom_headers) set(PKG_EXPORTS urdfdom) set(cmake_conf_file "cmake/urdfdom-config") include(CMakePackageConfigHelpers) @@ -86,16 +86,11 @@ install(FILES DESTINATION ${CMAKE_CONFIG_INSTALL_DIR} ) -# Some operating systems (like Ubuntu 22.04) do not provide a default -# way to find TinyXML2. For that reason, this package provides it -install(FILES cmake/FindTinyXML2.cmake - DESTINATION ${CMAKE_CONFIG_INSTALL_DIR}) - install(FILES package.xml DESTINATION share/${PROJECT_NAME}) # Make the package config file set(PKG_DESC "Unified Robot Description Format") -set(PKG_DEPENDS "tinyxml2 urdfdom_headers console_bridge") # make the list separated by spaces instead of ; +set(PKG_DEPENDS "urdfdom_headers") # make the list separated by spaces instead of ; set(PKG_URDF_LIBS "-lurdfdom_sensor -lurdfdom_model_state -lurdfdom_model -lurdfdom_world") set(pkg_conf_file "cmake/pkgconfig/urdfdom.pc") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${pkg_conf_file}.in" "${CMAKE_BINARY_DIR}/${pkg_conf_file}" @ONLY) diff --git a/urdf_parser/CMakeLists.txt b/urdf_parser/CMakeLists.txt index dba9ddab..a375f1fd 100644 --- a/urdf_parser/CMakeLists.txt +++ b/urdf_parser/CMakeLists.txt @@ -10,8 +10,10 @@ macro(add_urdfdom_library) "$") target_link_libraries(${add_urdfdom_library_LIBNAME} PUBLIC ${add_urdfdom_library_LINK} - ${console_bridge_link_libs} ${urdfdom_headers_link_libs} + ) + target_link_libraries(${add_urdfdom_library_LIBNAME} PRIVATE + ${console_bridge_link_libs} tinyxml2::tinyxml2 ) if(NOT CMAKE_CXX_STANDARD) diff --git a/urdf_parser/include/urdf_parser/urdf_parser.h b/urdf_parser/include/urdf_parser/urdf_parser.h index b7419483..0ea27df1 100644 --- a/urdf_parser/include/urdf_parser/urdf_parser.h +++ b/urdf_parser/include/urdf_parser/urdf_parser.h @@ -41,7 +41,6 @@ #include #include -#include #include #include #include @@ -51,6 +50,13 @@ #include "exportdecl.h" +namespace tinyxml2{ + // Forward declaration for APIs that use TinyXML2 structures. + // That way, we don't have to export a TinyXML2 dependency. + class XMLDocument; + class XMLElement; +} + namespace urdf_export_helpers { URDFDOM_DLLAPI std::string values2str(unsigned int count, const double *values, double (*conv)(double) = NULL); diff --git a/urdf_parser/src/check_urdf.cpp b/urdf_parser/src/check_urdf.cpp index 42e0fdac..292e6d20 100644 --- a/urdf_parser/src/check_urdf.cpp +++ b/urdf_parser/src/check_urdf.cpp @@ -35,6 +35,8 @@ /* Author: Wim Meeussen */ #include "urdf_parser/urdf_parser.h" + +#include #include #include diff --git a/urdf_parser/src/model.cpp b/urdf_parser/src/model.cpp index e3592939..fb49ecca 100644 --- a/urdf_parser/src/model.cpp +++ b/urdf_parser/src/model.cpp @@ -40,6 +40,7 @@ #include #include "urdf_parser/urdf_parser.h" #include +#include namespace urdf{ From 1e2932f31b37f291357a670ba7ec73f2f5836ac6 Mon Sep 17 00:00:00 2001 From: DasRoteSkelett Date: Wed, 20 Dec 2023 17:50:40 +0100 Subject: [PATCH 19/23] CMakeLists.txt: Some fixes for Relocatable package (#179) There are some absolute path in the generation of the .cmake files which ruin the creation of relocatable packages. Fixing: * CMAKE_MODULE_PATH append instead of replacement * INTERFACE use relative path instead of ${CMAKE_INSTALL_INCLUDEDIR} See also https://cmake.org/cmake/help/latest/guide/importing-exporting/index.html#creating-relocatable-packages for reference. Signed-off-by: Matthias Schoepfer Co-authored-by: Matthias Schoepfer Signed-off-by: harleylara --- CMakeLists.txt | 2 +- urdf_parser/CMakeLists.txt | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 20812842..ae031354 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,7 +43,7 @@ if(MSVC OR MSVC90 OR MSVC10) set(MSVC ON) endif (MSVC OR MSVC90 OR MSVC10) -set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") find_package(tinyxml2_vendor QUIET) find_package(TinyXML2 REQUIRED) diff --git a/urdf_parser/CMakeLists.txt b/urdf_parser/CMakeLists.txt index a375f1fd..20a6a050 100644 --- a/urdf_parser/CMakeLists.txt +++ b/urdf_parser/CMakeLists.txt @@ -75,9 +75,9 @@ target_include_directories(urdf_parser INTERFACE "$" "$") target_link_libraries(urdf_parser INTERFACE - urdfdom_model - urdfdom_sensor - urdfdom_world) + urdfdom::urdfdom_model + urdfdom::urdfdom_sensor + urdfdom::urdfdom_world) # -------------------------------- From 413402288209d68251756c21686ad7f5ff6f0c51 Mon Sep 17 00:00:00 2001 From: Chris Lalancette Date: Wed, 20 Dec 2023 11:50:56 -0500 Subject: [PATCH 20/23] Deprecate the APIs that we think are unused. (#191) * Deprecate the APIs that we think are unused. In an earlier commit, we changed from tinyxml -> tinyxml2 in the public API because we thought that there were no users of these APIs. Codify that here by marking these APIs as deprecated; if a user comes along and says that they are actually using it, we can undeprecated it. Note that in order to avoid deprecations from within the library, I had to add a bit of additional indirection here. If we remove the APIs in the future, we can also remove this indirection. * Properly export parsePoseInternal to make Windows happy. Signed-off-by: Chris Lalancette Signed-off-by: harleylara --- urdf_parser/include/urdf_parser/urdf_parser.h | 14 ++++++ urdf_parser/src/joint.cpp | 6 +-- urdf_parser/src/link.cpp | 10 ++--- urdf_parser/src/model.cpp | 10 ++++- urdf_parser/src/pose.cpp | 9 +++- urdf_parser/src/pose.hpp | 44 +++++++++++++++++++ urdf_parser/src/urdf_sensor.cpp | 24 +++++++--- 7 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 urdf_parser/src/pose.hpp diff --git a/urdf_parser/include/urdf_parser/urdf_parser.h b/urdf_parser/include/urdf_parser/urdf_parser.h index 0ea27df1..240e9df3 100644 --- a/urdf_parser/include/urdf_parser/urdf_parser.h +++ b/urdf_parser/include/urdf_parser/urdf_parser.h @@ -149,12 +149,26 @@ namespace urdf{ URDFDOM_DLLAPI ModelInterfaceSharedPtr parseURDF(const std::string &xml_string); URDFDOM_DLLAPI ModelInterfaceSharedPtr parseURDFFile(const std::string &path); + + [[deprecated("File an issue at https://github.com/ros/urdfdom if you rely on this")]] URDFDOM_DLLAPI tinyxml2::XMLDocument* exportURDF(ModelInterfaceSharedPtr &model); + + [[deprecated("File an issue at https://github.com/ros/urdfdom if you rely on this")]] URDFDOM_DLLAPI tinyxml2::XMLDocument* exportURDF(const ModelInterface &model); + + [[deprecated("File an issue at https://github.com/ros/urdfdom if you rely on this")]] URDFDOM_DLLAPI bool parsePose(Pose&, tinyxml2::XMLElement*); + + [[deprecated("File an issue at https://github.com/ros/urdfdom if you rely on this")]] URDFDOM_DLLAPI bool parseCamera(Camera&, tinyxml2::XMLElement*); + + [[deprecated("File an issue at https://github.com/ros/urdfdom if you rely on this")]] URDFDOM_DLLAPI bool parseRay(Ray&, tinyxml2::XMLElement*); + + [[deprecated("File an issue at https://github.com/ros/urdfdom if you rely on this")]] URDFDOM_DLLAPI bool parseSensor(Sensor&, tinyxml2::XMLElement*); + + [[deprecated("File an issue at https://github.com/ros/urdfdom if you rely on this")]] URDFDOM_DLLAPI bool parseModelState(ModelState&, tinyxml2::XMLElement*); } diff --git a/urdf_parser/src/joint.cpp b/urdf_parser/src/joint.cpp index 7668350f..4269419a 100644 --- a/urdf_parser/src/joint.cpp +++ b/urdf_parser/src/joint.cpp @@ -43,9 +43,9 @@ #include #include -namespace urdf{ +#include "./pose.hpp" -bool parsePose(Pose &pose, tinyxml2::XMLElement* xml); +namespace urdf{ bool parseJointDynamics(JointDynamics &jd, tinyxml2::XMLElement* config) { @@ -356,7 +356,7 @@ bool parseJoint(Joint &joint, tinyxml2::XMLElement* config) } else { - if (!parsePose(joint.parent_to_joint_origin_transform, origin_xml)) + if (!parsePoseInternal(joint.parent_to_joint_origin_transform, origin_xml)) { joint.parent_to_joint_origin_transform.clear(); CONSOLE_BRIDGE_logError("Malformed parent origin element for joint [%s]", joint.name.c_str()); diff --git a/urdf_parser/src/link.cpp b/urdf_parser/src/link.cpp index 85dafd44..ab83b5d3 100644 --- a/urdf_parser/src/link.cpp +++ b/urdf_parser/src/link.cpp @@ -48,9 +48,9 @@ #include #include -namespace urdf{ +#include "./pose.hpp" -bool parsePose(Pose &pose, tinyxml2::XMLElement* xml); +namespace urdf{ bool parseMaterial(Material &material, tinyxml2::XMLElement *config, bool only_name_is_ok) { @@ -274,7 +274,7 @@ bool parseInertial(Inertial &i, tinyxml2::XMLElement *config) tinyxml2::XMLElement *o = config->FirstChildElement("origin"); if (o) { - if (!parsePose(i.origin, o)) + if (!parsePoseInternal(i.origin, o)) return false; } @@ -353,7 +353,7 @@ bool parseVisual(Visual &vis, tinyxml2::XMLElement *config) // Origin tinyxml2::XMLElement *o = config->FirstChildElement("origin"); if (o) { - if (!parsePose(vis.origin, o)) + if (!parsePoseInternal(vis.origin, o)) return false; } @@ -395,7 +395,7 @@ bool parseCollision(Collision &col, tinyxml2::XMLElement* config) // Origin tinyxml2::XMLElement *o = config->FirstChildElement("origin"); if (o) { - if (!parsePose(col.origin, o)) + if (!parsePoseInternal(col.origin, o)) return false; } diff --git a/urdf_parser/src/model.cpp b/urdf_parser/src/model.cpp index fb49ecca..5236668a 100644 --- a/urdf_parser/src/model.cpp +++ b/urdf_parser/src/model.cpp @@ -273,7 +273,8 @@ ModelInterfaceSharedPtr parseURDF(const std::string &xml_string) bool exportMaterial(Material &material, tinyxml2::XMLElement *config); bool exportLink(Link &link, tinyxml2::XMLElement *config); bool exportJoint(Joint &joint, tinyxml2::XMLElement *config); -tinyxml2::XMLDocument* exportURDF(const ModelInterface &model) + +tinyxml2::XMLDocument* exportURDFInternal(const ModelInterface &model) { tinyxml2::XMLDocument *doc = new tinyxml2::XMLDocument(); @@ -303,9 +304,14 @@ tinyxml2::XMLDocument* exportURDF(const ModelInterface &model) return doc; } +tinyxml2::XMLDocument* exportURDF(const ModelInterface &model) +{ + return exportURDFInternal(model); +} + tinyxml2::XMLDocument* exportURDF(ModelInterfaceSharedPtr &model) { - return exportURDF(*model); + return exportURDFInternal(*model); } diff --git a/urdf_parser/src/pose.cpp b/urdf_parser/src/pose.cpp index 87479f39..ce6c92b2 100644 --- a/urdf_parser/src/pose.cpp +++ b/urdf_parser/src/pose.cpp @@ -43,6 +43,8 @@ #include #include +#include "./pose.hpp" + namespace urdf_export_helpers { std::string values2str(unsigned int count, const double *values, double (*conv)(double)) @@ -87,7 +89,7 @@ std::string values2str(double d) namespace urdf{ -bool parsePose(Pose &pose, tinyxml2::XMLElement* xml) +bool parsePoseInternal(Pose &pose, tinyxml2::XMLElement* xml) { pose.clear(); if (xml) @@ -119,6 +121,11 @@ bool parsePose(Pose &pose, tinyxml2::XMLElement* xml) return true; } +bool parsePose(Pose &pose, tinyxml2::XMLElement* xml) +{ + return parsePoseInternal(pose, xml); +} + bool exportPose(Pose &pose, tinyxml2::XMLElement* xml) { tinyxml2::XMLElement* origin = xml->GetDocument()->NewElement("origin"); diff --git a/urdf_parser/src/pose.hpp b/urdf_parser/src/pose.hpp new file mode 100644 index 00000000..cadc1832 --- /dev/null +++ b/urdf_parser/src/pose.hpp @@ -0,0 +1,44 @@ +/********************************************************************* +* Software License Agreement (BSD License) +* +* Copyright (c) 2008, Willow Garage, Inc. +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* * Neither the name of the Willow Garage nor the names of its +* contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +* POSSIBILITY OF SUCH DAMAGE. +*********************************************************************/ + +/* Author: Wim Meeussen, John Hsu */ + +#include +#include + +namespace urdf { + +URDFDOM_DLLAPI bool parsePoseInternal(Pose &pose, tinyxml2::XMLElement* xml); + +} diff --git a/urdf_parser/src/urdf_sensor.cpp b/urdf_parser/src/urdf_sensor.cpp index 8332920c..b9ac592b 100644 --- a/urdf_parser/src/urdf_sensor.cpp +++ b/urdf_parser/src/urdf_sensor.cpp @@ -47,11 +47,11 @@ #include -namespace urdf{ +#include "./pose.hpp" -bool parsePose(Pose &pose, tinyxml2::XMLElement* xml); +namespace urdf{ -bool parseCamera(Camera &camera, tinyxml2::XMLElement* config) +bool parseCameraInternal(Camera &camera, tinyxml2::XMLElement* config) { camera.clear(); camera.type = VisualSensor::CAMERA; @@ -173,7 +173,12 @@ bool parseCamera(Camera &camera, tinyxml2::XMLElement* config) return true; } -bool parseRay(Ray &ray, tinyxml2::XMLElement* config) +bool parseCamera(Camera &camera, tinyxml2::XMLElement* config) +{ + return parseCameraInternal(camera, config); +} + +bool parseRayInternal(Ray &ray, tinyxml2::XMLElement* config) { ray.clear(); ray.type = VisualSensor::RAY; @@ -292,6 +297,11 @@ bool parseRay(Ray &ray, tinyxml2::XMLElement* config) return false; } +bool parseRay(Ray &ray, tinyxml2::XMLElement* config) +{ + return parseRayInternal(ray, config); +} + VisualSensorSharedPtr parseVisualSensor(tinyxml2::XMLElement *g) { VisualSensorSharedPtr visual_sensor; @@ -303,7 +313,7 @@ VisualSensorSharedPtr parseVisualSensor(tinyxml2::XMLElement *g) Camera *camera = new Camera(); visual_sensor.reset(camera); sensor_xml = g->FirstChildElement("camera"); - if (!parseCamera(*camera, sensor_xml)) + if (!parseCameraInternal(*camera, sensor_xml)) visual_sensor.reset(); } else if (g->FirstChildElement("ray")) @@ -311,7 +321,7 @@ VisualSensorSharedPtr parseVisualSensor(tinyxml2::XMLElement *g) Ray *ray = new Ray(); visual_sensor.reset(ray); sensor_xml = g->FirstChildElement("ray"); - if (!parseRay(*ray, sensor_xml)) + if (!parseRayInternal(*ray, sensor_xml)) visual_sensor.reset(); } else @@ -347,7 +357,7 @@ bool parseSensor(Sensor &sensor, tinyxml2::XMLElement* config) tinyxml2::XMLElement *o = config->FirstChildElement("origin"); if (o) { - if (!parsePose(sensor.origin, o)) + if (!parsePoseInternal(sensor.origin, o)) return false; } From 6a5a7e6fc385a414440ab575b9958fa9416e1fa9 Mon Sep 17 00:00:00 2001 From: Chris Lalancette Date: Tue, 26 Dec 2023 18:46:47 +0000 Subject: [PATCH 21/23] 4.0.0 Signed-off-by: Chris Lalancette Signed-off-by: harleylara --- CMakeLists.txt | 4 ++-- package.xml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ae031354..b5330130 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ cmake_minimum_required( VERSION 3.5 FATAL_ERROR ) project (urdfdom CXX C) -set (URDF_MAJOR_VERSION 3) +set (URDF_MAJOR_VERSION 4) set (URDF_MINOR_VERSION 0) -set (URDF_PATCH_VERSION 2) +set (URDF_PATCH_VERSION 0) set (URDF_VERSION ${URDF_MAJOR_VERSION}.${URDF_MINOR_VERSION}.${URDF_PATCH_VERSION}) set (URDF_MAJOR_MINOR_VERSION ${URDF_MAJOR_VERSION}.${URDF_MINOR_VERSION}) diff --git a/package.xml b/package.xml index e34b5333..e2455b46 100644 --- a/package.xml +++ b/package.xml @@ -1,7 +1,7 @@ urdfdom - 3.1.1 + 4.0.0 A library to access URDFs using the DOM model. Chris Lalancette @@ -20,7 +20,7 @@ tinyxml2 tinyxml2_vendor urdfdom_headers - + cmake console_bridge_vendor @@ -30,7 +30,7 @@ urdfdom_headers python3 - + cmake From 7455f502b7c41face94be24b682639e4abe223f8 Mon Sep 17 00:00:00 2001 From: harleylara Date: Thu, 15 Feb 2024 11:24:10 +0100 Subject: [PATCH 22/23] add robot and link Signed-off-by: harleylara --- specification/README.md | 8 +- specification/joint.md | 132 +++++++++++++++++++ specification/link.md | 278 +++++++++++++++++++++++++++------------- specification/robot.md | 27 ++++ xsd/urdf.xsd | 14 +- 5 files changed, 368 insertions(+), 91 deletions(-) create mode 100644 specification/joint.md create mode 100644 specification/robot.md diff --git a/specification/README.md b/specification/README.md index d3e6ad25..303e81a0 100644 --- a/specification/README.md +++ b/specification/README.md @@ -12,7 +12,7 @@ The description of a robot consists of a set of [link elements](./link.md), and ~~~xml - + ... ... @@ -26,8 +26,14 @@ The description of a robot consists of a set of [link elements](./link.md), and You can see that the root element of the URDF format is a `` element. +## `` element + +The robot element describes all properties of a robot. For details on the root description format, check out the [robot elements](./robot.md) page. + ## `` element + For details on the link description format, check out the [link elements](./link.md) page. ## `` element + For details on the joint description format, check out the [joint elements](./joint.md) page. diff --git a/specification/joint.md b/specification/joint.md new file mode 100644 index 00000000..a6fd4fe7 --- /dev/null +++ b/specification/joint.md @@ -0,0 +1,132 @@ +# `` element + +The joint element describes the kinematics and dynamics of the joint and also specifies the [safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits) of the joint. + +![example-joint](./joint.png) + +## Attributes + +| attribute | type | use | default value | description | +| --------- | ----------- | -------- | ------------- | ------------------------------------------------------------------------------ | +| `name` | `string` | required | NA | Specifies a unique name of the join. | +| `type` | `JointType` | required | NA | Specifies the type of joint, see "Type: `JointType`" section for more details. | + +### Type: `JointType` + +where type can be one of the following: +- `revolute`: a hinge joint that rotates along the axis and has a limited range specified by the upper and lower limits. +- `continuous`: a continuous hinge joint that rotates around the axis and has no upper and lower limits. +- `prismatic`: a sliding joint that slides along the axis, and has a limited range specified by the upper and lower limits. +- `fixed`: this is not really a joint because it cannot move. All degrees of freedom are locked. This type of joint does not require the ``, ``, ``, `` or ``. +- `floating`: this joint allows motion for all 6 degrees of freedom. +- `planar`: this joint allows motion in a plane perpendicular to the axis. + +## Elements + +The joint element has following elements: + +| element | use | +| ------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| [``](#parent) | required | +| [``](#child) | required | +| [``](#origin) | optional: defaults to identity if not specified | +| [``](#axis) | optional: defaults to (1,0,0) | +| [``](#calibration) | optional | +| [``](#dynamics) | optional | +| [``](#limit) | required only for revolute and prismatic joint | +| [``](#mimic) | optional (New with ROS Groovy. See [issue](https://github.com/ros/robot_state_publisher/issues/1)) | +| [``](#safety_controller) | optional | + +### `` + +This is the transform from the parent link to the child link. The joint is located at the origin of the child link, as shown in the figure above. + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `xyz` | `string` | optional | zero vector | Represents the x, y, z offset. All positions are specified in metres. | +| `rpy` | `string` | optional | zero vector | Represents the rotation around fixed axis: first roll around x, then pitch around y and finally yaw around z. All angles are specified in radians. | + +### `` + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | --------------------------------------------------------------------------------- | +| `link` | `string` | required | NA | The name of the link that is the parent of this link in the robot tree structure. | + +### `` + +| attribute | type | use | default value | description | +| --------- | ------ | -------- | ------------- | -------------------------------------------- | +| `link` | `string` | required | NA | The name of the link that is the child link. | + +### `` + +The joint axis specified in the joint frame. This is the axis of rotation for revolute joints, the axis of translation for prismatic joints, and the surface normal for planar joints. The axis is specified in the joint frame of reference. Fixed and floating joints do not use the axis field. + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | --------------------------------------------------------------------------------- | +| `xyz` | `string` | required | NA | Represents the (x, y, z) components of a vector. The vector should be normalized. | + +### `` + +The reference positions of the joint, used to calibrate the absolute position of the joint. + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------- | +| `rising` | `double` | optional | ??? | When the joint moves in a positive direction, this reference position will trigger a rising edge. | +| `falling` | `double` | optional | ??? | When the joint moves in a positive direction, this reference position will trigger a falling edge. | + +### `` + +An element specifying physical properties of the joint. These values are used to specify modeling properties of the joint, particularly useful for simulation. + +| attribute | type | use | default value | description | +| ---------- | -------- | -------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `damping` | `double` | optional | defaults to 0 | The physical damping value of the joint (in newton-seconds per metre [N∙s/m] for prismatic joints, in newton-metre-seconds per radian [N∙m∙s/rad] for revolute joints). | +| `friction` | `double` | optional | defaults to 0 | The physical static friction value of the joint (in newtons [N] for prismatic joints, in newton-metres [N∙m] for revolute joints). | + +### `` + +(required only for revolute and prismatic joint) + +| attribute | type | use | default value | description | +| ---------- | -------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `effort` | `double` | required | NA | An attribute for enforcing the maximum joint effort (\|applied effort\| < \|effort\|). See safety limits. | +| `velocity` | `double` | required | NA | An attribute for enforcing the maximum joint velocity (in radians per second [rad/s] for revolute joints, in metres per second [m/s] for prismatic joints). [See safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits). | +| `lower` | `double` | optional | defaults to 0 | An attribute specifying the lower joint limit (in radians for revolute joints, in metres for prismatic joints). Omit if joint is continuous. | +| `upper` | `double` | optional | defaults to 0 | An attribute specifying the upper joint limit (in radians for revolute joints, in metres for prismatic joints). Omit if joint is continuous. | + +### `` + +(optional) (New with ROS Groovy. See issue) + +This tag is used to specify that the defined joint mimics another existing joint. The value of this joint can be computed as value = multiplier * other_joint_value + offset. + +| attribute | type | use | default value | description | +| ------------ | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------- | +| `joint` | `string` | required | NA | This specifies the name of the joint to mimic. | +| `multiplier` | `double` | optional | defaults to 1 | Specifies the multiplicative factor in the formula above. | +| `offset` | `double` | optional | defaults to 0 | Specifies the offset to add in the formula above. Defaults to 0 (radians for revolute joints, meters for prismatic joints) | + +### `` + +| attribute | type | use | default value | description | +| ------------------ | -------- | -------- | ------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `k_velocity` | `double` | required | NA | An attribute specifying the relation between effort and velocity limits. See See safety limits for more details. | +| `soft_lower_limit` | `double` | optional | defaults to 0 | An attribute specifying the lower joint boundary where the safety controller starts limiting the position of the joint. This limit needs to be larger than the lower joint limit (see above). See [safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits) for more details. | +| `soft_upper_limit` | `double` | optional | defaults to 0 | An attribute specifying the upper joint boundary where the safety controller starts limiting the position of the joint. This limit needs to be smaller than the upper joint limit (see above). See [safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits) for more details. | +| `k_position` | `double` | optional | defaults to 0 | An attribute specifying the relation between position and velocity limits. See [safety limits](http://wiki.ros.org/pr2_controller_manager/safety_limits) for more details. | + +## Example + +```xml + + + + + + + + + + +``` \ No newline at end of file diff --git a/specification/link.md b/specification/link.md index 97bd17ed..8df5f94a 100644 --- a/specification/link.md +++ b/specification/link.md @@ -1,104 +1,174 @@ -# Link - -## `` element +# `` element The link element describes a rigid body with an inertia, visual features, and collision properties. -Here is an example of a link element: - -~~~xml - - - - - - - - - - - - - - - - - - - - - - - - -~~~ Inertial ## Attributes - * **`name`** *(required)* - * The name of the link itself. + +| `` attr | type | use | default value | description | +| ------------- | -------- | -------- | ------------- | ---------------------------- | +| `name` | `string` | required | NA | The name of the link itself. | ## Elements - * **``** *(optional: defaults to a zero mass and zero inertia if not specified)* - * The link’s mass, position of its center of mass, and its central inertia properties. - * **``** *(optional: defaults to identity if not specified)* - * This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. - * **`xyz`** *(optional: defaults to zero vector)* - * Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as **x L̂x + y L̂y + z L̂z**, where **L̂x, L̂y, L̂z** are link-frame L's orthogonal unit vectors. - * **`rpy`** *(optional: defaults to identity if not specified)* - * Represents the orientation of C's unit vectors **Ĉx, Ĉy, Ĉz** relative to link-frame L as a sequence of Euler rotations (r p y) in radians. Note: **Ĉx, Ĉy, Ĉz** do not need to be aligned with the link’s principal axes of inertia. - * **``** - * The mass of the link is represented by the **`value`** attribute of this element - * **``** - * This link's moments of inertia **ixx, iyy, izz** and products of inertia **ixy, ixz, iyz** about Co (the link’s center of mass) for the unit vectors **Ĉx, Ĉy, Ĉz** fixed in the center-of-mass frame C. Note: the orientation of **Ĉx, Ĉy, Ĉz** relative to **L̂x, L̂y, L̂z** is specified by the rpy values in the tag. The attributes **ixx, ixy, ixz, iyy, iyz, izz** for some primitive shapes are [here](https://en.wikipedia.org/wiki/ List_of_moments_of_inertia#List_of_3D_inertia_tensors). URDF assumes a negative product of inertia convention (for more info, see [these MathWorks docs](https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia. html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c) for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align **Ĉx, Ĉy, Ĉz** with principal inertia directions so that all the products of inertia are zero. - * **``** *(optional)* - * The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. - - * **name** *(optional)* - * Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. - - * **``** *(optional: defaults to identity if not specified)* - * The reference frame of the visual element with respect to the reference frame of the link. - * **`xyz`** *(optional: defaults to zero vector)* - * Represents the **x**, **y**, **z** offset. - * **rpy** *(optional: defaults to identity if not specified)* - * Represents the fixed axis roll, pitch and yaw angles in radians. - * **``** *(required)* - * The shape of the visual object. This can be *one* of the following: - * **``** - * **`size`** attribute contains the three side lengths of the box. The origin of the box is in its center. - * **``** - * Specify the **`radius`** and **`length`**. The origin of the cylinder is in its center. Cylinder Coordinates - * **``** - * Specify the **`radius`**. The origin of the sphere is in its center. - * **``** - * A trimesh element specified by a **`filename`**, and an optional **`scale`** that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with **`package:///`** to make the path to the mesh file relative to the package ``. - * **``** *(optional)* - * The material of the visual element. It is allowed to specify a material element outside of the 'link' object, in the top level 'robot' element. From within a link element you can then reference the material by name. - * **`name`** name of the material - * **``** *(optional)* - * **`rgba`** The color of a material specified by set of four numbers representing red/green/blue/alpha, each in the range of [0,1]. - * **``** *(optional)* - * The texture of a material is specified by a **`filename`** + +The link element has following child elements: + +| `` element | use | description | +| --------------------------- | -------------------------------------------------------------------- | ----------------------------------- | +| [``](#visual) | optional | The visual properties of the link. | +| [``](#collision) | optional | The collision properties of a link. | +| [``](#inertial) | optional: defaults to a zero mass and zero inertial if not specified | The visual properties of the link. | + +### `` + +The visual properties of the link. This element specifies the shape of the object (box, cylinder, etc.) for visualization purposes. + +> [!NOTE] +> multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the visual representation of the link. + +| `` attr | type | use | default value | description | +| --------------- | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `name` | `string` | optional | none | Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. | + +Child elements of a `visual` element: +| `` element | use | description | +| -------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------ | +| [``](#visual-geometry) | required | The shape of the visual object. | +| [``](#visual-origin) | optional: defaults to identity if not specified | The reference frame of the visual element with respect to the reference frame of the link. | +| [``](#visual-material) | optional | The material of the visual element. | + +#### visual: `` + +The reference frame of the visual element with respect to the reference frame of the link. + +| `` attr | type | use | default value | description | +| --------------- | -------- | -------- | ------------------------------------- | ---------------------------------------------------------------- | +| `xyz` | `string` | optional | defaults to zero vector | Represents the **x**, **y**, **z** offset. | +| `rpy` | `string` | optional | defaults to identity if not specified | Represents the fixed axis roll, pitch and yaw angles in radians. | + +#### visual: `` + +The shape of the visual object. + +This element **may contain one** of the following elements: +| `` element | use | description | +| ---------------------------------- | -------- | --------------------------- | +| [``](#geometry-box) | optional | Defines a cubic mesh. | +| [``](#geometry-cylinder) | optional | Defines a cylindrical mesh. | +| [``](#geometry-sphere) | optional | Defines a spherical mesh. | +| [``](#geometry-mesh) | optional | Defines a custom mesh. | + +##### geometry: `` + +| `` attr | type | use | default value | description | +| ------------ | -------- | -------- | ------------- | ------------------------------------------------------------------------------------------------ | +| `size` | `string` | optional | zero vector | The three side lengths of the box in the form `"x y z"`. The origin of the box is in its center. | + +##### geometry: `` + +The origin of the cylinder is in its center. Cylinder Coordinates + +| `` attr | type | use | default value | description | +| ----------------- | -------- | -------- | ---------------- | ----------- | +| `radius` | `double` | required | Cylinder radius. | +| `length` | `double` | required | Cylinder lenght. | + +##### geometry: `` + +The origin of the sphere is in its center. + +| `` attr | type | use | default value | description | +| --------------- | -------- | -------- | ------------- | -------------- | +| `radius` | `double` | required | NA | Sphere radius. | + +##### geometry: `` + +A trimesh element specified by a **`filename`**, and an optional **`scale`** that scales the mesh's axis-aligned-bounding-box. Any geometry format is acceptable but specific application compatibility is dependent on implementation. The recommended format for best texture and color support is Collada .dae files. The mesh file is not transferred between machines referencing the same model. It must be a local file. Prefix the filename with **`package:///`** to make the path to the mesh file relative to the package ``. + +| `` attr | type | use | default value | description | +| ------------- | -------- | -------- | ------------- | ------------------------------------------------- | +| `filename` | `anyURI` | required | NA | Absolute path to the mesh file. | +| `scale` | `double` | optional | unit vector | Scale factor for the mesh in form `"x y z"` axis. | + +#### visual: `` + +The material of the visual element. It is allowed to specify a material element outside of the 'link' object, in the top level 'robot' element. From within a link element you can then reference the material by name. + +| `` attr | type | use | default value | description | +| ----------------- | -------- | -------- | ------------- | --------------------- | +| `name` | `string` | optional | none | Name of the material. | + +Child elements of a `material` element: +| `` element | use | description | +| -------------------------------- | -------- | ----------------------------------- | +| [``](#material-color) | optional | Defines the color of the material. | +| [``](#material-texture) | optional | Defines the texture of the material | + +##### material: `` + +| `` attr | type | use | default value | description | +| -------------- | -------- | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------ | +| `rgba` | `string` | optional | `"0 0 0 0"` | The color of a material specified by set of four numbers representing red/green/blue/alpha, each in the range of [0,1]. | + +##### material: `` + +| `` attr | type | use | default value | description | +| ---|---|----|----|----| +| `filename` | `anyURI` | required | NA | Path to rhe texture of a material. | + +### `` + +The link’s mass, position of its center of mass, and its central inertia properties. + +Child elements of a `` element: +| `` element | use | description | +| -------------------------------- | ----------------------------------------------- | -------------------------------------------------------------------------------- | +| [``](#inertial-origin) | optional: defaults to identity if not specified | This pose (translation, rotation) of the link’s center of mass w.r.t. link-frame | +| [``](#inertial-mass) | required | The mass of the link is represented by the value attribute of this element | +| [``](#inertial-inertia) | ??? | interia matrix, see [``](#inertial-inertia) element for more details. | + + - * **``** *(optional)* - * The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the collision representation of the link. +#### inertial: `` + +(optional: defaults to identity if not specified)* + +This pose (translation, rotation) describes the position and orientation of the link’s center of mass frame C relative to the link-frame L. + +| `` attr | type | use | default value | description | +| ----------------- | -------- | -------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `xyz` | `string` | optional | defaults to zero vector | Represents the position vector from Lo (the link-frame origin) to Co (the link’s center of mass) as **x L̂x + y L̂y + z L̂z**, where **L̂x, L̂y, L̂z** are link-frame L's orthogonal unit vectors. | +| `rpy` | `string` | optional | defaults to identity if not specified | Represents the orientation of C's unit vectors **Ĉx, Ĉy, Ĉz** relative to link-frame L as a sequence of Euler rotations (r p y) in radians. *Note*: **Ĉx, Ĉy, Ĉz** do not need to be aligned with the link’s principal axes of inertia. | + +#### inertial: `` + +The mass of the link is represented by the **`value`** attribute of this element. + +#### inertial: `` - * **`name`** *(optional)* - * Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. - * **``** *(optional: defaults to identity if not specified)* - * The reference frame of the collision element, relative to the reference frame of the link. - * **`xyz`** *(optional: defaults to zero vector)* - * Represents the **x**, **y**, **z** offset. - * **`rpy`** *(optional: defaults to identity if not specified)* - * Represents the fixed axis roll, pitch and yaw angles in radians. - * **``** - * See the geometry description in the above visual element. +This link's moments of inertia **ixx, iyy, izz** and products of inertia **ixy, ixz, iyz** about Co (the link’s center of mass) for the unit vectors **Ĉx, Ĉy, Ĉz** fixed in the center-of-mass frame C. Note: the orientation of **Ĉx, Ĉy, Ĉz** relative to **L̂x, L̂y, L̂z** is specified by the rpy values in the tag. The attributes **ixx, ixy, ixz, iyy, iyz, izz** for some primitive shapes are [here](https://en.wikipedia.org/wiki/List_of_moments_of_inertia#List_of_3D_inertia_tensors). URDF assumes a negative product of inertia convention (for more info, see [these MathWorks docs](https://www.mathworks.com/help/releases/R2021b/physmod/sm/ug/specify-custom-inertia.html#mw_b043ec69-835b-4ca9-8769-af2e6f1b190c) for working with CAD tools). The simplest way to avoid compatibility issues associated with the negative sign convention for product of inertia is to align **Ĉx, Ĉy, Ĉz** with principal inertia directions so that all the products of inertia are zero. + + +### `` -# Recommended Mesh Resolution - * For collision checking using the [[moveit| ROS motion planning]] packages, as few faces per link as possible are recommended for the collision meshes that you put into the URDF (ideally less than 1000). If possible, approximating the meshes with other primitives is encouraged. +The collision properties of a link. Note that this can be different from the visual properties of a link, for example, simpler collision models are often used to reduce computation time. **Note:** multiple instances of `` tags can exist for the same link. The union of the geometry they define forms the collision representation of the link. -# Multiple Collision Bodies +| `` attr | type | use | default value | description | +| ------------------ | -------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `name` | `string` | optional | none | Specifies a name for a part of a link's geometry. This is useful to be able to refer to specific bits of the geometry of a link. | + +Child elements of a `` element: +| `` element | use | description | +| --------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | +| `` | optional: same as the [``](#visual-geometry) element in the [``](#visual) element. | The reference frame of the collision element, relative to the reference frame of the link. | +| `` | optional: same as the [``](#visual-geometry) element in the [``](#visual) element. | See the geometry description in the above [``](#visual) element. | + +## Recommended Mesh Resolution + +For collision checking using the [[moveit| ROS motion planning]] packages, as few faces per link as possible are recommended for the collision meshes that you put into the URDF (ideally less than 1000). If possible, approximating the meshes with other primitives is encouraged. + +## Multiple Collision Bodies It was decided that URDFs should not support multiple groups of collision bodies, even though there are sometimes applications for this. The URDF is intended to only represent the actual robot's properties, and not collisions used for external things like controller collision checking. In a URDF, the elements should be as accurate as possible to the real robot, and the elements should still be a close approximation, albeit with far fewer triangles in the meshes. @@ -132,3 +202,33 @@ If you do need coarser-grain, over sized collision geometries for things like co A URDF will ignore these custom elements like "collision_checking", and your particular program can parse the XML itself to get this information. +## Example + +Here is an example of a link element: + +~~~xml + + + + + + + + + + + + + + + + + + + + + + + + +~~~ \ No newline at end of file diff --git a/specification/robot.md b/specification/robot.md new file mode 100644 index 00000000..c4338de7 --- /dev/null +++ b/specification/robot.md @@ -0,0 +1,27 @@ +# `` element + +The root element in a robot description file must be a `` element, with all other elements must be encapsulated within. + +## Attributes + +| `` attr | type | use | default value | description | +| -------------- | ------ | -------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | string | required | NA | The master file must have a *name* attribute. The *name* attribute is optional in included files. If the attribute *name* is specified in an additional included file, it must have the same value as in the master file. | +| `version` | string | optional | "1.0" | version of the urdf specification in `.` format. | + +## Elements + +| `` element | description | +| ------------------------------------- | -------------------------------------------------------------------- | +| [``](./link.md) | defines a link with its own frame. | +| [``](./joint.md) | mandatory joint frame definition. | +| [``](./transmission.md) | (PR2 specific). | +| [``](./gazebo.md) | [Gazebo](http://wiki.ros.org/gazebo_ros_pkgs) simulation extensions. | + +## Example + +```xml + + + +``` diff --git a/xsd/urdf.xsd b/xsd/urdf.xsd index ccebfb26..f94ff12d 100644 --- a/xsd/urdf.xsd +++ b/xsd/urdf.xsd @@ -13,6 +13,18 @@ xmlns="http://www.ros.org" elementFormDefault="qualified"> + + + + + + + + + + + + @@ -293,7 +305,7 @@ type="mimic" minOccurs="0" maxOccurs="1" /> - + From 384b855e886f4705a68480df63999949890d1d5a Mon Sep 17 00:00:00 2001 From: harleylara Date: Thu, 15 Feb 2024 14:04:49 +0100 Subject: [PATCH 23/23] add sensor and gazebo element Signed-off-by: harleylara --- specification/README.md | 14 +++-- specification/gazebo.md | 5 ++ specification/sensor.md | 111 ++++++++++++++++++++++++++++++++++++++++ xsd/urdf.xsd | 68 +++++++++++++++++++++++- 4 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 specification/gazebo.md create mode 100644 specification/sensor.md diff --git a/specification/README.md b/specification/README.md index 303e81a0..e192cb0f 100644 --- a/specification/README.md +++ b/specification/README.md @@ -28,12 +28,20 @@ You can see that the root element of the URDF format is a `` element. ## `` element -The robot element describes all properties of a robot. For details on the root description format, check out the [robot elements](./robot.md) page. +The `` element describes all properties of a robot. For details on the root description format, check out the [robot element](./robot.md) page. ## `` element -For details on the link description format, check out the [link elements](./link.md) page. +For details on the `` description format, check out the [link element](./link.md) page. ## `` element -For details on the joint description format, check out the [joint elements](./joint.md) page. +For details on the `` description format, check out the [joint element](./joint.md) page. + +## `` element + +For details on the `` description format, check out the [gazebo element](./gazebo.md) page. + +## `` element + +For details on the `` description format, check out the [sensor element](./sensor.md) page. \ No newline at end of file diff --git a/specification/gazebo.md b/specification/gazebo.md new file mode 100644 index 00000000..e8bdd9fe --- /dev/null +++ b/specification/gazebo.md @@ -0,0 +1,5 @@ +# `` element + +The gazebo element is an extension to the URDF robot description format, used for simulation purposes in the [Gazebo](https://gazebosim.org/) simulator. + +For full documentation of the Gazebo element, see [Using A URDF In Gazebo](http://gazebosim.org/tutorials?tut=ros_urdf&cat=connect_ros) (for Gazebo Classic) or [SDFormat extensions to URDF (the `` tag)](http://sdformat.org/tutorials?tut=sdformat_urdf_extensions&cat=specification&) (for new Gazebo). \ No newline at end of file diff --git a/specification/sensor.md b/specification/sensor.md new file mode 100644 index 00000000..71a3b920 --- /dev/null +++ b/specification/sensor.md @@ -0,0 +1,111 @@ +# `` element + +>[!WARNING] +> The sensor element has been implemented in the URDF Dom but has never really been used in application. This is a project that was dropped anyone is encouraged to pick it up and extend it to sensor hardware applications. Please contribute! + +The sensor element describes basic properties of a visual sensor (i.e. camera / ray sensor). + +Here is an example of a camera sensor element: +```xml + + + + + + + +``` + +And below is an example of a laser scan (ray) sensor element: + +```xml + + + + + + + + +``` + +## Attributes + +| attribute | type | use | default value | description | +| ------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------- | +| `name` | `string` | required | NA | The name of the sensor link | +| `update_rate` | `double` | optional | The frequency at which the sensor data is generated in `hz`. If left unspecified, the sensor will generate data every cycle. | + +## Elements + +| element | use | description | +| ---------------------- | -------- | -------------------------------------------------------------------------------------------- | +| [``](#origin)` | optional | This is the pose of the sensor optical frame, relative to the sensor parent reference frame. | +| [``](#camaera) | optional | Camera sensor definition. | +| [``](#ray) | optional | Laser sensor definition. | + +### `` + + +| attribute | type | use | default value | description | +| --------- | -------- | -------- | ------------- | ------------------------------------------------------- | +| `link` | `string` | required | NA | The name of the parent link this sensor is attached to. | + +### `` + +| attribute | type | use | default value | description | +| `xyz` | `string` | optional | zero vector | Represents the offset with respect to the parent frame. | +| `rpy` | `string` | optional | zero vector | Represents the fixed axis roll, pitch and yaw angles in radians. | + +### `` + +The `` element has following child elements: +| element | use | description | +| -------------------------- | -------- | ----------------------------- | +| [``](#camera-image) | required | Defines the image parameters. | + +#### camera: `` + +| attribute | type | use | default value | description | +| --------- | -------------- | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `width` | `unsigned int` | required | NA | Width of the camera in `pixels`. | +| `height` | `unsigned int` | required | NA | Height of the camera in `pixels`. | +| `format` | `string` | required | NA | Can be any of the strings defined in [image_encodings.h insdie sensor_msgs](https://code.ros.org/trac/ros-pkg/browser/stacks/common_msgs/trunk/sensor_msgs/include/sensor_msgs/image_encodings.h). | +| `hfov` | `double` | required | NA | Horizontal field of view of the camera in `radians`. | +| `near` | `double` | required | NA | Near clip distance of the camera in `meters`. | +| `far` | `double` | required | NA | Far clip distance of the camera in `meters`. This needs to be greater or equal to near clip. | + +### `` + +The `` element has following child elements: +| element | use | description | +| -------------- | -------- | ----------------------------------------------- | +| `` | optional | Defines the horizontal parameters of the laser. | +| `` | optional | Defines the vertical parameters of the laser. | + +#### ray: `` + +| attribute | type | use | default value | description | +| ------------ | -------------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `samples` | `unsigned int` | optional | 1 | The number of simulated rays to generate per complete laser sweep cycle. | +| `resolution` | `unsigned int` | optional | 1 | This number is multiplied by samples to determine the number of range data points returned. If resolution is less than one, range data is interpolated. If resolution is greater than one, range data is averaged. | +| `min_angle` | `double` | optional | Minimun angle in `radians`. | +| `max_angle` | `double` | optional | Maximum angle in `radian`. Must be greater or equal to `min_angle`. | + +#### ray: `` + +| attribute | type | use | default value | description | +| ------------ | -------------- | -------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `samples` | `unsigned int` | optional | 1 | The number of simulated rays to generate per complete laser sweep cycle. | +| `resolution` | `unsigned int` | optional | 1 | This number is multiplied by samples to determine the number of range data points returned. If resolution is less than one, range data is interpolated. If resolution is greater than one, range data is averaged. | +| `min_angle` | `double` | optional | Minimun angle in `radians`. | +| `max_angle` | `double` | optional | Maximum angle in `radian`. Must be greater or equal to `min_angle`. | + +## Recommended Camera or Ray Resolution + +In simulation, large sensors will slow down overall performance. Depending on update rates required, it is recommended to keep the camera or ray resolution and update rates as low as possible. + +## Proposal for New Type of Sensor + +TBD \ No newline at end of file diff --git a/xsd/urdf.xsd b/xsd/urdf.xsd index f94ff12d..130b64bd 100644 --- a/xsd/urdf.xsd +++ b/xsd/urdf.xsd @@ -154,7 +154,6 @@ - @@ -282,6 +281,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -326,6 +386,12 @@ type="transmission" minOccurs="0" maxOccurs="unbounded" /> + + + +