Martin  Felis avatar Martin Felis committed 51aeb98

started to work on a URDF reader

Comments (0)

Files changed (26)

 OPTION (RBDL_ENABLE_LOGGING "Enable logging (warning: major impact on performance!)" OFF)
 OPTION (RBDL_USE_SIMPLE_MATH "Use slow math instead of the fast Eigen3 library (faster compilation)" OFF)
 OPTION (RBDL_STORE_VERSION "Enable storing of version information in the library (requires build from valid repository)" OFF)
-OPTION (BUILD_ADDON_XMLREADER "Build the (experimental) xml reader" OFF)
+OPTION (BUILD_ADDON_URDFREADER "Build the (experimental) urdf reader" OFF)
 OPTION (BUILD_ADDON_BENCHMARK "Build the benchmarking tool" OFF)
 
 SET ( RBDL_SOURCES 
 
 ADD_LIBRARY ( rbdl SHARED ${RBDL_SOURCES} )
 
-IF (BUILD_ADDON_XMLREADER)
-  ADD_SUBDIRECTORY ( addons/xmlreader )
-ENDIF (BUILD_ADDON_XMLREADER)
+IF (BUILD_ADDON_URDFREADER)
+  ADD_SUBDIRECTORY ( addons/urdfreader )
+ENDIF (BUILD_ADDON_URDFREADER)
 
 IF (BUILD_ADDON_BENCHMARK)
   ADD_SUBDIRECTORY ( addons/benchmark )

addons/urdfreader/CMakeLists.txt

+PROJECT (RBDL_ADDON_URDFREADER)
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+LIST( APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake )
+
+INCLUDE_DIRECTORIES ( 
+	${CMAKE_CURRENT_BINARY_DIR}/include/rbdl
+	${CMAKE_CURRENT_SOURCE_DIR}/tinyxml/
+)
+
+SET_TARGET_PROPERTIES ( ${PROJECT_EXECUTABLES} PROPERTIES
+		LINKER_LANGUAGE CXX
+	)
+
+# Perform the proper linking
+SET (CMAKE_SKIP_BUILD_RPATH FALSE)
+SET (CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
+SET (CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
+SET (CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
+
+# Options
+SET ( URDFREADER_SOURCES 
+	rbdl_urdfreader.cc
+	tinyxml/tinystr.cpp
+	tinyxml/tinyxml.cpp
+	tinyxml/tinyxmlerror.cpp
+	tinyxml/tinyxmlparser.cpp
+	)
+
+ADD_LIBRARY ( rbdl_urdfreader SHARED ${URDFREADER_SOURCES} )
+
+ADD_DEFINITIONS (-DTIXML_USE_STL)
+
+IF (BUILD_STATIC)
+  ADD_LIBRARY ( rbdl_urdfreader-static STATIC ${RBDL_SOURCES} )
+  SET_TARGET_PROPERTIES ( rbdl_urdfreader-static PROPERTIES PREFIX "lib")
+  SET_TARGET_PROPERTIES ( rbdl_urdfreader-static PROPERTIES OUTPUT_NAME "rbdl_urdfreader")
+
+	INSTALL (TARGETS rbdl_urdfreader-static
+	  LIBRARY DESTINATION lib
+  	ARCHIVE DESTINATION lib
+	)
+ENDIF (BUILD_STATIC)
+
+ADD_EXECUTABLE (rbdl_urdf_test rbdl_urdf_test.cc)
+
+TARGET_LINK_LIBRARIES (rbdl_urdf_test
+	rbdl_urdfreader
+	)
+
+# Installing
+INSTALL (TARGETS rbdl_urdfreader
+	LIBRARY DESTINATION lib
+	ARCHIVE DESTINATION lib
+	)
+
+FILE ( GLOB headers 
+	"${CMAKE_CURRENT_SOURCE_DIR}/*.h"
+	)
+
+INSTALL ( FILES ${headers} DESTINATION include/rbdl/addons/urdfreader )

addons/urdfreader/rbdl_urdf_test.cc

+#include "rbdl.h"
+#include "rbdl_urdfreader.h"
+
+#include <iostream>
+
+using namespace std;
+
+int main (int argc, char *argv[]) {
+	if (argc != 2) {
+		cerr << "Usage: " << argv[0] << " <robot.urdf>" << endl;
+		return -1;
+	}
+
+	RigidBodyDynamics::Model model;
+	if (!RigidBodyDynamics::Addons::read_urdf_model(argv[1], &model, true)) {
+		cerr << "Loading of urdf model failed!" << endl;
+		return -1;
+	}
+
+	return 0;
+}

addons/urdfreader/rbdl_urdfreader.cc

+#include "rbdl.h"
+#include "rbdl_urdfreader.h"
+
+#include <assert.h>
+#include <iostream>
+#include <map>
+#include "tinyxml/tinyxml.h"
+
+using namespace std;
+
+struct URDFLink {
+	URDFLink () :
+		name (""),
+		origin_x (0.), origin_y (0.), origin_z (0.),
+		origin_rot_r (0.), origin_rot_p (0.), origin_rot_y (0.),
+		mass (0.),
+		ixx(0.), ixy(0.), ixz(0.), iyy(0.), iyz(0.), izz(0.)
+	{}
+
+	string name;
+	double origin_x, origin_y, origin_z;
+	double origin_rot_r, origin_rot_p, origin_rot_y;
+	double mass;
+	double ixx, ixy, ixz, iyy, iyz, izz;
+
+	void debug_print () {
+		cout << "link '" << name << "'" << endl;
+		cout << "  origin xyz = " << origin_x << " " << origin_y << " " << origin_z << endl;
+		cout << "  origin_rot rpy = " << origin_rot_r << " " << origin_rot_p << " " << origin_rot_y << endl;
+		cout << "  mass = " << mass << endl;
+		cout << "  ixx = " << ixx << " ixy = " <<  ixy << " ixz = " << ixz << " iyy = " << iyy << " iyz = " << iyz << " izz = " << izz << endl;
+	}
+};
+
+enum URDFJointType {
+	URDFJointTypeUnknown = 0,
+	URDFJointTypeRevolute,
+	URDFJointTypeContinuous,
+	URDFJointTypePrismatic,
+	URDFJointTypeFixed,
+	URDFJointTypeFloating,
+	URDFJointTypePlanar,
+	URDFJointTypeLast
+};
+
+struct URDFJoint {
+	URDFJoint() :
+		name (""),
+		type (URDFJointTypeUnknown),
+		origin_x (0.), origin_y (0.), origin_z (0.),
+		origin_rot_r (0.), origin_rot_p (0.), origin_rot_y (0.),
+		parent(""),
+		child ("")
+	{
+		axis[0] = 0.;
+		axis[1] = 0.;
+		axis[2] = 0.;
+	}
+
+	string name;
+	URDFJointType type;
+
+	string parent;
+	string child;
+
+	double origin_x, origin_y, origin_z;
+	double origin_rot_r, origin_rot_p, origin_rot_y;
+
+	double axis[3];
+
+	void debug_print () {
+		cout << "joint '" << name << "'" << endl;
+		cout << "  type = " << type << endl;
+		cout << "  parent = " << parent << endl;
+		cout << "  child = " << child << endl;
+		cout << "  origin xyz = " << origin_x << " " << origin_y << " " << origin_z << endl;
+		cout << "  origin_rot rpy = " << origin_rot_r << " " << origin_rot_p << " " << origin_rot_y << endl;
+		cout << "  axis = " << axis[0] << " " << axis[1] << " " << axis[2] << endl;
+	}};
+
+typedef std::map<std::string, URDFLink> LinkMap;
+typedef std::map<std::string, URDFJoint> JointMap;
+
+namespace RigidBodyDynamics {
+
+class Model;
+
+namespace Addons {
+
+bool parse_double_triple (string str, double out[3]) {
+	istringstream value_stream (str);
+
+	if ((value_stream >> out[0]).bad())
+		return false;
+
+	if ((value_stream >> out[1]).bad())
+		return false;
+
+	if ((value_stream >> out[2]).bad())
+		return false;
+
+	return true;
+}
+
+bool read_single_link (TiXmlHandle handle, URDFLink &link) {
+	string link_name;
+	handle.ToElement()->QueryStringAttribute("name", &link_name);
+	link.name = link_name;
+
+	// read origin xyz and rpy
+	TiXmlElement *origin_element = handle.FirstChild("inertial").FirstChild("origin").ToElement();
+	if (origin_element) {
+		string value_str;
+		origin_element->QueryStringAttribute("xyz", &value_str);
+
+		if (value_str.size() != 0) {
+			double values[3];
+			if (!parse_double_triple (value_str, values)) {
+				cerr << "Unable to parse origin xyz: '" << value_str << "'" << endl;
+				return false;
+			}
+			link.origin_x = values[0];
+			link.origin_y = values[1];
+			link.origin_z = values[2];
+		}
+		
+		origin_element->QueryStringAttribute("rpy", &value_str);
+
+		if (value_str.size() != 0) {
+			double values[3];
+			if (!parse_double_triple (value_str, values)) {
+				cerr << "Unable to parse origin rpy: '" << value_str << "'" << endl;
+				return false;
+			}
+			link.origin_rot_r = values[0];
+			link.origin_rot_p = values[1];
+			link.origin_rot_y = values[2];
+		}
+	}
+
+	// read mass
+	TiXmlElement *mass_element = handle.FirstChild("inertial").FirstChild("mass").ToElement();
+	if (mass_element) {
+		if (mass_element->QueryDoubleAttribute ("value", &(link.mass)) != TIXML_SUCCESS)
+			link.mass = 0.;
+	}
+
+	// and inertia
+	TiXmlElement *inertia_element = handle.FirstChild("inertial").FirstChild("inertia").ToElement();
+	if (inertia_element) {
+		if (inertia_element->QueryDoubleAttribute ("ixx", &(link.ixx)) != TIXML_SUCCESS) {
+			link.ixx = 0.;
+		}
+		if (inertia_element->QueryDoubleAttribute ("ixy", &(link.ixy)) != TIXML_SUCCESS) {
+			link.ixy = 0.;
+		}
+		if (inertia_element->QueryDoubleAttribute ("ixz", &(link.ixz)) != TIXML_SUCCESS) {
+			link.ixz = 0.;
+		}
+		if (inertia_element->QueryDoubleAttribute ("iyy", &(link.iyy)) != TIXML_SUCCESS) {
+			link.iyy = 0.;
+		}
+		if (inertia_element->QueryDoubleAttribute ("iyz", &(link.iyz)) != TIXML_SUCCESS) {
+			link.iyz = 0.;
+		}
+		if (inertia_element->QueryDoubleAttribute ("izz", &(link.izz)) != TIXML_SUCCESS) {
+			link.izz = 0.;
+		}
+	}
+
+	return true;
+}
+
+bool read_links (TiXmlDocument &doc, LinkMap &links) {
+	TiXmlHandle doc_handle (&doc);
+	TiXmlHandle link_handle = doc_handle.FirstChild("robot").FirstChild("link");
+
+	TiXmlElement *child = link_handle.ToElement();
+
+	while (child) {
+		if (child->ValueStr() != "link") {
+			child = child->NextSiblingElement();
+			continue;
+		}
+
+		URDFLink link;
+		string link_name;
+		child->QueryStringAttribute("name", &link_name);
+
+		if (!read_single_link(child, link)) {
+			return false;
+		}
+
+		links[link_name] = link;
+
+		child = child->NextSiblingElement();
+	}
+
+	return true;
+}
+
+bool read_single_joint (TiXmlHandle handle, URDFJoint &joint) {
+	string joint_name;
+	handle.ToElement()->QueryStringAttribute("name", &joint_name);
+	joint.name = joint_name;
+
+	// type
+	string joint_type_string;
+	handle.ToElement()->QueryStringAttribute("type", &joint_type_string);
+	if (joint_type_string == "revolute")
+		joint.type = URDFJointTypeRevolute;
+	else if (joint_type_string == "continuous")
+		joint.type = URDFJointTypeContinuous;
+	else if (joint_type_string == "prismatic")
+		joint.type = URDFJointTypePrismatic;
+	else if (joint_type_string == "fixed")
+		joint.type = URDFJointTypeFixed;
+	else if (joint_type_string == "Floating")
+		joint.type = URDFJointTypeFloating;
+	else if (joint_type_string == "Planar")
+		joint.type = URDFJointTypePlanar;
+
+	// read origin xyz and rpy
+	TiXmlElement *origin_element = handle.FirstChild("origin").ToElement();
+	if (origin_element) {
+		string value_str;
+		origin_element->QueryStringAttribute("xyz", &value_str);
+
+		if (value_str.size() != 0) {
+			double values[3];
+			if (!parse_double_triple (value_str, values)) {
+				cerr << "Unable to parse origin xyz: '" << value_str << "'" << endl;
+				return false;
+			}
+			joint.origin_x = values[0];
+			joint.origin_y = values[1];
+			joint.origin_z = values[2];
+		}
+		
+		origin_element->QueryStringAttribute("rpy", &value_str);
+
+		if (value_str.size() != 0) {
+			double values[3];
+			if (!parse_double_triple (value_str, values)) {
+				cerr << "Unable to parse origin rpy: '" << value_str << "'" << endl;
+				return false;
+			}
+			joint.origin_rot_r = values[0];
+			joint.origin_rot_p = values[1];
+			joint.origin_rot_y = values[2];
+		}
+	}
+
+	// read parent
+	TiXmlElement *parent_element = handle.FirstChild("parent").ToElement();
+	if (!parent_element) {
+		cerr << "Could not find required parent element for joint '" << joint_name << endl;
+		return false;
+	}
+
+	if (parent_element->QueryStringAttribute ("link", &(joint.parent)) != TIXML_SUCCESS) {
+		cerr << "Could not find required parent element for joint '" << joint_name << endl;
+		return false;
+	}
+
+	// read child
+	TiXmlElement *child_element = handle.FirstChild("child").ToElement();
+	if (!child_element) {
+		cerr << "Could not find required child element for joint '" << joint_name << endl;
+		return false;
+	}
+
+	if (child_element->QueryStringAttribute ("link", &(joint.child)) != TIXML_SUCCESS) {
+		cerr << "Could not find required child element for joint '" << joint_name << endl;
+		return false;
+	}
+
+	// axis
+	joint.axis[0] = 1.;
+	joint.axis[1] = 0.;
+	joint.axis[2] = 0.;
+
+	TiXmlElement *axis_element = handle.FirstChild("axis").ToElement();
+	if (axis_element) {
+		string value_str;
+		axis_element->QueryStringAttribute("xyz", &value_str);
+
+		if (value_str.size() != 0) {
+			double values[3];
+			if (!parse_double_triple (value_str, values)) {
+				cerr << "Unable to parse origin xyz: '" << value_str << "'" << endl;
+				return false;
+			}
+			joint.axis[0] = values[0];
+			joint.axis[1] = values[1];
+			joint.axis[2] = values[2];
+		}
+	}
+
+//	joint.debug_print();
+
+	return true;
+}
+
+bool read_joints (TiXmlDocument &doc, JointMap &joints) {
+	TiXmlHandle doc_handle (&doc);
+	TiXmlHandle joint_handle = doc_handle.FirstChild("robot").FirstChild("joint");
+
+	TiXmlElement *child = joint_handle.ToElement();
+
+	while (child) {
+		if (child->ValueStr() != "joint") {
+			child = child->NextSiblingElement();
+			continue;
+		}
+
+		URDFJoint joint;
+		string joint_name;
+		child->QueryStringAttribute("name", &joint_name);
+
+		if (!read_single_joint(child, joint)) {
+			return false;
+		}
+
+		joints[joint_name] = joint;
+
+		child = child->NextSiblingElement();
+	}
+
+	return true;
+}
+
+bool read_urdf_model (const char* filename, Model* model, bool verbose) {
+	assert (model);
+
+	TiXmlDocument doc (filename);
+	bool load_success = doc.LoadFile();
+
+	if (!load_success) {
+		return false;
+	}
+
+	LinkMap links;
+	JointMap joints;
+
+	if (!read_links(doc, links)) {
+		return false;
+	}
+
+	if (verbose) {
+		cout << "Read " << links.size() << " links." << endl;
+	}
+
+	if (!read_joints(doc, joints)) {
+		return false;
+	}
+
+	if (verbose) {
+		cout << "Read " << joints.size() << " joints." << endl;
+	}
+
+
+	return false;
+}
+
+}
+
+}

addons/urdfreader/rbdl_urdfreader.h

+#ifndef _RBDL_URDFREADER_H
+#define _RBDL_URDFREADER_H
+
+namespace RigidBodyDynamics {
+
+class Model;
+
+namespace Addons {
+	bool read_urdf_model (const char* filename, Model* model, bool verbose = false);
+}
+
+}
+
+/* _RBDL_URDFREADER_H */
+#endif

addons/urdfreader/tinyxml/changes.txt

+Changes in version 1.0.1:
+- Fixed comment tags which were outputing as '<?--' instead of 
+  the correct '<!--'.
+- Implemented the Next and Prev methods of the TiXmlAttribute class.
+- Renamed 'LastAttribtute' to 'LastAttribute'
+- Fixed bad pointer to 'isspace' that could occur while parsing text.
+- Errors finding beginning and end of tags no longer throw it into an
+  infinite loop. (Hopefully.)
+
+Changes in version 1.0.2
+- Minor documentation fixes.
+
+Changes in version 1.0.3
+- After nodes are added to a document, they return a pointer
+  to the new node instead of a bool for success.
+- Elements can be constructed with a value, which is the
+  element name. Every element must have a value or it will be
+  invalid, but the code changes to enforce this are not fully
+  in place.
+
+Changes in version 1.1.0
+- Added the	TiXmlAttributeSet class to pull the attributes into
+  a seperate container.
+- Moved the doubly liked list out of XmlBase. Now XmlBase only
+  requires the Print() function and defines some utility functions.
+- Moved errors into a seperate file. (With the idea of internationalization
+  to the other latin-1 languages.)
+- Added the "NodeType"
+- Fixed white space parsing in text to conform with the standard. 
+  Basically, all white space becomes just one space.
+- Added the TiXmlDeclaration class to read xml declarations.
+
+Changes in version 1.2.0
+- Removed the factory. The factory was not really in the spirit 
+  of small and simple, confused the code, and was of limited value.
+- Added FirstChildElement and NextSiblingElement, because they
+  are such common functions.
+- Re-wrote the example to test and demonstrate more functionality.
+
+Changes in version 1.2.1
+- Fixed a bug where comments couldn't be inside elements.
+- Loading now clears out existing XML rather than appending.
+- Added the "Clear" method on a node to delete all its children.
+
+Changes in version 1.2.2
+- Fixed TiXmlAttribute::Previous actually returning "next." Thanks
+  to Rickard Troedsson for the bug fix.
+
+Changes in version 1.2.3
+- Added the TIXML prefix to the error strings to resolve conflicts
+  with #defines in OS headers. Thanks to Steve Lhomme.
+- Fixed a delete buf that should be a delete [] buf. 
+  Thanks to Ephi Sinowitz.
+
+Changes in version 1.2.4
+- ReplaceChild() was almost guarenteed to fail. Should be fixed,
+  thanks to Joe Smith. Joe also pointed out that the Print() functions
+  should take stream references: I agree, and would like to overload
+  the Print() method to take either format, but I don't want to do 
+  this in a dot release.
+- Some compilers seem to need an extra <ctype.h> include. Thanks
+  to Steve Lhomme for that.
+
+Changes in version 2.0.0 BETA
+- Made the ToXXX() casts safe if 'this' is null. 
+  When "LoadFile" is called with a filename, the value will correctly get set.
+  Thanks to Brian Yoder.
+- Fixed bug where isalpha() and isalnum() would get called with a negative value for 
+  high ascii numbers. Thanks to Alesky Aksenov.
+- Fixed some errors codes that were not getting set.
+- Made methods "const" that were not.
+- Added a switch to enable or disable the ignoring of white space. ( TiXmlDocument::SetIgnoreWhiteSpace() )
+- Greater standardization and code re-use in the parser.
+- Added a stream out operator.
+- Added a stream in operator.
+- Entity support, of predefined entites. &#x entities are untouched by input or output.
+- Improved text out formatting.
+- Fixed ReplaceChild bug, thanks to Tao Chen.
+
+Changes in version 2.0.1
+- Fixed hanging on loading a 0 length file. Thanks to Jeff Scozzafava.
+- Fixed crashing on InsertBeforeChild and InsertAfterChild. Also possibility of bad links being
+  created by same function. Thanks to Frank De prins.
+- Added missing licence text. Thanks to Lars Willemsens.
+- Added <ctype.h> include, at the suggestion of Steve Walters.
+
+Changes in version 2.1.0
+- Yves Berquin brings us the STL switch. The forum on SourceForge, and various emails to
+  me, have long debated all out STL vs. no STL at all. And now you can have it both ways.
+  TinyXml will compile either way.
+
+Changes in version 2.1.1
+- Compilation warnings.
+
+Changes in version 2.1.2
+- Uneeded code is not compiled in the STL case.
+- Changed headers so that STL can be turned on or off in tinyxml.h
+
+Changes in version 2.1.3
+- Fixed non-const reference in API; now uses a pointer.
+- Copy constructor of TiXmlString not checking for assignment to self.
+- Nimrod Cohen found a truly evil bug in the STL implementation that occurs
+  when a string is converted to a c_str and then assigned to self. Search for
+  STL_STRING_BUG for a full description. I'm asserting this is a Microsoft STL
+  bug, since &string and string.c_str() should never be the same. Nevertheless,
+  the code works around it.
+- Urivan Saaib pointed out a compiler conflict, where the C headers define
+  the isblank macro, which was wiping out the TiXmlString::isblank() method.
+  The method was unused and has been removed.
+
+Changes in version 2.1.4
+- Reworked the entity code. Entities were not correctly surving round trip input and output.
+  Will now automatically create entities for high ascii in output.
+
+Changes in version 2.1.5
+- Bug fix by kylotan : infinite loop on some input (tinyxmlparser.cpp rev 1.27)
+- Contributed by Ivica Aracic (bytelord) : 1 new VC++ project to compile versions as static libraries (tinyxml_lib.dsp), 
+  and an example usage in xmltest.dsp
+  (Patch request ID 678605)
+- A suggestion by Ronald Fenner Jr (dormlock) to add #include <istream> and <ostream> for Apple's Project Builder 
+  (Patch request ID 697642)
+- A patch from ohommes that allows to parse correctly dots in element names and attribute names
+  (Patch request 602600 and kylotan 701728)
+- A patch from  hermitgeek ( James ) and wasteland for improper error reporting
+- Reviewed by Lee, with the following changes:
+	- Got sick of fighting the STL/non-STL thing in the windows build. Broke
+	  them out as seperate projects.
+	- I have too long not included the dsw. Added.
+	- TinyXmlText had a protected Print. Odd.
+	- Made LinkEndChild public, with docs and appropriate warnings.
+	- Updated the docs.
+
+2.2.0
+- Fixed an uninitialized pointer in the TiXmlAttributes
+- Fixed STL compilation problem in MinGW (and gcc 3?) - thanks Brian Yoder for finding this one
+- Fixed a syntax error in TiXmlDeclaration - thanks Brian Yoder
+- Fletcher Dunn proposed and submitted new error handling that tracked the row and column. Lee
+  modified it to not have performance impact.
+- General cleanup suggestions from Fletcher Dunn.
+- In error handling, general errors will no longer clear the error state of specific ones.
+- Fix error in documentation : comments starting with "<?--" instead of "<!--" (thanks ion_pulse)
+- Added the TiXmlHandle. An easy, safe way to browse XML DOMs with less code.
+- Added QueryAttribute calls which have better error messaging. (Proposed by Fletcher Dunn)
+- Nodes and attributes can now print themselves to strings. (Yves suggestion)
+- Fixed bug where entities with one character would confuse parser. (Thanks Roman)
+
+2.2.1
+- Additional testing (no more bugs found to be fixed in this release)
+- Significant performance improvement to the cursor code.
+
+2.3.0
+- User Data are now defined in TiXmlBase instead of TiXmlNode
+- Character Entities are now UCS-2
+- Character Entities can be decimal or hexadecimal
+- UTF-8 conversion.
+- Fixed many, many bugs.
+
+2.3.1
+- Fixed bug in handling nulls embedded in the input.
+- Make UTF-8 parser tolerant of bad text encoding.
+- Added encoding detection. 
+- Many fixes and input from John-Philip Leonard Johansson (JP) and Ellers, 
+  including UTF-8 feedback, bug reports, and patches. Thanks!
+- Added version # constants - a suggestion from JP and Ellers.
+- [ 979180 ] Missing ; in entity reference, fix from Rob Laveaux.
+- Copy constructors and assignment have been a long time coming. Thanks to
+  Fokke and JP.
+
+2.3.2
+- Made the IsAlpha and IsAlphaNum much more tolerant of non-UTF-8 encodings. Thanks
+  Volker Boerchers for finding the issue.
+- Ran the program though the magnificent Valgrind - http://valgrind.kde.org - to check
+  for memory errors. Fixed some minor issues.
+
+2.3.3
+- Fixed crash when test program was run from incorrect directory.
+- Fixed bug 1070717 - empty document not returned correctly - thanks Katsuhisa Yuasa.
+- Bug 1079301 resolved - deprecated stdlib calls. Thanks Adrian Boeing.
+- Bug 1035218 fixed - documentation errors. Xunji Luo
+- Other bug fixes have accumulated and been fixed on the way as well; my apologies to
+  authors not credited!
+- Big fix / addition is to correctly return const values. TinyXml could basically
+  remove const in a method like this: TiXmlElement* Foo() const, where the returned element
+  was a pointer to internal data. That is now: const TiXmlElement* Foo() const and
+  TiXmlElement* Foo().
+
+2.3.4
+- Fixed additional const errors, thanks Kent Gibson.
+- Correctly re-enable warnings after tinyxml header. Thanks Cory Nelson.
+- Variety of type cleanup and warning fixes. Thanks Warren Stevens.
+- Cleaned up unneeded constructor calls in TinyString - thanks to Geoff Carlton and
+  the discussion group on sourceforge.
+
+2.4.0
+- Improved string class, thanks Tyge Lovset (whose name gets mangled in English - sorry)
+- Type cast compiler warning, thanks Rob van den Bogaard
+- Added GetText() convenience function. Thanks Ilya Parniuk & Andrew Ellers for input.
+- Many thanks to marlonism for finding an infinite loop in bad xml.
+- A patch to cleanup warnings from Robert Gebis.
+- Added ValueStr() to get the value of a node as a string.
+- TiXmlText can now parse and output as CDATA
+- Additional string improvement from James (z2895)
+- Removed extraneous 'const', thanks David Aldrich
+- First pass at switching to the "safe" stdlib functions. Many people have suggested and
+  pushed on this, but Warren Stevens put together the first proposal.
+- TinyXml now will do EOL normalization before parsing, consistent with the W3C XML spec.
+- Documents loaded with the UTF-8 BOM will now save with the UTF-8 BOM. Good suggestion 
+  from 'instructor_'
+- Ellers submitted his very popular tutorials, which have been added to the distribution.
+
+2.4.1
+- Fixed CDATA output formatting
+- Fixed memory allocators in TinyString to work with overloaded new/delete
+
+2.4.2
+- solosnake pointed out that TIXML_LOG causes problems on an XBOX. The definition in the header
+  was superflous and was moved inside of DEBUG_PARSING
+
+2.4.3
+- Fixed a test bug that caused a crash in 'xmltest'. TinyXML was fine, but it isn't good
+  to ship with a broken test suite.
+- Started converting some functions to not cast between std::string and const char* 
+  quite as often.
+- Added FILE* versions of the document loads - good suggestion from Wade Brainerd
+- Empty documents might not always return the errors they should. [1398915] Thanks to igor v.
+- Added some asserts for multiply adding a node, regardng bug [1391937] suggested by Paco Arjonilla.
+
+2.4.4
+- Bug find thanks to andre-gross found a memory leak that occured when a document failed to load.
+- Bug find (and good analysis) by VirtualJim who found a case where attribute parsing 
+  should be throwing an error and wasn't.
+- Steve Hyatt suggested the QueryValueAttribute method, which is now implemented.
+- DavidA identified a chunk of dead code.
+- Andrew Baxter sent in some compiler warnings that were good clean up points.
+
+2.5
+- Added the Visit() API. Many thanks to both Andrew Ellerton and John-Philip for all their
+  work, code, suggestion, and just general pushing that it should be done.
+- Removed existing streaming code and use TiXmlPrinter instead.
+- [ tinyxml-Bugs-1527079 ] Compile error in tinystr.cpp fixed, thanks to Paul Suggs
+- [ tinyxml-Bugs-1522890 ] SaveFile has no error checks fixed, thanks to Ivan Dobrokotov
+- Ivan Dobrokotov also reported redundant memory allocation in the Attribute() method, which
+  upon investigation was a mess. The attribute should now be fixed for both const char* and 
+  std::string, and the return types match the input parameters.
+- Feature [ 1511105 ] Make TiXmlComment constructor accept a string / char*, implemented.
+  Thanks to Karl Itschen for the feedback.
+- [ 1480108 ] Stream parsing fails when CDATA contains tags was found by Tobias Grimm, who also
+  submitted a test case and patch. A significant bug in CDATA streaming (operator>>) has now
+  been fixed.
+
+2.5.2
+- Lieven, and others, pointed out a missing const-cast that upset the Open Watcom compiler.
+  Should now be fixed.
+- ErrorRow and ErrorCol should have been const, and weren't. Fixed thanks to Dmitry Polutov.
+
+2.5.3
+- zloe_zlo identified a missing string specialization for QueryValueAttribute() [ 1695429 ]. Worked
+  on this bug, but not sure how to fix it in a safe, cross-compiler way.
+- increased warning level to 4 and turned on detect 64 bit portability issues for VC2005.
+  May address [ 1677737 ] VS2005: /Wp64 warnings
+- grosheck identified several problems with the Document copy. Many thanks for [ 1660367 ]
+- Nice catch, and suggested fix, be Gilad Novik on the Printer dropping entities.
+  "[ 1600650 ] Bug when printing xml text" is now fixed.
+- A subtle fix from Nicos Gollan in the tinystring initializer: 
+  [ 1581449 ] Fix initialiser of TiXmlString::nullrep_
+- Great catch, although there isn't a submitter for the bug. [ 1475201 ] TinyXML parses entities in comments. 
+  Comments should not, in fact, parse entities. Fixed the code path and added tests.
+- We were not catching all the returns from ftell. Thanks to Bernard for catching that.
+  
+2.5.4
+- A TiXMLDocument can't be a sub-node. Block this from happening in the 'replace'. Thanks Noam.
+- [ 1714831 ] TiXmlBase::location is not copied by copy-ctors, fix reported and suggested by Nicola Civran.
+- Fixed possible memory overrun in the comment reading code - thanks gcarlton77
+
+2.5.5
+- Alex van der Wal spotted incorrect types (lf) being used in print and scan. robertnestor pointed out some problems with the simple solution. Types updated.
+- Johannes Hillert pointed out some bug typos.
+- Christian Mueller identified inconsistent error handling with Attributes.
+- olivier barthelemy also reported a problem with double truncation, also related to the %lf issue.
+- zaelsius came up with a great (and simple) suggestion to fix QueryValueAttribute truncating strings.
+- added some null pointer checks suggested by hansenk
+- Sami V�is�nen found a (rare) buffer overrun that could occur in parsing.
+- vi tri filed a bug that led to a refactoring of the attribute setting mess (as well as adding a missing SetDoubleAttribute() )
+- removed TIXML_ERROR_OUT_OF_MEMORY. TinyXML does not systematically address OOO, and the notion it does is misleading.
+- vanneto, keithmarshall, others all reported the warning from IsWhiteSpace() usage. Cleaned this up - many thanks to everyone who reported this one.
+- tibur found a bug in end tag parsing
+
+
+2.6.2
+- Switched over to VC 2010
+- Fixed up all the build issues arising from that. (Lots of latent build problems.)
+- Removed the old, now unmaintained and likely not working, build files.
+- Fixed some static analysis issues reported by orbitcowboy from cppcheck. 
+- Bayard 95 sent in analysis from a different analyzer - fixes applied from that as well.
+- Tim Kosse sent a patch fixing an infinite loop.
+- Ma Anguo identified a doc issue.
+- Eddie Cohen identified a missing qualifier resulting in a compilation error on some systems.
+- Fixed a line ending bug. (What year is this? Can we all agree on a format for text files? Please? ...oh well.)
+

addons/urdfreader/tinyxml/readme.txt

+/** @mainpage
+
+<h1> TinyXML </h1>
+
+TinyXML is a simple, small, C++ XML parser that can be easily 
+integrated into other programs.
+
+<h2> What it does. </h2>
+	
+In brief, TinyXML parses an XML document, and builds from that a 
+Document Object Model (DOM) that can be read, modified, and saved.
+
+XML stands for "eXtensible Markup Language." It allows you to create 
+your own document markups. Where HTML does a very good job of marking 
+documents for browsers, XML allows you to define any kind of document 
+markup, for example a document that describes a "to do" list for an 
+organizer application. XML is a very structured and convenient format.
+All those random file formats created to store application data can 
+all be replaced with XML. One parser for everything.
+
+The best place for the complete, correct, and quite frankly hard to
+read spec is at <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">
+http://www.w3.org/TR/2004/REC-xml-20040204/</a>. An intro to XML
+(that I really like) can be found at 
+<a href="http://skew.org/xml/tutorial/">http://skew.org/xml/tutorial</a>.
+
+There are different ways to access and interact with XML data.
+TinyXML uses a Document Object Model (DOM), meaning the XML data is parsed
+into a C++ objects that can be browsed and manipulated, and then 
+written to disk or another output stream. You can also construct an XML document 
+from scratch with C++ objects and write this to disk or another output
+stream.
+
+TinyXML is designed to be easy and fast to learn. It is two headers 
+and four cpp files. Simply add these to your project and off you go. 
+There is an example file - xmltest.cpp - to get you started. 
+
+TinyXML is released under the ZLib license, 
+so you can use it in open source or commercial code. The details
+of the license are at the top of every source file.
+
+TinyXML attempts to be a flexible parser, but with truly correct and
+compliant XML output. TinyXML should compile on any reasonably C++
+compliant system. It does not rely on exceptions or RTTI. It can be 
+compiled with or without STL support. TinyXML fully supports
+the UTF-8 encoding, and the first 64k character entities.
+
+
+<h2> What it doesn't do. </h2>
+
+TinyXML doesn't parse or use DTDs (Document Type Definitions) or XSLs
+(eXtensible Stylesheet Language.) There are other parsers out there 
+(check out www.sourceforge.org, search for XML) that are much more fully
+featured. But they are also much bigger, take longer to set up in
+your project, have a higher learning curve, and often have a more
+restrictive license. If you are working with browsers or have more
+complete XML needs, TinyXML is not the parser for you.
+
+The following DTD syntax will not parse at this time in TinyXML:
+
+@verbatim
+	<!DOCTYPE Archiv [
+	 <!ELEMENT Comment (#PCDATA)>
+	]>
+@endverbatim
+
+because TinyXML sees this as a !DOCTYPE node with an illegally 
+embedded !ELEMENT node. This may be addressed in the future.
+
+<h2> Tutorials. </h2>
+
+For the impatient, here is a tutorial to get you going. A great way to get started, 
+but it is worth your time to read this (very short) manual completely.
+
+- @subpage tutorial0
+
+<h2> Code Status.  </h2>
+
+TinyXML is mature, tested code. It is very stable. If you find
+bugs, please file a bug report on the sourceforge web site
+(www.sourceforge.net/projects/tinyxml). We'll get them straightened 
+out as soon as possible.
+
+There are some areas of improvement; please check sourceforge if you are
+interested in working on TinyXML.
+
+<h2> Related Projects </h2>
+
+TinyXML projects you may find useful! (Descriptions provided by the projects.)
+
+<ul>
+<li> <b>TinyXPath</b> (http://tinyxpath.sourceforge.net). TinyXPath is a small footprint 
+     XPath syntax decoder, written in C++.</li>
+<li> <b>TinyXML++</b> (http://code.google.com/p/ticpp/). TinyXML++ is a completely new 
+     interface to TinyXML that uses MANY of the C++ strengths. Templates, 
+	 exceptions, and much better error handling.</li>
+</ul>
+
+<h2> Features </h2>
+
+<h3> Using STL </h3>
+
+TinyXML can be compiled to use or not use STL. When using STL, TinyXML
+uses the std::string class, and fully supports std::istream, std::ostream,
+operator<<, and operator>>. Many API methods have both 'const char*' and
+'const std::string&' forms.
+
+When STL support is compiled out, no STL files are included whatsoever. All
+the string classes are implemented by TinyXML itself. API methods
+all use the 'const char*' form for input.
+
+Use the compile time #define:
+
+	TIXML_USE_STL
+
+to compile one version or the other. This can be passed by the compiler,
+or set as the first line of "tinyxml.h".
+
+Note: If compiling the test code in Linux, setting the environment
+variable TINYXML_USE_STL=YES/NO will control STL compilation. In the
+Windows project file, STL and non STL targets are provided. In your project,
+It's probably easiest to add the line "#define TIXML_USE_STL" as the first
+line of tinyxml.h.
+
+<h3> UTF-8 </h3>
+
+TinyXML supports UTF-8 allowing to manipulate XML files in any language. TinyXML
+also supports "legacy mode" - the encoding used before UTF-8 support and
+probably best described as "extended ascii".
+
+Normally, TinyXML will try to detect the correct encoding and use it. However,
+by setting the value of TIXML_DEFAULT_ENCODING in the header file, TinyXML
+can be forced to always use one encoding.
+
+TinyXML will assume Legacy Mode until one of the following occurs:
+<ol>
+	<li> If the non-standard but common "UTF-8 lead bytes" (0xef 0xbb 0xbf)
+		 begin the file or data stream, TinyXML will read it as UTF-8. </li>
+	<li> If the declaration tag is read, and it has an encoding="UTF-8", then
+		 TinyXML will read it as UTF-8. </li>
+	<li> If the declaration tag is read, and it has no encoding specified, then TinyXML will 
+		 read it as UTF-8. </li>
+	<li> If the declaration tag is read, and it has an encoding="something else", then TinyXML 
+		 will read it as Legacy Mode. In legacy mode, TinyXML will work as it did before. It's 
+		 not clear what that mode does exactly, but old content should keep working.</li>
+	<li> Until one of the above criteria is met, TinyXML runs in Legacy Mode.</li>
+</ol>
+
+What happens if the encoding is incorrectly set or detected? TinyXML will try
+to read and pass through text seen as improperly encoded. You may get some strange results or 
+mangled characters. You may want to force TinyXML to the correct mode.
+
+You may force TinyXML to Legacy Mode by using LoadFile( TIXML_ENCODING_LEGACY ) or
+LoadFile( filename, TIXML_ENCODING_LEGACY ). You may force it to use legacy mode all
+the time by setting TIXML_DEFAULT_ENCODING = TIXML_ENCODING_LEGACY. Likewise, you may 
+force it to TIXML_ENCODING_UTF8 with the same technique.
+
+For English users, using English XML, UTF-8 is the same as low-ASCII. You
+don't need to be aware of UTF-8 or change your code in any way. You can think
+of UTF-8 as a "superset" of ASCII.
+
+UTF-8 is not a double byte format - but it is a standard encoding of Unicode!
+TinyXML does not use or directly support wchar, TCHAR, or Microsoft's _UNICODE at this time. 
+It is common to see the term "Unicode" improperly refer to UTF-16, a wide byte encoding
+of unicode. This is a source of confusion.
+
+For "high-ascii" languages - everything not English, pretty much - TinyXML can
+handle all languages, at the same time, as long as the XML is encoded
+in UTF-8. That can be a little tricky, older programs and operating systems
+tend to use the "default" or "traditional" code page. Many apps (and almost all
+modern ones) can output UTF-8, but older or stubborn (or just broken) ones
+still output text in the default code page. 
+
+For example, Japanese systems traditionally use SHIFT-JIS encoding. 
+Text encoded as SHIFT-JIS can not be read by TinyXML. 
+A good text editor can import SHIFT-JIS and then save as UTF-8.
+
+The <a href="http://skew.org/xml/tutorial/">Skew.org link</a> does a great
+job covering the encoding issue.
+
+The test file "utf8test.xml" is an XML containing English, Spanish, Russian,
+and Simplified Chinese. (Hopefully they are translated correctly). The file
+"utf8test.gif" is a screen capture of the XML file, rendered in IE. Note that
+if you don't have the correct fonts (Simplified Chinese or Russian) on your
+system, you won't see output that matches the GIF file even if you can parse
+it correctly. Also note that (at least on my Windows machine) console output
+is in a Western code page, so that Print() or printf() cannot correctly display
+the file. This is not a bug in TinyXML - just an OS issue. No data is lost or 
+destroyed by TinyXML. The console just doesn't render UTF-8.
+
+
+<h3> Entities </h3>
+TinyXML recognizes the pre-defined "character entities", meaning special
+characters. Namely:
+
+@verbatim
+	&amp;	&
+	&lt;	<
+	&gt;	>
+	&quot;	"
+	&apos;	'
+@endverbatim
+
+These are recognized when the XML document is read, and translated to there
+UTF-8 equivalents. For instance, text with the XML of:
+
+@verbatim
+	Far &amp; Away
+@endverbatim
+
+will have the Value() of "Far & Away" when queried from the TiXmlText object,
+and will be written back to the XML stream/file as an ampersand. Older versions
+of TinyXML "preserved" character entities, but the newer versions will translate
+them into characters.
+
+Additionally, any character can be specified by its Unicode code point:
+The syntax "&#xA0;" or "&#160;" are both to the non-breaking space characher.
+
+<h3> Printing </h3>
+TinyXML can print output in several different ways that all have strengths and limitations.
+
+- Print( FILE* ). Output to a std-C stream, which includes all C files as well as stdout.
+	- "Pretty prints", but you don't have control over printing options.
+	- The output is streamed directly to the FILE object, so there is no memory overhead
+	  in the TinyXML code.
+	- used by Print() and SaveFile()
+
+- operator<<. Output to a c++ stream.
+	- Integrates with standart C++ iostreams.
+	- Outputs in "network printing" mode without line breaks. Good for network transmission
+	  and moving XML between C++ objects, but hard for a human to read.
+
+- TiXmlPrinter. Output to a std::string or memory buffer.
+	- API is less concise
+	- Future printing options will be put here.
+	- Printing may change slightly in future versions as it is refined and expanded.
+
+<h3> Streams </h3>
+With TIXML_USE_STL on TinyXML supports C++ streams (operator <<,>>) streams as well
+as C (FILE*) streams. There are some differences that you may need to be aware of.
+
+C style output:
+	- based on FILE*
+	- the Print() and SaveFile() methods
+
+	Generates formatted output, with plenty of white space, intended to be as 
+	human-readable as possible. They are very fast, and tolerant of ill formed 
+	XML documents. For example, an XML document that contains 2 root elements 
+	and 2 declarations, will still print.
+
+C style input:
+	- based on FILE*
+	- the Parse() and LoadFile() methods
+
+	A fast, tolerant read. Use whenever you don't need the C++ streams.
+
+C++ style output:
+	- based on std::ostream
+	- operator<<
+
+	Generates condensed output, intended for network transmission rather than
+	readability. Depending on your system's implementation of the ostream class,
+	these may be somewhat slower. (Or may not.) Not tolerant of ill formed XML:
+	a document should contain the correct one root element. Additional root level
+	elements will not be streamed out.
+
+C++ style input:
+	- based on std::istream
+	- operator>>
+
+	Reads XML from a stream, making it useful for network transmission. The tricky
+	part is knowing when the XML document is complete, since there will almost
+	certainly be other data in the stream. TinyXML will assume the XML data is
+	complete after it reads the root element. Put another way, documents that
+	are ill-constructed with more than one root element will not read correctly.
+	Also note that operator>> is somewhat slower than Parse, due to both 
+	implementation of the STL and limitations of TinyXML.
+
+<h3> White space </h3>
+The world simply does not agree on whether white space should be kept, or condensed.
+For example, pretend the '_' is a space, and look at "Hello____world". HTML, and 
+at least some XML parsers, will interpret this as "Hello_world". They condense white
+space. Some XML parsers do not, and will leave it as "Hello____world". (Remember
+to keep pretending the _ is a space.) Others suggest that __Hello___world__ should become
+Hello___world.
+
+It's an issue that hasn't been resolved to my satisfaction. TinyXML supports the
+first 2 approaches. Call TiXmlBase::SetCondenseWhiteSpace( bool ) to set the desired behavior.
+The default is to condense white space.
+
+If you change the default, you should call TiXmlBase::SetCondenseWhiteSpace( bool )
+before making any calls to Parse XML data, and I don't recommend changing it after
+it has been set.
+
+
+<h3> Handles </h3>
+
+Where browsing an XML document in a robust way, it is important to check
+for null returns from method calls. An error safe implementation can
+generate a lot of code like:
+
+@verbatim
+TiXmlElement* root = document.FirstChildElement( "Document" );
+if ( root )
+{
+	TiXmlElement* element = root->FirstChildElement( "Element" );
+	if ( element )
+	{
+		TiXmlElement* child = element->FirstChildElement( "Child" );
+		if ( child )
+		{
+			TiXmlElement* child2 = child->NextSiblingElement( "Child" );
+			if ( child2 )
+			{
+				// Finally do something useful.
+@endverbatim
+
+Handles have been introduced to clean this up. Using the TiXmlHandle class,
+the previous code reduces to:
+
+@verbatim
+TiXmlHandle docHandle( &document );
+TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement();
+if ( child2 )
+{
+	// do something useful
+@endverbatim
+
+Which is much easier to deal with. See TiXmlHandle for more information.
+
+
+<h3> Row and Column tracking </h3>
+Being able to track nodes and attributes back to their origin location
+in source files can be very important for some applications. Additionally,
+knowing where parsing errors occured in the original source can be very
+time saving.
+
+TinyXML can tracks the row and column origin of all nodes and attributes
+in a text file. The TiXmlBase::Row() and TiXmlBase::Column() methods return
+the origin of the node in the source text. The correct tabs can be 
+configured in TiXmlDocument::SetTabSize().
+
+
+<h2> Using and Installing </h2>
+
+To Compile and Run xmltest:
+
+A Linux Makefile and a Windows Visual C++ .dsw file is provided. 
+Simply compile and run. It will write the file demotest.xml to your 
+disk and generate output on the screen. It also tests walking the
+DOM by printing out the number of nodes found using different 
+techniques.
+
+The Linux makefile is very generic and runs on many systems - it 
+is currently tested on mingw and
+MacOSX. You do not need to run 'make depend'. The dependecies have been
+hard coded.
+
+<h3>Windows project file for VC6</h3>
+<ul>
+<li>tinyxml:		tinyxml library, non-STL </li>
+<li>tinyxmlSTL:		tinyxml library, STL </li>
+<li>tinyXmlTest:	test app, non-STL </li>
+<li>tinyXmlTestSTL: test app, STL </li>
+</ul>
+
+<h3>Makefile</h3>
+At the top of the makefile you can set:
+
+PROFILE, DEBUG, and TINYXML_USE_STL. Details (such that they are) are in
+the makefile.
+
+In the tinyxml directory, type "make clean" then "make". The executable
+file 'xmltest' will be created.
+
+
+
+<h3>To Use in an Application:</h3>
+
+Add tinyxml.cpp, tinyxml.h, tinyxmlerror.cpp, tinyxmlparser.cpp, tinystr.cpp, and tinystr.h to your
+project or make file. That's it! It should compile on any reasonably
+compliant C++ system. You do not need to enable exceptions or
+RTTI for TinyXML.
+
+
+<h2> How TinyXML works.  </h2>
+
+An example is probably the best way to go. Take:
+@verbatim
+	<?xml version="1.0" standalone=no>
+	<!-- Our to do list data -->
+	<ToDo>
+		<Item priority="1"> Go to the <bold>Toy store!</bold></Item>
+		<Item priority="2"> Do bills</Item>
+	</ToDo>
+@endverbatim
+
+Its not much of a To Do list, but it will do. To read this file 
+(say "demo.xml") you would create a document, and parse it in:
+@verbatim
+	TiXmlDocument doc( "demo.xml" );
+	doc.LoadFile();
+@endverbatim
+
+And its ready to go. Now lets look at some lines and how they 
+relate to the DOM.
+
+@verbatim
+<?xml version="1.0" standalone=no>
+@endverbatim
+
+	The first line is a declaration, and gets turned into the
+	TiXmlDeclaration class. It will be the first child of the
+	document node.
+	
+	This is the only directive/special tag parsed by TinyXML.
+	Generally directive tags are stored in TiXmlUnknown so the 
+	commands wont be lost when it is saved back to disk.
+
+@verbatim
+<!-- Our to do list data -->
+@endverbatim
+
+	A comment. Will become a TiXmlComment object.
+
+@verbatim
+<ToDo>
+@endverbatim
+
+	The "ToDo" tag defines a TiXmlElement object. This one does not have 
+	any attributes, but does contain 2 other elements.
+
+@verbatim
+<Item priority="1"> 
+@endverbatim
+
+	Creates another TiXmlElement which is a child of the "ToDo" element. 
+	This element has 1 attribute, with the name "priority" and the value 
+	"1".
+
+@verbatim
+Go to the
+@endverbatim 
+
+	A TiXmlText. This is a leaf node and cannot contain other nodes. 
+	It is a child of the "Item" TiXmlElement.
+
+@verbatim
+<bold>
+@endverbatim
+
+	
+	Another TiXmlElement, this one a child of the "Item" element.
+
+Etc.
+
+Looking at the entire object tree, you end up with:
+@verbatim
+TiXmlDocument					"demo.xml"
+	TiXmlDeclaration			"version='1.0'" "standalone=no"
+	TiXmlComment				" Our to do list data"
+	TiXmlElement				"ToDo"
+		TiXmlElement			"Item" Attribtutes: priority = 1
+			TiXmlText			"Go to the "
+			TiXmlElement		"bold"
+				TiXmlText		"Toy store!"
+		TiXmlElement			"Item" Attributes: priority=2
+			TiXmlText			"Do bills"
+@endverbatim
+
+<h2> Documentation </h2>
+
+The documentation is build with Doxygen, using the 'dox' 
+configuration file.
+
+<h2> License </h2>
+
+TinyXML is released under the zlib license:
+
+This software is provided 'as-is', without any express or implied 
+warranty. In no event will the authors be held liable for any 
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any 
+purpose, including commercial applications, and to alter it and 
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must 
+not claim that you wrote the original software. If you use this 
+software in a product, an acknowledgment in the product documentation 
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and 
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source 
+distribution.
+
+<h2> References  </h2>
+
+The World Wide Web Consortium is the definitive standard body for 
+XML, and their web pages contain huge amounts of information. 
+
+The definitive spec: <a href="http://www.w3.org/TR/2004/REC-xml-20040204/">
+http://www.w3.org/TR/2004/REC-xml-20040204/</a>
+
+I also recommend "XML Pocket Reference" by Robert Eckstein and published by 
+OReilly...the book that got the whole thing started.
+
+<h2> Contributors, Contacts, and a Brief History </h2>
+
+Thanks very much to everyone who sends suggestions, bugs, ideas, and 
+encouragement. It all helps, and makes this project fun. A special thanks
+to the contributors on the web pages that keep it lively.
+
+So many people have sent in bugs and ideas, that rather than list here 
+we try to give credit due in the "changes.txt" file.
+
+TinyXML was originally written by Lee Thomason. (Often the "I" still
+in the documentation.) Lee reviews changes and releases new versions,
+with the help of Yves Berquin, Andrew Ellerton, and the tinyXml community.
+
+We appreciate your suggestions, and would love to know if you 
+use TinyXML. Hopefully you will enjoy it and find it useful. 
+Please post questions, comments, file bugs, or contact us at:
+
+www.sourceforge.net/projects/tinyxml
+
+Lee Thomason, Yves Berquin, Andrew Ellerton
+*/

addons/urdfreader/tinyxml/tinystr.cpp

+/*
+www.sourceforge.net/projects/tinyxml
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TIXML_USE_STL
+
+#include "tinystr.h"
+
+// Error value for find primitive
+const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1);
+
+
+// Null rep.
+TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } };
+
+
+void TiXmlString::reserve (size_type cap)
+{
+	if (cap > capacity())
+	{
+		TiXmlString tmp;
+		tmp.init(length(), cap);
+		memcpy(tmp.start(), data(), length());
+		swap(tmp);
+	}
+}
+
+
+TiXmlString& TiXmlString::assign(const char* str, size_type len)
+{
+	size_type cap = capacity();
+	if (len > cap || cap > 3*(len + 8))
+	{
+		TiXmlString tmp;
+		tmp.init(len);
+		memcpy(tmp.start(), str, len);
+		swap(tmp);
+	}
+	else
+	{
+		memmove(start(), str, len);
+		set_size(len);
+	}
+	return *this;
+}
+
+
+TiXmlString& TiXmlString::append(const char* str, size_type len)
+{
+	size_type newsize = length() + len;
+	if (newsize > capacity())
+	{
+		reserve (newsize + capacity());
+	}
+	memmove(finish(), str, len);
+	set_size(newsize);
+	return *this;
+}
+
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b)
+{
+	TiXmlString tmp;
+	tmp.reserve(a.length() + b.length());
+	tmp += a;
+	tmp += b;
+	return tmp;
+}
+
+TiXmlString operator + (const TiXmlString & a, const char* b)
+{
+	TiXmlString tmp;
+	TiXmlString::size_type b_len = static_cast<TiXmlString::size_type>( strlen(b) );
+	tmp.reserve(a.length() + b_len);
+	tmp += a;
+	tmp.append(b, b_len);
+	return tmp;
+}
+
+TiXmlString operator + (const char* a, const TiXmlString & b)
+{
+	TiXmlString tmp;
+	TiXmlString::size_type a_len = static_cast<TiXmlString::size_type>( strlen(a) );
+	tmp.reserve(a_len + b.length());
+	tmp.append(a, a_len);
+	tmp += b;
+	return tmp;
+}
+
+
+#endif	// TIXML_USE_STL

addons/urdfreader/tinyxml/tinystr.h

+/*
+www.sourceforge.net/projects/tinyxml
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+
+#ifndef TIXML_USE_STL
+
+#ifndef TIXML_STRING_INCLUDED
+#define TIXML_STRING_INCLUDED
+
+#include <assert.h>
+#include <string.h>
+
+/*	The support for explicit isn't that universal, and it isn't really
+	required - it is used to check that the TiXmlString class isn't incorrectly
+	used. Be nice to old compilers and macro it here:
+*/
+#if defined(_MSC_VER) && (_MSC_VER >= 1200 )
+	// Microsoft visual studio, version 6 and higher.
+	#define TIXML_EXPLICIT explicit
+#elif defined(__GNUC__) && (__GNUC__ >= 3 )
+	// GCC version 3 and higher.s
+	#define TIXML_EXPLICIT explicit
+#else
+	#define TIXML_EXPLICIT
+#endif
+
+
+/*
+   TiXmlString is an emulation of a subset of the std::string template.
+   Its purpose is to allow compiling TinyXML on compilers with no or poor STL support.
+   Only the member functions relevant to the TinyXML project have been implemented.
+   The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase
+   a string and there's no more room, we allocate a buffer twice as big as we need.
+*/
+class TiXmlString
+{
+  public :
+	// The size type used
+  	typedef size_t size_type;
+
+	// Error value for find primitive
+	static const size_type npos; // = -1;
+
+
+	// TiXmlString empty constructor
+	TiXmlString () : rep_(&nullrep_)
+	{
+	}
+
+	// TiXmlString copy constructor
+	TiXmlString ( const TiXmlString & copy) : rep_(0)
+	{
+		init(copy.length());
+		memcpy(start(), copy.data(), length());
+	}
+
+	// TiXmlString constructor, based on a string
+	TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0)
+	{
+		init( static_cast<size_type>( strlen(copy) ));
+		memcpy(start(), copy, length());
+	}
+
+	// TiXmlString constructor, based on a string
+	TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0)
+	{
+		init(len);
+		memcpy(start(), str, len);
+	}
+
+	// TiXmlString destructor
+	~TiXmlString ()
+	{
+		quit();
+	}
+
+	TiXmlString& operator = (const char * copy)
+	{
+		return assign( copy, (size_type)strlen(copy));
+	}
+
+	TiXmlString& operator = (const TiXmlString & copy)
+	{
+		return assign(copy.start(), copy.length());
+	}
+
+
+	// += operator. Maps to append
+	TiXmlString& operator += (const char * suffix)
+	{
+		return append(suffix, static_cast<size_type>( strlen(suffix) ));
+	}
+
+	// += operator. Maps to append
+	TiXmlString& operator += (char single)
+	{
+		return append(&single, 1);
+	}
+
+	// += operator. Maps to append
+	TiXmlString& operator += (const TiXmlString & suffix)
+	{
+		return append(suffix.data(), suffix.length());
+	}
+
+
+	// Convert a TiXmlString into a null-terminated char *
+	const char * c_str () const { return rep_->str; }
+
+	// Convert a TiXmlString into a char * (need not be null terminated).
+	const char * data () const { return rep_->str; }
+
+	// Return the length of a TiXmlString
+	size_type length () const { return rep_->size; }
+
+	// Alias for length()
+	size_type size () const { return rep_->size; }
+
+	// Checks if a TiXmlString is empty
+	bool empty () const { return rep_->size == 0; }
+
+	// Return capacity of string
+	size_type capacity () const { return rep_->capacity; }
+
+
+	// single char extraction
+	const char& at (size_type index) const
+	{
+		assert( index < length() );
+		return rep_->str[ index ];
+	}
+
+	// [] operator
+	char& operator [] (size_type index) const
+	{
+		assert( index < length() );
+		return rep_->str[ index ];
+	}
+
+	// find a char in a string. Return TiXmlString::npos if not found
+	size_type find (char lookup) const
+	{
+		return find(lookup, 0);
+	}
+
+	// find a char in a string from an offset. Return TiXmlString::npos if not found
+	size_type find (char tofind, size_type offset) const
+	{
+		if (offset >= length()) return npos;
+
+		for (const char* p = c_str() + offset; *p != '\0'; ++p)
+		{
+		   if (*p == tofind) return static_cast< size_type >( p - c_str() );
+		}
+		return npos;
+	}
+
+	void clear ()
+	{
+		//Lee:
+		//The original was just too strange, though correct:
+		//	TiXmlString().swap(*this);
+		//Instead use the quit & re-init:
+		quit();
+		init(0,0);
+	}
+
+	/*	Function to reserve a big amount of data when we know we'll need it. Be aware that this
+		function DOES NOT clear the content of the TiXmlString if any exists.
+	*/
+	void reserve (size_type cap);
+
+	TiXmlString& assign (const char* str, size_type len);
+
+	TiXmlString& append (const char* str, size_type len);
+
+	void swap (TiXmlString& other)
+	{
+		Rep* r = rep_;
+		rep_ = other.rep_;
+		other.rep_ = r;
+	}
+
+  private:
+
+	void init(size_type sz) { init(sz, sz); }
+	void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; }
+	char* start() const { return rep_->str; }
+	char* finish() const { return rep_->str + rep_->size; }
+
+	struct Rep
+	{
+		size_type size, capacity;
+		char str[1];
+	};
+
+	void init(size_type sz, size_type cap)
+	{
+		if (cap)
+		{
+			// Lee: the original form:
+			//	rep_ = static_cast<Rep*>(operator new(sizeof(Rep) + cap));
+			// doesn't work in some cases of new being overloaded. Switching
+			// to the normal allocation, although use an 'int' for systems
+			// that are overly picky about structure alignment.
+			const size_type bytesNeeded = sizeof(Rep) + cap;
+			const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); 
+			rep_ = reinterpret_cast<Rep*>( new int[ intsNeeded ] );
+
+			rep_->str[ rep_->size = sz ] = '\0';
+			rep_->capacity = cap;
+		}
+		else
+		{
+			rep_ = &nullrep_;
+		}
+	}
+
+	void quit()
+	{
+		if (rep_ != &nullrep_)
+		{
+			// The rep_ is really an array of ints. (see the allocator, above).
+			// Cast it back before delete, so the compiler won't incorrectly call destructors.
+			delete [] ( reinterpret_cast<int*>( rep_ ) );
+		}
+	}
+
+	Rep * rep_;
+	static Rep nullrep_;
+
+} ;
+
+
+inline bool operator == (const TiXmlString & a, const TiXmlString & b)
+{
+	return    ( a.length() == b.length() )				// optimization on some platforms
+	       && ( strcmp(a.c_str(), b.c_str()) == 0 );	// actual compare
+}
+inline bool operator < (const TiXmlString & a, const TiXmlString & b)
+{
+	return strcmp(a.c_str(), b.c_str()) < 0;
+}
+
+inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); }
+inline bool operator >  (const TiXmlString & a, const TiXmlString & b) { return b < a; }
+inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); }
+inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); }
+
+inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; }
+inline bool operator == (const char* a, const TiXmlString & b) { return b == a; }
+inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); }
+inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); }
+
+TiXmlString operator + (const TiXmlString & a, const TiXmlString & b);
+TiXmlString operator + (const TiXmlString & a, const char* b);
+TiXmlString operator + (const char* a, const TiXmlString & b);
+
+
+/*
+   TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString.
+   Only the operators that we need for TinyXML have been developped.
+*/
+class TiXmlOutStream : public TiXmlString
+{
+public :
+
+	// TiXmlOutStream << operator.
+	TiXmlOutStream & operator << (const TiXmlString & in)
+	{
+		*this += in;
+		return *this;
+	}
+
+	// TiXmlOutStream << operator.
+	TiXmlOutStream & operator << (const char * in)
+	{
+		*this += in;
+		return *this;
+	}
+
+} ;
+
+#endif	// TIXML_STRING_INCLUDED
+#endif	// TIXML_USE_STL

addons/urdfreader/tinyxml/tinyxml.cpp

+/*
+www.sourceforge.net/projects/tinyxml
+Original code by Lee Thomason (www.grinninglizard.com)
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any
+damages arising from the use of this software.
+
+Permission is granted to anyone to use this software for any
+purpose, including commercial applications, and to alter it and
+redistribute it freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must
+not claim that you wrote the original software. If you use this
+software in a product, an acknowledgment in the product documentation
+would be appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and
+must not be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source
+distribution.
+*/
+
+#include <ctype.h>
+
+#ifdef TIXML_USE_STL
+#include <sstream>
+#include <iostream>
+#endif
+
+#include "tinyxml.h"
+
+FILE* TiXmlFOpen( const char* filename, const char* mode );
+
+bool TiXmlBase::condenseWhiteSpace = true;
+
+// Microsoft compiler security
+FILE* TiXmlFOpen( const char* filename, const char* mode )
+{
+	#if defined(_MSC_VER) && (_MSC_VER >= 1400 )
+		FILE* fp = 0;
+		errno_t err = fopen_s( &fp, filename, mode );
+		if ( !err && fp )
+			return fp;
+		return 0;
+	#else
+		return fopen( filename, mode );
+	#endif
+}
+
+void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString )
+{
+	int i=0;
+
+	while( i<(int)str.length() )
+	{
+		unsigned char c = (unsigned char) str[i];
+
+		if (    c == '&' 
+		     && i < ( (int)str.length() - 2 )
+			 && str[i+1] == '#'
+			 && str[i+2] == 'x' )
+		{
+			// Hexadecimal character reference.
+			// Pass through unchanged.
+			// &#xA9;	-- copyright symbol, for example.
+			//
+			// The -1 is a bug fix from Rob Laveaux. It keeps
+			// an overflow from happening if there is no ';'.
+			// There are actually 2 ways to exit this loop -
+			// while fails (error case) and break (semicolon found).
+			// However, there is no mechanism (currently) for
+			// this function to return an error.
+			while ( i<(int)str.length()-1 )
+			{
+				outString->append( str.c_str() + i, 1 );
+				++i;
+				if ( str[i] == ';' )
+					break;
+			}
+		}
+		else if ( c == '&' )
+		{
+			outString->append( entity[0].str, entity[0].strLength );
+			++i;
+		}
+		else if ( c == '<' )
+		{
+			outString->append( entity[1].str, entity[1].strLength );
+			++i;
+		}
+		else if ( c == '>' )
+		{
+			outString->append( entity[2].str, entity[2].strLength );
+			++i;
+		}
+		else if ( c == '\"' )
+		{
+			outString->append( entity[3].str, entity[3].strLength );
+			++i;
+		}
+		else if ( c == '\'' )
+		{
+			outString->append( entity[4].str, entity[4].strLength );
+			++i;
+		}
+		else if ( c < 32 )
+		{
+			// Easy pass at non-alpha/numeric/symbol
+			// Below 32 is symbolic.
+			char buf[ 32 ];
+			
+			#if defined(TIXML_SNPRINTF)		
+				TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) );
+			#else
+				sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) );
+			#endif		
+
+			//*ME:	warning C4267: convert 'size_t' to 'int'
+			//*ME:	Int-Cast to make compiler happy ...
+			outString->append( buf, (int)strlen( buf ) );
+			++i;
+		}
+		else
+		{
+			//char realc = (char) c;
+			//outString->append( &realc, 1 );
+			*outString += (char) c;	// somewhat more efficient function call.
+			++i;
+		}
+	}
+}
+
+
+TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase()
+{
+	parent = 0;
+	type = _type;
+	firstChild = 0;
+	lastChild = 0;
+	prev = 0;
+	next = 0;
+}
+
+
+TiXmlNode::~TiXmlNode()
+{
+	TiXmlNode* node = firstChild;
+	TiXmlNode* temp = 0;
+
+	while ( node )
+	{
+		temp = node;
+		node = node->next;
+		delete temp;
+	}	
+}
+
+
+void TiXmlNode::CopyTo( TiXmlNode* target ) const
+{
+	target->SetValue (value.c_str() );
+	target->userData = userData; 
+	target->location = location;
+}
+
+
+void TiXmlNode::Clear()
+{
+	TiXmlNode* node = firstChild;
+	TiXmlNode* temp = 0;
+
+	while ( node )
+	{
+		temp = node;
+		node = node->next;
+		delete temp;
+	}	
+
+	firstChild = 0;
+	lastChild = 0;
+}
+
+
+TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
+{
+	assert( node->parent == 0 || node->parent == this );
+	assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() );
+
+	if ( node->Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		delete node;
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	node->parent = this;
+
+	node->prev = lastChild;
+	node->next = 0;
+
+	if ( lastChild )
+		lastChild->next = node;
+	else
+		firstChild = node;			// it was an empty list.
+
+	lastChild = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
+{
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+
+	return LinkEndChild( node );
+}
+
+
+TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
+{	
+	if ( !beforeThis || beforeThis->parent != this ) {
+		return 0;
+	}
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+	node->parent = this;
+
+	node->next = beforeThis;
+	node->prev = beforeThis->prev;
+	if ( beforeThis->prev )
+	{
+		beforeThis->prev->next = node;
+	}
+	else
+	{
+		assert( firstChild == beforeThis );
+		firstChild = node;
+	}
+	beforeThis->prev = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
+{
+	if ( !afterThis || afterThis->parent != this ) {
+		return 0;
+	}
+	if ( addThis.Type() == TiXmlNode::TINYXML_DOCUMENT )
+	{
+		if ( GetDocument() ) 
+			GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	TiXmlNode* node = addThis.Clone();
+	if ( !node )
+		return 0;
+	node->parent = this;
+
+	node->prev = afterThis;
+	node->next = afterThis->next;
+	if ( afterThis->next )
+	{
+		afterThis->next->prev = node;
+	}
+	else
+	{
+		assert( lastChild == afterThis );
+		lastChild = node;
+	}
+	afterThis->next = node;
+	return node;
+}
+
+
+TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
+{
+	if ( !replaceThis )
+		return 0;
+
+	if ( replaceThis->parent != this )
+		return 0;
+
+	if ( withThis.ToDocument() ) {
+		// A document can never be a child.	Thanks to Noam.
+		TiXmlDocument* document = GetDocument();
+		if ( document ) 
+			document->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN );
+		return 0;
+	}
+
+	TiXmlNode* node = withThis.Clone();
+	if ( !node )
+		return 0;
+
+	node->next = replaceThis->next;
+	node->prev = replaceThis->prev;
+
+	if ( replaceThis->next )
+		replaceThis->next->prev = node;
+	else
+		lastChild = node;
+
+	if ( replaceThis->prev )
+		replaceThis->prev->next = node;
+	else
+		firstChild = node;
+
+	delete replaceThis;
+	node->parent = this;
+	return node;
+}
+
+
+bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
+{
+	if ( !removeThis ) {
+		return false;
+	}
+
+	if ( removeThis->parent != this )
+	{	
+		assert( 0 );
+		return false;
+	}
+
+	if ( removeThis->next )
+		removeThis->next->prev = removeThis->prev;
+	else
+		lastChild = removeThis->prev;
+
+	if ( removeThis->prev )
+		removeThis->prev->next = removeThis->next;
+	else
+		firstChild = removeThis->next;
+
+	delete removeThis;
+	return true;