Introduction of 1.TinyXML2
Third-party libraries TinyXML2 is simple, compact, efficient and open source C ++ XML file parsing library, you can easily apply it to existing projects, ideal for parsing XML files, store simple data, configuration files, and object serialization and other data volume is not large operations.
TinyXML2 details and see: TinyXML2 official website .
Acquisition and installation of 2.TinyXML2
TinyXML2 by their Github page get the source code can be used specifically git clone
order or directly download the ZIP archive, git clone
calling the situation a command is as follows:
git clone https://github.com/leethomason/tinyxml2
Entering the command line tinyxml2
directory, using the following command to compile and install TinyXML2, command execution as follows (wherein the $
symbol is a command shell prompt):
$ sudo make install
mkdir -p /usr/local
mkdir -p /usr/local/bin
mkdir -p /usr/local/lib
mkdir -p /usr/local/include
install xmltest /usr/local/bin/xmltest
install -m 644 tinyxml2.h /usr/local/include/tinyxml2.h
install -m 644 libtinyxml2.a /usr/local/lib/libtinyxml2.a
Accordingly, put tinyxml2
library is installed into the local environment, tinyxml2
run the following command directory, run the test code TinyXML2:
$ xmltest
This routine is executed when used xml files are located in tinyxml2
the directory in resources
the directory, the terminal ends the procedure executed after the prompt as shown below:
It showed tinyxml2
library has been successfully installed.
Simple example of the use of 2.TinyXML2
After TinyXML2 installed on the local environment, the following simple demonstration of the use of TinyXML2:
the TinyXML2 source files in the folder xmltest.cpp
and resources/dream.xml
copied to the destination folder for examples demonstrate.
Here, in xmltest.c
reference to the header file tinyxml2.h
:
#include "tinyxml2.h"
At the same time declared namespace TinyXML2 of:
using namespace tinyxml2;
Further, in the main function is defined: If the program parameter is greater than 1, is created XMLDocument
object and the loader file specified, if the last file successfully loaded, the output of the correlation processing time, the portion of the code is shown below.
if ( argc > 1 ) {
XMLDocument* doc = new XMLDocument();
clock_t startTime = clock();
doc->LoadFile( argv[1] );
clock_t loadTime = clock();
int errorID = doc->ErrorID();
delete doc; doc = 0;
clock_t deleteTime = clock();
printf( "Test file '%s' loaded. ErrorID=%d\n", argv[1], errorID );
if ( !errorID ) {
printf( "Load time=%u\n", (unsigned)(loadTime - startTime) );
printf( "Delete time=%u\n", (unsigned)(deleteTime - loadTime) );
printf( "Total time=%u\n", (unsigned)(deleteTime - startTime) );
}
exit(0);
}
Use the following command to compile the program:
$ g++ -o xmltest xmltest.cpp -ltinyxml2
If it can not find a file not found error message appears or static library, you can also manually specify the header file directory ( -I
) and library files directory ( -L
):
$ g++ -o xmltest xmltest.cpp -I /usr/local/include -L /usr/local/lib -ltinyxml2
Enter the following command to execute the sample program:
$ xmltest dream.xml
You can see the program output is as follows, that is, the program successfully loaded the XML file dream.xml.
3.TinyXML2 use of ROS
The following feature package to create a ROS ROS work in space by tinyxml_test
using Launch file TinyXML2 resolve the ROS, ROS in order to demonstrate the use of TnyXML2.
Here is the feature package package.xml
file:
<?xml version="1.0"?>
<package format="2">
<name>tinyxml_test</name>
<version>0.0.0</version>
<license>TODO</license>
<maintainer email="[email protected]">jacky</maintainer>
<description>The tinyxml_test package</description>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>tf</build_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>tf</build_export_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>tf</exec_depend>
</package>
Node functions package source tinyxml_test_node.cpp
code is as follows:
#include <ros/ros.h>
#include <ros/package.h>
#include <tf/transform_broadcaster.h>
#include <tinyxml2.h>
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <map>
using namespace tinyxml2;//使用tinyxml2命名空间
using namespace std;
/* 功能函数 */
float String2Float(std::string numStr){
std::stringstream ss(numStr);
float num;
ss>>num;
return num;
}
int main(int argc, char **argv) {
ros::init(argc, argv, "tinyxml_test_node");
ros::NodeHandle nh("~"), nh_param("~");
std::string tf_launch_file;
//注:"test.launch"文件位于catkin_ws/src/tinyxml_test/launch/目录下
nh_param.param<std::string>("tf_launch_file", tf_launch_file,"test.launch");
/*Load launch file to get the tf args.*/
XMLDocument* doc = new XMLDocument();
std::map<std::string,tf::StampedTransform> stampedTransformMap;//用于存储多个不同坐标系之间的转换关系
std::string filePath = ros::package::getPath("tinyxml_test");//获取tinyxml_test功能包的绝对路径
filePath+="/launch/";
filePath+=tf_launch_file;
doc->LoadFile( filePath.c_str() );
int errorID = doc->ErrorID();
if(errorID){
ROS_FATAL("[radar_freespace] Failed to load launch file %s.", filePath.c_str());
return -1;
}
ROS_INFO( "[radar_freespace] Launch file '%s' loaded.", filePath.c_str());
XMLElement* rootElement = doc->RootElement();//获得根元素,即launch
std::cout<<"Root Element:"<<rootElement->Value()<<std::endl;
for(const XMLElement* element =rootElement->FirstChildElement();element;element=element->NextSiblingElement()){
const XMLAttribute* argsAttr = element->FindAttribute("args");
std::string argsAttrStr=std::string(argsAttr->Value());
std::cout<<"Args Attribute:"<<argsAttrStr<<std::endl;
std::stringstream ss(argsAttrStr);
std::vector<std::string> argStrVec;
std::string tmpArgStr = "";
while (std::getline(ss, tmpArgStr, ' ')) {
argStrVec.push_back(tmpArgStr);
}
tf::Transform transform;
transform.setOrigin(tf::Vector3(String2Float(argStrVec.at(0)),String2Float(argStrVec.at(1)),String2Float(argStrVec.at(2))));
tf::Quaternion quaternion;
quaternion.setRPY(String2Float(argStrVec.at(5)),String2Float(argStrVec.at(4)),String2Float(argStrVec.at(3)));
transform.setRotation(quaternion);
stampedTransformMap[argStrVec.at(6)]=tf::StampedTransform(transform,ros::Time::now(),argStrVec.at(6),argStrVec.at(7));
//输出launch文件中记录的坐标系转换关系
std::cout<<stampedTransformMap[argStrVec.at(6)].getOrigin().x()<<","<<stampedTransformMap[argStrVec.at(6)].getOrigin().y()<<","<<stampedTransformMap[argStrVec.at(6)].getOrigin().z()<<",";
std::cout<<stampedTransformMap[argStrVec.at(6)].getRotation().getW()<<","<<stampedTransformMap[argStrVec.at(6)].getRotation().getX()<<","<<stampedTransformMap[argStrVec.at(6)].getRotation().getY()<<","<<stampedTransformMap[argStrVec.at(6)].getRotation().getZ()<<std::endl;
}
delete doc; //删除对象
doc = NULL; //避免野指针
ros::spin();
return 0;
}
This can be utilized TinyXML2 Node Launch parse file (XML format) function present in the package, the file is located catkin_ws / src / tinyxml_test / launch / files in the directory test.launch
, and wherein the final output can be saved according to launch a file read coordinates tf conversion information. test.launch
Contents of the file are as follows:
<?xml version="1.0"?>
<launch>
<node pkg="tf" type="static_transform_publisher" name="sensor_frame_to_world" args="2 2 2 0 0 0 world sensor_frame 100" />
<node pkg="tf" type="static_transform_publisher" name="imu_to_sensor_frame" args="0 0 0 0 0 0 sensor_frame imu 100" />
<node pkg="tf" type="static_transform_publisher" name="lidar_to_sensor_frame" args="1 1 1 0 0 0 sensor_frame lidar 100" />
</launch>
To compile the feature pack, also you need to modify its CMakeLists.txt file, add the necessary feature pack, the directory containing the source code and libraries and so on. The complete contents of the file are as follows:
cmake_minimum_required(VERSION 2.8.3)
project(tinyxml_test)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
roscpp
roslib
tf
)
###################################
## catkin specific configuration ##
###################################
catkin_package(
LIBRARIES
${PROJECT_NAME}
CATKIN_DEPENDS
roscpp tf
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
${catkin_INCLUDE_DIRS}
)
## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(${PROJECT_NAME}_node src/tinyxml_test_node.cpp)
## Specify libraries to link a library or executable target against
target_link_libraries(${PROJECT_NAME}_node
-ltinyxml2
${catkin_LIBRARIES}
)
#############
## Install ##
#############
## Mark executables and/or libraries for installation
install(
TARGETS
${PROJECT_NAME}_node
ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
Note: Because the program needs to call third-party library TinyXML2, it is necessary in CMakeLists.txt file find_package
to add options roslib
feature pack, and target_link_libraries
specify the link to the static library option ( -ltinyxml2
).
Finally, execute the command catkin_make
will feature pack after a successful compilation, use the following command to run the node (to be run in advance roscore
node):
$ rosrun tinyxml_test tinyxml_test_node
Launch the program can output files stored tf coordinate conversion information:
you're done!