Skip to content

Commit c83c375

Browse files
committed
Refactor sensor parsing
- parse sensor-specific content with a SensorParser (extension point) - implemented parseCamera() and parseRay() as SensorParsers (in visual_sensor_parsers.*) - added unittest test_sensor_parsing
1 parent d054150 commit c83c375

File tree

8 files changed

+398
-137
lines changed

8 files changed

+398
-137
lines changed

urdf_parser/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ add_urdfdom_library(
5858
LIBNAME
5959
urdfdom_sensor
6060
SOURCES
61-
src/urdf_sensor.cpp
61+
src/sensor_parser.cpp
62+
src/visual_sensor_parsers.cpp
6263
LINK
6364
urdfdom_model)
6465

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*********************************************************************
2+
* Software License Agreement (BSD License)
3+
*
4+
* Copyright (c) 2016, Bielefeld University
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions
9+
* are met:
10+
*
11+
* * Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
* * Redistributions in binary form must reproduce the above
14+
* copyright notice, this list of conditions and the following
15+
* disclaimer in the documentation and/or other materials provided
16+
* with the distribution.
17+
* * Neither the name of Bielefeld University nor the names of its
18+
* contributors may be used to endorse or promote products derived
19+
* from this software without specific prior written permission.
20+
*
21+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32+
* POSSIBILITY OF SUCH DAMAGE.
33+
*********************************************************************/
34+
35+
/* Author: Robert Haschke */
36+
37+
#ifndef URDF_PARSER_URDF_SENSOR_PARSER_H
38+
#define URDF_PARSER_URDF_SENSOR_PARSER_H
39+
40+
#include <string>
41+
#include <map>
42+
#include <tinyxml.h>
43+
#include <urdf_sensor/types.h>
44+
45+
#include "exportdecl.h"
46+
47+
namespace urdf {
48+
49+
/// API for any custom SensorParser
50+
class URDFDOM_DLLAPI SensorParser {
51+
public:
52+
virtual ~SensorParser() = default;
53+
virtual SensorBaseSharedPtr parse(TiXmlElement &sensor_element) = 0;
54+
};
55+
URDF_TYPEDEF_CLASS_POINTER(SensorParser);
56+
57+
/// map from sensor name to Sensor instance
58+
using SensorMap = std::map<std::string, SensorSharedPtr>;
59+
/// map from sensor type to SensorParser instance
60+
using SensorParserMap = std::map<std::string, SensorParserSharedPtr>;
61+
62+
/** parse <sensor> tags in URDF document for which a parser exists in SensorParserMap */
63+
URDFDOM_DLLAPI SensorMap parseSensors(TiXmlDocument &urdf, const SensorParserMap &parsers);
64+
65+
/** convienency function to fetch a sensor with given name and type from the map */
66+
template <typename T>
67+
URDFDOM_DLLAPI std::shared_ptr<T> getSensor(const std::string &name, const SensorMap &sensors) {
68+
SensorMap::const_iterator s = sensors.find(name);
69+
if (s == sensors.end()) return std::shared_ptr<T>();
70+
else return std::dynamic_pointer_cast<T>(s->second->sensor_);
71+
}
72+
73+
}
74+
75+
#endif

urdf_parser/include/urdf_parser/sensor.h renamed to urdf_parser/include/urdf_parser/visual_sensor_parsers.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,24 @@
3232
* POSSIBILITY OF SUCH DAMAGE.
3333
*********************************************************************/
3434

35-
#ifndef URDF_PARSER_SENSOR_H
36-
#define URDF_PARSER_SENSOR_H
35+
/* Author: Robert Haschke */
3736

38-
#include <urdf_sensor/sensor.h>
39-
#include <tinyxml.h>
37+
#ifndef URDF_PARSER_VISUAL_SENSOR_PARSERS_H
38+
#define URDF_PARSER_VISUAL_SENSOR_PARSERS_H
39+
40+
#include "sensor_parser.h"
4041

4142
namespace urdf {
4243

43-
bool parseSensor(Sensor &sensor, TiXmlElement* config);
44+
class URDFDOM_DLLAPI CameraParser : public SensorParser {
45+
public:
46+
SensorBaseSharedPtr parse(TiXmlElement &sensor_element);
47+
};
48+
49+
class URDFDOM_DLLAPI RayParser : public SensorParser {
50+
public:
51+
SensorBaseSharedPtr parse(TiXmlElement &sensor_element);
52+
};
4453

4554
}
4655

urdf_parser/src/sensor_parser.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*********************************************************************
2+
* Software License Agreement (BSD License)
3+
*
4+
* Copyright (c) 2008, Willow Garage, Inc.
5+
* All rights reserved.
6+
*
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions
9+
* are met:
10+
*
11+
* * Redistributions of source code must retain the above copyright
12+
* notice, this list of conditions and the following disclaimer.
13+
* * Redistributions in binary form must reproduce the above
14+
* copyright notice, this list of conditions and the following
15+
* disclaimer in the documentation and/or other materials provided
16+
* with the distribution.
17+
* * Neither the name of the Willow Garage nor the names of its
18+
* contributors may be used to endorse or promote products derived
19+
* from this software without specific prior written permission.
20+
*
21+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22+
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23+
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24+
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25+
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26+
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27+
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28+
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31+
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32+
* POSSIBILITY OF SUCH DAMAGE.
33+
*********************************************************************/
34+
35+
/* Author: John Hsu */
36+
37+
38+
#include "urdf_parser/sensor_parser.h"
39+
#include "urdf_parser/pose.h"
40+
#include <urdf_sensor/camera.h>
41+
#include <urdf_sensor/ray.h>
42+
43+
#include <boost/lexical_cast.hpp>
44+
#include <console_bridge/console.h>
45+
46+
namespace urdf {
47+
48+
SensorBaseSharedPtr parseSensorBase(TiXmlElement *sensor_xml, const SensorParserMap &parsers)
49+
{
50+
// find first child element that is not <parent> or <origin>
51+
const char* sensor_type;
52+
TiXmlElement *sensor_base_xml = sensor_xml->FirstChildElement();
53+
while (sensor_base_xml) {
54+
sensor_type = sensor_base_xml->Value();
55+
if (strcmp(sensor_type, "parent") && strcmp(sensor_type, "origin"))
56+
break;
57+
sensor_base_xml = sensor_base_xml->NextSiblingElement();
58+
}
59+
60+
if (sensor_base_xml)
61+
{
62+
SensorParserMap::const_iterator parser = parsers.find(sensor_type);
63+
if (parser != parsers.end() && parser->second)
64+
{
65+
return parser->second->parse(*sensor_base_xml);
66+
}
67+
else
68+
{
69+
CONSOLE_BRIDGE_logDebug("Sensor type not handled: %s", sensor_type);
70+
}
71+
}
72+
else
73+
{
74+
CONSOLE_BRIDGE_logError("No child element defining the sensor.");
75+
}
76+
77+
return SensorBaseSharedPtr();
78+
}
79+
80+
81+
bool parseSensor(Sensor &sensor, TiXmlElement* config, const SensorParserMap &parsers)
82+
{
83+
sensor.clear();
84+
85+
const char *name_char = config->Attribute("name");
86+
if (!name_char)
87+
{
88+
CONSOLE_BRIDGE_logError("No name given for the sensor.");
89+
return false;
90+
}
91+
sensor.name_ = std::string(name_char);
92+
93+
// parse parent link name
94+
TiXmlElement *parent_xml = config->FirstChildElement("parent");
95+
const char *parent_link_name_char = parent_xml ? parent_xml->Attribute("link") : NULL;
96+
if (!parent_link_name_char)
97+
{
98+
CONSOLE_BRIDGE_logError("No parent link name given for the sensor.");
99+
return false;
100+
}
101+
sensor.parent_link_ = std::string(parent_link_name_char);
102+
103+
// parse origin
104+
TiXmlElement *o = config->FirstChildElement("origin");
105+
if (o)
106+
{
107+
if (!parsePose(sensor.origin_, o))
108+
return false;
109+
}
110+
111+
// parse sensor
112+
sensor.sensor_ = parseSensorBase(config, parsers);
113+
return static_cast<bool>(sensor.sensor_);
114+
}
115+
116+
URDFDOM_DLLAPI
117+
SensorMap parseSensors(TiXmlDocument &urdf_xml, const SensorParserMap &parsers)
118+
{
119+
TiXmlElement *robot_xml = urdf_xml.FirstChildElement("robot");
120+
if (!robot_xml) {
121+
CONSOLE_BRIDGE_logError("Could not find the 'robot' element in the URDF");
122+
}
123+
124+
SensorMap results;
125+
// Get all sensor elements
126+
for (TiXmlElement* sensor_xml = robot_xml->FirstChildElement("sensor");
127+
sensor_xml; sensor_xml = sensor_xml->NextSiblingElement("sensor"))
128+
{
129+
SensorSharedPtr sensor;
130+
sensor.reset(new Sensor);
131+
132+
if (parseSensor(*sensor, sensor_xml, parsers))
133+
{
134+
if (results.find(sensor->name_) != results.end())
135+
{
136+
CONSOLE_BRIDGE_logWarn("Sensor '%s' is not unique. Ignoring consecutive ones.", sensor->name_.c_str());
137+
}
138+
else
139+
{
140+
results.insert(make_pair(sensor->name_, sensor));
141+
CONSOLE_BRIDGE_logDebug("urdfdom: successfully added a new sensor '%s'", sensor->name_.c_str());
142+
}
143+
}
144+
else
145+
{
146+
CONSOLE_BRIDGE_logError("failed to parse sensor element");
147+
}
148+
}
149+
return results;
150+
}
151+
152+
}

0 commit comments

Comments
 (0)