MMMExporter.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package ArmarXGuiPlugins::RobotTrajectoryDesigner::ImportExport
17 * @author Liran Dattner
18 * @date 2018
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23#include "MMMExporter.h"
24
25#include <clocale>
26
27#include <boost/make_shared.hpp>
28
29#include <QString>
30#include <QtXml>
31
33
36#include <MMM/Model/Model.h>
37#include <MMM/Model/ModelReaderXML.h>
38#include <MMM/Motion/Motion.h>
39#include <MMM/Motion/MotionWriterXML.h>
40#include <MMM/Motion/Plugin/KinematicPlugin/KinematicSensor.h>
41#include <MMM/Motion/Plugin/ModelPosePlugin/ModelPoseSensor.h>
42#include <MMM/RapidXML/rapidxml.hpp>
43
45{
46 this->environment = environment;
47}
48
49void
50armarx::MMMExporter::exportTrajectory(std::vector<armarx::DesignerTrajectoryPtr> trajectories,
51 const std::string file)
52{
53 //Ensure that locale is en - punctuation for doubles in exported file
54 setlocale(LC_NUMERIC, "en_US.UTF-8");
55 //ARMARX_INFO << "Received " << trajectories.size() << " trajectories";
56 //Create a ModelPoseSensor. The sensors name is the used rns
57 MMM::ModelReaderXMLPtr modelReader(new MMM::ModelReaderXML());
58 MMM::ModelPtr modelptr = modelReader->loadModel(environment->getRobot()->getFilename());
59 MMM::MotionWriterXML motionWriter;
60 MMM::MotionList motions;
61 MMM::RapidXMLWriter writer;
62 MMM::RapidXMLWriterNodePtr metaDataNode = writer.createRootNode("RobotTrajectoryDesignerData");
63 metaDataNode->append_string_node("Robot", environment->getRobot()->getFilename());
64 MMM::Motion* kinematicMotion =
65 new MMM::Motion("RobotTrajectoryDesigner", modelptr, modelptr, nullptr);
66
67 MMM::ModelPoseSensor kinematicModelPoseSensor = MMM::ModelPoseSensor("Model");
68 MMM::ModelPoseSensorMeasurementPtr kinematicModelPoseSensorMeasurement =
69 boost::make_shared<MMM::ModelPoseSensorMeasurement>(MMM::ModelPoseSensorMeasurement(
70 0,
71 Eigen::Vector3f(1, 1, 1),
72 MMM::Math::matrix4fToEulerXZY(MMM::Math::quat2eigen4f(0, 0, 0, 0))));
73 kinematicModelPoseSensor.addSensorMeasurement(kinematicModelPoseSensorMeasurement);
74 kinematicMotion->addSensor(boost::make_shared<MMM::ModelPoseSensor>(kinematicModelPoseSensor),
75 0);
76
77 MMM::MotionPtr mptr(kinematicMotion);
78 motions.push_back(mptr);
79
80 //ARMARX_INFO << "Exporting";
81 for (armarx::DesignerTrajectoryPtr trajectory : trajectories)
82 {
83 std::string location(TRAJECTORYDESIGNER_SOURCEDIR);
84 location += "/data/RobotTrajectoryDesigner/Resources/UserWaypoint.xml";
85 MMM::ModelPtr modelptr = modelReader->loadModel(location);
86 MMM::Motion* m =
87 new MMM::Motion(trajectory->getRns()->getName(), modelptr, modelptr, nullptr);
88 MMM::ModelPoseSensor modelPoseSensor =
89 MMM::ModelPoseSensor(trajectory->getRns()->getName());
90 //Get all userWayPoints
91 std::vector<armarx::UserWaypointPtr> userWayPoints = trajectory->getAllUserWaypoints();
92 /*
93 for (armarx::UserWaypointPtr up : userWayPoints)
94 {
95 ARMARX_INFO << "Exporting point:";
96 ARMARX_INFO << up;
97 }
98 */
99 //Add the userWaypoints to the ModelPoseSensor
100 //ARMARX_INFO << "Now creating ModelPoses";
101 MMM::RapidXMLWriterNodePtr trajectoryNode =
102 metaDataNode->append_node(trajectory->getRns()->getName());
103 MMM::RapidXMLWriterNodePtr userWaypointsNode = trajectoryNode->append_node("UserWaypoints");
104 MMM::RapidXMLWriterNodePtr transitionsNode = trajectoryNode->append_node("Transitions");
105 for (unsigned int index = 0; index < userWayPoints.size(); index++)
106 {
107 armarx::UserWaypointPtr userWayPoint = userWayPoints[index];
108 //Get the reached Pose
109 armarx::Vector3BasePtr pos = userWayPoint->getPose()->position;
110 Eigen::Vector3f position = Eigen::Vector3f(pos->x, pos->y, pos->z);
111 armarx::QuaternionBasePtr quaternion = userWayPoint->getPose()->orientation;
112 Eigen::Matrix4f matrix = MMM::Math::quat2eigen4f(
113 quaternion->qx, quaternion->qy, quaternion->qz, quaternion->qw);
114 Eigen::Vector3f orientation = MMM::Math::matrix4fToEulerXZY(matrix);
115 //Create a measurement containing the reached pose
116 MMM::ModelPoseSensorMeasurementPtr measurement =
117 boost::make_shared<MMM::ModelPoseSensorMeasurement>(MMM::ModelPoseSensorMeasurement(
118 userWayPoint->getUserTimestamp(), position, orientation));
119 //Add the measurement to the sensor
120 modelPoseSensor.addSensorMeasurement(measurement);
121 MMM::RapidXMLWriterNodePtr userpointNode =
122 userWaypointsNode->append_node("UserWaypoint");
123 std::string jointAngleString;
124 for (unsigned int j = 0; j < userWayPoints[index]->getJointAngles().size(); j++)
125 {
126 jointAngleString +=
127 boost::lexical_cast<std::string>(userWayPoints[index]->getJointAngles()[j]) +
128 " ";
129 }
130 MMM::RapidXMLWriterNodePtr jointAngleNode = userpointNode->append_string_node(
131 "JointAngles", jointAngleString.substr(0, jointAngleString.size() - 1));
132 MMM::RapidXMLWriterNodePtr timeOptimalTimeStampNode = userpointNode->append_string_node(
133 "TimeOptimalTimeStamp",
134 boost::lexical_cast<std::string>(
135 (userWayPoints[index]->getTimeOptimalTimestamp())));
136 MMM::RapidXMLWriterNodePtr breakpointNode = userpointNode->append_string_node(
137 "IsBreakPoint",
138 std::to_string((int)(userWayPoints[index]->getIsTimeOptimalBreakpoint())));
139 MMM::RapidXMLWriterNodePtr cartesianSelectionNode = userpointNode->append_string_node(
140 "CartesianSelection",
141 std::to_string((int)(userWayPoints[index]->getIKSelection())));
142 }
143 for (unsigned int index = 0; index < trajectory->getNrOfUserWaypoints() - 1; index++)
144 {
145 MMM::RapidXMLWriterNodePtr transitionNode = transitionsNode->append_node("Transition");
146 MMM::RapidXMLWriterNodePtr timeOptimalDurationNode = transitionNode->append_string_node(
147 "TimeOptimalDuration",
148 boost::lexical_cast<std::string>(
149 trajectory->getTransition(index)->getTimeOptimalDuration()));
150 MMM::RapidXMLWriterNodePtr userDurationNode = transitionNode->append_string_node(
151 "UserDuration",
152 boost::lexical_cast<std::string>(
153 trajectory->getTransition(index)->getUserDuration()));
154 MMM::RapidXMLWriterNodePtr interpolationTypeNode = transitionNode->append_string_node(
155 "InterpolationType",
156 std::to_string((int)(trajectory->getTransition(index)->getInterpolationType())));
157 }
158 MMM::RapidXMLWriterNodePtr interBreakpointTrajectoriesNode =
159 trajectoryNode->append_node("InterBreakpointTrajectories");
160 for (unsigned int index = 0; index < trajectory->getInterBreakpointTrajectories().size();
161 index++)
162 {
163 MMM::RapidXMLWriterNodePtr interBreakpointTrajectoryNode =
164 interBreakpointTrajectoriesNode->append_node("InterBreakpointTrajectory");
165 MMM::KinematicSensorPtr interBreakpointSensor(new MMM::KinematicSensor(
166 trajectory->getRns()->getNodeNames(), trajectory->getRns()->getName()));
167 for (double t : trajectory->getInterBreakpointTrajectories()[index]->getTimestamps())
168 {
169 std::vector<double> positions =
170 trajectory->getInterBreakpointTrajectories()[index]->getStates(t, 0);
171 const Eigen::VectorXd vectord =
172 Eigen::VectorXd::Map(positions.data(), positions.size());
173 const Eigen::VectorXf vector = vectord.cast<float>();
174 MMM::KinematicSensorMeasurement* measurement =
175 new MMM::KinematicSensorMeasurement(t, vector);
176 MMM::KinematicSensorMeasurementPtr measurementptr(measurement);
177 interBreakpointSensor->addSensorMeasurement(measurementptr);
178 }
179 interBreakpointSensor->setName(trajectory->getRns()->getName());
180 interBreakpointSensor->appendSensorXML(interBreakpointTrajectoryNode);
181 }
182 modelPoseSensor.setName(trajectory->getRns()->getName());
183 //ARMARX_INFO << "Adding Sensor for " << trajectory->getRns()->getName();
184 m->addSensor(boost::make_shared<MMM::ModelPoseSensor>(modelPoseSensor), 0);
185
186 MMM::MotionPtr mptr(m);
187 motions.push_back(mptr);
188
189 MMM::KinematicSensorPtr kinematicSensor(new MMM::KinematicSensor(
190 trajectory->getRns()->getNodeNames(), trajectory->getRns()->getName()));
191 /*100FPS*/ //for (double t = 0; t < trajectory->getFinalTrajectory()->getLength(); t += 0.01)
192 //Model implements fps conversion for finalTrajectory
193 for (double t : trajectory->getFinalTrajectory()->getTimestamps())
194 {
195 std::vector<double> positions = trajectory->getFinalTrajectory()->getStates(t, 0);
196 const Eigen::VectorXd vectord =
197 Eigen::VectorXd::Map(positions.data(), positions.size());
198 const Eigen::VectorXf vector = vectord.cast<float>();
199 MMM::KinematicSensorMeasurement* measurement =
200 new MMM::KinematicSensorMeasurement(t, vector);
201 MMM::KinematicSensorMeasurementPtr measurementptr(measurement);
202 kinematicSensor->addSensorMeasurement(measurementptr);
203 }
204 kinematicSensor->setName(trajectory->getRns()->getName());
205 kinematicMotion->addSensor(kinematicSensor, 0);
206 }
207 //ARMARX_INFO << "Done with Sensors";
208
209 //Write the motion to the target xml file
210 //ARMARX_INFO << "Writing motion";
211 std::string motionString = motionWriter.toXMLString(motions, file);
212 //ARMARX_INFO << "Wrote Motion";
213 std::string metaDataString = writer.print(false);
214
215 //Cut and merge strings
216 motionString = motionString.substr(0, motionString.find("</MMM>"));
217 //ARMARX_INFO << metaDataString.find("<RobotTrajectoryDesignerData") << "loc";
218 metaDataString = metaDataString.substr(metaDataString.find("<RobotTrajectoryDesignerData"));
219 motionString = motionString + metaDataString + '\n' + "</MMM>";
220
221 //Autoformat strings to xml format
222 QString xmlInput = QString::fromStdString(motionString);
223 QString xmlOutput;
224 QXmlStreamReader qxmlreader(xmlInput);
225 QXmlStreamWriter qxmlwriter(&xmlOutput);
226 qxmlwriter.setAutoFormatting(true);
227 while (!qxmlreader.atEnd())
228 {
229 qxmlreader.readNext();
230 if (!qxmlreader.isWhitespace())
231 {
232 qxmlwriter.writeCurrentToken(qxmlreader);
233 }
234 }
235
236 std::ofstream output;
237 output.open(file);
238 output << xmlOutput.toStdString();
239 output.close();
240}
uint8_t index
void exportTrajectory(std::vector< armarx::DesignerTrajectoryPtr > trajectories, const std::string file)
Exports a trajectory to the target file as a MMM file.
MMMExporter(EnvironmentPtr environment)
std::shared_ptr< Environment > EnvironmentPtr
Definition Environment.h:29
std::shared_ptr< DesignerTrajectory > DesignerTrajectoryPtr
std::shared_ptr< UserWaypoint > UserWaypointPtr