Skip to content

Commit 2e891c2

Browse files
authored
urdf: fix sensor/light pose for links lumped by fixed joints (#1114)
When converting a fixed joint in a URDF file to SDFormat, by default the contents of the child link are merged into the parent link, but poses in gazebo extensions such as //gazebo/sensor/pose are not properly transformed (#378). This issue has already been fixed in newer branches by #525, so the test and that fix have been backported and refactored to reduce code duplication (about 30 lines removed from parser_urdf.cc) and also fix the treatment of //gazebo/light/pose. Fixes #378. Signed-off-by: Steve Peters <scpeters@openrobotics.org>
1 parent 3e76d92 commit 2e891c2

File tree

4 files changed

+446
-90
lines changed

4 files changed

+446
-90
lines changed

Migration.md

+9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@ forward programmatically.
1212
This document aims to contain similar information to those files
1313
but with improved human-readability..
1414

15+
## libsdformat 9.8.0 to 9.8.1
16+
17+
### Modifications
18+
19+
1. URDF parser now properly transforms poses for lights, projectors and sensors
20+
from gazebo extension tags that are moved to a new link during fixed joint
21+
reduction.
22+
+ [pull request 1114](https://github.com/osrf/sdformat/pull/1114)
23+
1524
## libsdformat 9.4 to 9.5
1625

1726
### Additions

src/parser_urdf.cc

+58-90
Original file line numberDiff line numberDiff line change
@@ -87,17 +87,12 @@ void InsertSDFExtensionJoint(TiXmlElement *_elem,
8787
/// option is set
8888
bool FixedJointShouldBeReduced(urdf::JointSharedPtr _jnt);
8989

90-
/// reduced fixed joints: apply transform reduction for ray sensors
90+
/// reduced fixed joints: apply transform reduction for named elements
9191
/// in extensions when doing fixed joint reduction
92-
void ReduceSDFExtensionSensorTransformReduction(
92+
void ReduceSDFExtensionElementTransformReduction(
9393
std::vector<TiXmlElementPtr>::iterator _blobIt,
94-
ignition::math::Pose3d _reductionTransform);
95-
96-
/// reduced fixed joints: apply transform reduction for projectors in
97-
/// extensions when doing fixed joint reduction
98-
void ReduceSDFExtensionProjectorTransformReduction(
99-
std::vector<TiXmlElementPtr>::iterator _blobIt,
100-
ignition::math::Pose3d _reductionTransform);
94+
const ignition::math::Pose3d &_reductionTransform,
95+
const std::string &_elementName);
10196

10297

10398
/// reduced fixed joints: apply transform reduction to extensions
@@ -400,8 +395,8 @@ void ReduceVisualToParent(urdf::LinkSharedPtr _parentLink,
400395
// collision elements of the child link into the parent link
401396
void ReduceFixedJoints(TiXmlElement *_root, urdf::LinkSharedPtr _link)
402397
{
403-
// if child is attached to self by fixed _link first go up the tree,
404-
// check it's children recursively
398+
// if child is attached to self by fixed joint first go up the tree,
399+
// check its children recursively
405400
for (unsigned int i = 0 ; i < _link->child_links.size() ; ++i)
406401
{
407402
if (FixedJointShouldBeReduced(_link->child_links[i]->parent_joint))
@@ -2453,8 +2448,7 @@ void ReduceSDFExtensionToParent(urdf::LinkSharedPtr _link)
24532448
for (std::vector<SDFExtensionPtr>::iterator ge = ext->second.begin();
24542449
ge != ext->second.end(); ++ge)
24552450
{
2456-
(*ge)->reductionTransform = TransformToParentFrame(
2457-
(*ge)->reductionTransform,
2451+
(*ge)->reductionTransform = CopyPose(
24582452
_link->parent_joint->parent_to_joint_origin_transform);
24592453
// for sensor and projector blocks only
24602454
ReduceSDFExtensionsTransform((*ge));
@@ -2545,11 +2539,12 @@ void ReduceSDFExtensionsTransform(SDFExtensionPtr _ge)
25452539
for (std::vector<TiXmlElementPtr>::iterator blobIt = _ge->blobs.begin();
25462540
blobIt != _ge->blobs.end(); ++blobIt)
25472541
{
2548-
/// @todo make sure we are not missing any additional transform reductions
2549-
ReduceSDFExtensionSensorTransformReduction(blobIt,
2550-
_ge->reductionTransform);
2551-
ReduceSDFExtensionProjectorTransformReduction(blobIt,
2552-
_ge->reductionTransform);
2542+
ReduceSDFExtensionElementTransformReduction(
2543+
blobIt, _ge->reductionTransform, "light");
2544+
ReduceSDFExtensionElementTransformReduction(
2545+
blobIt, _ge->reductionTransform, "projector");
2546+
ReduceSDFExtensionElementTransformReduction(
2547+
blobIt, _ge->reductionTransform, "sensor");
25532548
}
25542549
}
25552550

@@ -3282,12 +3277,13 @@ bool FixedJointShouldBeReduced(urdf::JointSharedPtr _jnt)
32823277
}
32833278

32843279
////////////////////////////////////////////////////////////////////////////////
3285-
void ReduceSDFExtensionSensorTransformReduction(
3280+
void ReduceSDFExtensionElementTransformReduction(
32863281
std::vector<TiXmlElementPtr>::iterator _blobIt,
3287-
ignition::math::Pose3d _reductionTransform)
3282+
const ignition::math::Pose3d &_reductionTransform,
3283+
const std::string &_elementName)
32883284
{
3289-
// overwrite <xyz> and <rpy> if they exist
3290-
if ((*_blobIt)->ValueStr() == "sensor")
3285+
auto element = *_blobIt;
3286+
if (element->ValueStr() == _elementName)
32913287
{
32923288
// parse it and add/replace the reduction transform
32933289
// find first instance of xyz and rpy, replace with reduction transform
@@ -3298,82 +3294,54 @@ void ReduceSDFExtensionSensorTransformReduction(
32983294
// {
32993295
// std::ostringstream streamIn;
33003296
// streamIn << *elIt;
3301-
// sdfdbg << " " << streamIn << "\n";
3297+
// sdfdbg << " " << streamIn.str() << "\n";
33023298
// }
33033299

3300+
auto pose {ignition::math::Pose3d::Zero};
33043301
{
3305-
TiXmlNode* oldPoseKey = (*_blobIt)->FirstChild("pose");
3306-
/// @todo: FIXME: we should read xyz, rpy and aggregate it to
3307-
/// reductionTransform instead of just throwing the info away.
3302+
std::string poseText = "0 0 0 0 0 0";
3303+
3304+
TiXmlNode* oldPoseKey = element->FirstChild("pose");
33083305
if (oldPoseKey)
33093306
{
3310-
(*_blobIt)->RemoveChild(oldPoseKey);
3311-
}
3312-
}
3313-
3314-
// convert reductionTransform to values
3315-
urdf::Vector3 reductionXyz(_reductionTransform.Pos().X(),
3316-
_reductionTransform.Pos().Y(),
3317-
_reductionTransform.Pos().Z());
3318-
urdf::Rotation reductionQ(_reductionTransform.Rot().X(),
3319-
_reductionTransform.Rot().Y(),
3320-
_reductionTransform.Rot().Z(),
3321-
_reductionTransform.Rot().W());
3322-
3323-
urdf::Vector3 reductionRpy;
3324-
reductionQ.getRPY(reductionRpy.x, reductionRpy.y, reductionRpy.z);
3325-
3326-
// output updated pose to text
3327-
std::ostringstream poseStream;
3328-
poseStream << reductionXyz.x << " " << reductionXyz.y
3329-
<< " " << reductionXyz.z << " " << reductionRpy.x
3330-
<< " " << reductionRpy.y << " " << reductionRpy.z;
3331-
TiXmlText* poseTxt = new TiXmlText(poseStream.str());
3332-
3333-
TiXmlElement* poseKey = new TiXmlElement("pose");
3334-
poseKey->LinkEndChild(poseTxt);
3335-
3336-
(*_blobIt)->LinkEndChild(poseKey);
3337-
}
3338-
}
3307+
const auto& poseElemXml = oldPoseKey->ToElement();
3308+
if (poseElemXml->Attribute("relative_to"))
3309+
{
3310+
return;
3311+
}
33393312

3340-
////////////////////////////////////////////////////////////////////////////////
3341-
void ReduceSDFExtensionProjectorTransformReduction(
3342-
std::vector<TiXmlElementPtr>::iterator _blobIt,
3343-
ignition::math::Pose3d _reductionTransform)
3344-
{
3345-
// overwrite <pose> (xyz/rpy) if it exists
3346-
if ((*_blobIt)->ValueStr() == "projector")
3347-
{
3348-
// parse it and add/replace the reduction transform
3349-
// find first instance of xyz and rpy, replace with reduction transform
3350-
//
3351-
// for (TiXmlNode* elIt = (*_blobIt)->FirstChild();
3352-
// elIt; elIt = elIt->NextSibling())
3353-
// {
3354-
// std::ostringstream streamIn;
3355-
// streamIn << *elIt;
3356-
// sdfdbg << " " << streamIn << "\n";
3357-
// }
3313+
if (poseElemXml->GetText())
3314+
{
3315+
poseText = poseElemXml->GetText();
3316+
}
33583317

3359-
// should read <pose>...</pose> and agregate reductionTransform
3360-
TiXmlNode* poseKey = (*_blobIt)->FirstChild("pose");
3361-
// read pose and save it
3318+
// delete the <pose> tag, we'll add a new one at the end
3319+
element->RemoveChild(oldPoseKey);
3320+
}
33623321

3363-
// remove the tag for now
3364-
if (poseKey)
3365-
{
3366-
(*_blobIt)->RemoveChild(poseKey);
3322+
// parse the 6-tuple text into math::Pose3d
3323+
std::stringstream ss;
3324+
ss.imbue(std::locale::classic());
3325+
ss << poseText;
3326+
ss >> pose;
3327+
if (ss.fail())
3328+
{
3329+
sdferr << "Could not parse <" << _elementName << "><pose>: ["
3330+
<< poseText << "]\n";
3331+
return;
3332+
}
33673333
}
33683334

3335+
pose = _reductionTransform * pose;
3336+
33693337
// convert reductionTransform to values
3370-
urdf::Vector3 reductionXyz(_reductionTransform.Pos().X(),
3371-
_reductionTransform.Pos().Y(),
3372-
_reductionTransform.Pos().Z());
3373-
urdf::Rotation reductionQ(_reductionTransform.Rot().X(),
3374-
_reductionTransform.Rot().Y(),
3375-
_reductionTransform.Rot().Z(),
3376-
_reductionTransform.Rot().W());
3338+
urdf::Vector3 reductionXyz(pose.Pos().X(),
3339+
pose.Pos().Y(),
3340+
pose.Pos().Z());
3341+
urdf::Rotation reductionQ(pose.Rot().X(),
3342+
pose.Rot().Y(),
3343+
pose.Rot().Z(),
3344+
pose.Rot().W());
33773345

33783346
urdf::Vector3 reductionRpy;
33793347
reductionQ.getRPY(reductionRpy.x, reductionRpy.y, reductionRpy.z);
@@ -3383,12 +3351,12 @@ void ReduceSDFExtensionProjectorTransformReduction(
33833351
poseStream << reductionXyz.x << " " << reductionXyz.y
33843352
<< " " << reductionXyz.z << " " << reductionRpy.x
33853353
<< " " << reductionRpy.y << " " << reductionRpy.z;
3386-
TiXmlText* poseTxt = new TiXmlText(poseStream.str());
3354+
TiXmlText* poseTxt = new TiXmlText(poseStream.str().c_str());
33873355

3388-
poseKey = new TiXmlElement("pose");
3356+
TiXmlElement* poseKey = new TiXmlElement("pose");
33893357
poseKey->LinkEndChild(poseTxt);
33903358

3391-
(*_blobIt)->LinkEndChild(poseKey);
3359+
element->LinkEndChild(poseKey);
33923360
}
33933361
}
33943362

0 commit comments

Comments
 (0)