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 #include <boost/make_shared.hpp>
25 #include "../Model/DesignerTrajectory.h"
26 #include "../Model/UserWaypoint.h"
27 #include <MMM/Motion/Plugin/ModelPosePlugin/ModelPoseSensor.h>
28 #include <MMM/Motion/Plugin/KinematicPlugin/KinematicSensor.h>
29 #include <MMM/Motion/Motion.h>
30 #include <MMM/Motion/MotionWriterXML.h>
31 #include <MMM/Model/Model.h>
32 #include <MMM/Model/ModelReaderXML.h>
33 #include <MMM/RapidXML/rapidxml.hpp>
34 #include <QString>
35 #include <QtXml>
36 #include <clocale>
38 
40 {
41  this->environment = environment;
42 }
43 
44 void armarx::MMMExporter::exportTrajectory(std::vector<armarx::DesignerTrajectoryPtr> trajectories, const std::string file)
45 {
46  //Ensure that locale is en - punctuation for doubles in exported file
47  setlocale(LC_NUMERIC, "en_US.UTF-8");
48  //ARMARX_INFO << "Received " << trajectories.size() << " trajectories";
49  //Create a ModelPoseSensor. The sensors name is the used rns
50  MMM::ModelReaderXMLPtr modelReader(new MMM::ModelReaderXML());
51  MMM::ModelPtr modelptr = modelReader->loadModel(environment->getRobot()->getFilename());
52  MMM::MotionWriterXML motionWriter;
53  MMM::MotionList motions;
54  MMM::RapidXMLWriter writer;
55  MMM::RapidXMLWriterNodePtr metaDataNode = writer.createRootNode("RobotTrajectoryDesignerData");
56  metaDataNode->append_string_node("Robot", environment->getRobot()->getFilename());
57  MMM::Motion* kinematicMotion = new MMM::Motion("RobotTrajectoryDesigner", modelptr, modelptr, nullptr);
58 
59  MMM::ModelPoseSensor kinematicModelPoseSensor = MMM::ModelPoseSensor("Model");
60  MMM::ModelPoseSensorMeasurementPtr kinematicModelPoseSensorMeasurement = boost::make_shared<MMM::ModelPoseSensorMeasurement>(MMM::ModelPoseSensorMeasurement(0, Eigen::Vector3f(1, 1, 1), MMM::Math::matrix4fToEulerXZY(MMM::Math::quat2eigen4f(0, 0, 0, 0))));
61  kinematicModelPoseSensor.addSensorMeasurement(kinematicModelPoseSensorMeasurement);
62  kinematicMotion->addSensor(boost::make_shared<MMM::ModelPoseSensor>(kinematicModelPoseSensor), 0);
63 
64  MMM::MotionPtr mptr(kinematicMotion);
65  motions.push_back(mptr);
66 
67  //ARMARX_INFO << "Exporting";
68  for (armarx::DesignerTrajectoryPtr trajectory : trajectories)
69  {
70  std::string location(TRAJECTORYDESIGNER_SOURCEDIR);
71  location += "/data/RobotTrajectoryDesigner/Resources/UserWaypoint.xml";
72  MMM::ModelPtr modelptr = modelReader->loadModel(location);
73  MMM::Motion* m = new MMM::Motion(trajectory->getRns()->getName(), modelptr, modelptr, nullptr);
74  MMM::ModelPoseSensor modelPoseSensor = MMM::ModelPoseSensor(trajectory->getRns()->getName());
75  //Get all userWayPoints
76  std::vector<armarx::UserWaypointPtr> userWayPoints = trajectory->getAllUserWaypoints();
77  /*
78  for (armarx::UserWaypointPtr up : userWayPoints)
79  {
80  ARMARX_INFO << "Exporting point:";
81  ARMARX_INFO << up;
82  }
83  */
84  //Add the userWaypoints to the ModelPoseSensor
85  //ARMARX_INFO << "Now creating ModelPoses";
86  MMM::RapidXMLWriterNodePtr trajectoryNode = metaDataNode->append_node(trajectory->getRns()->getName());
87  MMM::RapidXMLWriterNodePtr userWaypointsNode = trajectoryNode->append_node("UserWaypoints");
88  MMM::RapidXMLWriterNodePtr transitionsNode = trajectoryNode->append_node("Transitions");
89  for (unsigned int index = 0; index < userWayPoints.size(); index++)
90  {
91  armarx::UserWaypointPtr userWayPoint = userWayPoints[index];
92  //Get the reached Pose
93  armarx::Vector3BasePtr pos = userWayPoint->getPose()->position;
94  Eigen::Vector3f position = Eigen::Vector3f(pos->x, pos->y, pos->z);
95  armarx::QuaternionBasePtr quaternion = userWayPoint->getPose()->orientation;
96  Eigen::Matrix4f matrix = MMM::Math::quat2eigen4f(quaternion->qx, quaternion->qy, quaternion->qz, quaternion->qw);
97  Eigen::Vector3f orientation = MMM::Math::matrix4fToEulerXZY(matrix);
98  //Create a measurement containing the reached pose
99  MMM::ModelPoseSensorMeasurementPtr measurement = boost::make_shared<MMM::ModelPoseSensorMeasurement>(MMM::ModelPoseSensorMeasurement(userWayPoint->getUserTimestamp(), position, orientation));
100  //Add the measurement to the sensor
101  modelPoseSensor.addSensorMeasurement(measurement);
102  MMM::RapidXMLWriterNodePtr userpointNode = userWaypointsNode->append_node("UserWaypoint");
103  std::string jointAngleString;
104  for (unsigned int j = 0; j < userWayPoints[index]->getJointAngles().size(); j++)
105  {
106  jointAngleString += boost::lexical_cast<std::string>(userWayPoints[index]->getJointAngles()[j]) + " ";
107  }
108  MMM::RapidXMLWriterNodePtr jointAngleNode = userpointNode->append_string_node("JointAngles", jointAngleString.substr(0, jointAngleString.size() - 1));
109  MMM::RapidXMLWriterNodePtr timeOptimalTimeStampNode = userpointNode->append_string_node("TimeOptimalTimeStamp", boost::lexical_cast<std::string>((userWayPoints[index]->getTimeOptimalTimestamp())));
110  MMM::RapidXMLWriterNodePtr breakpointNode = userpointNode->append_string_node("IsBreakPoint", std::to_string((int)(userWayPoints[index]->getIsTimeOptimalBreakpoint())));
111  MMM::RapidXMLWriterNodePtr cartesianSelectionNode = userpointNode->append_string_node("CartesianSelection", std::to_string((int)(userWayPoints[index]->getIKSelection())));
112  }
113  for (unsigned int index = 0; index < trajectory->getNrOfUserWaypoints() - 1; index ++)
114  {
115  MMM::RapidXMLWriterNodePtr transitionNode = transitionsNode->append_node("Transition");
116  MMM::RapidXMLWriterNodePtr timeOptimalDurationNode = transitionNode->append_string_node("TimeOptimalDuration", boost::lexical_cast<std::string>(trajectory->getTransition(index)->getTimeOptimalDuration()));
117  MMM::RapidXMLWriterNodePtr userDurationNode = transitionNode->append_string_node("UserDuration", boost::lexical_cast<std::string>(trajectory->getTransition(index)->getUserDuration()));
118  MMM::RapidXMLWriterNodePtr interpolationTypeNode = transitionNode->append_string_node("InterpolationType", std::to_string((int)(trajectory->getTransition(index)->getInterpolationType())));
119  }
120  MMM::RapidXMLWriterNodePtr interBreakpointTrajectoriesNode = trajectoryNode->append_node("InterBreakpointTrajectories");
121  for (unsigned int index = 0; index < trajectory->getInterBreakpointTrajectories().size(); index++)
122  {
123  MMM::RapidXMLWriterNodePtr interBreakpointTrajectoryNode = interBreakpointTrajectoriesNode->append_node("InterBreakpointTrajectory");
124  MMM::KinematicSensorPtr interBreakpointSensor(new MMM::KinematicSensor(trajectory->getRns()->getNodeNames(), trajectory->getRns()->getName()));
125  for (double t : trajectory->getInterBreakpointTrajectories()[index]->getTimestamps())
126  {
127  std::vector<double> positions = trajectory->getInterBreakpointTrajectories()[index]->getStates(t, 0);
128  const Eigen::VectorXd vectord = Eigen::VectorXd::Map(positions.data(), positions.size());
129  const Eigen::VectorXf vector = vectord.cast<float>();
130  MMM::KinematicSensorMeasurement* measurement = new MMM::KinematicSensorMeasurement(t, vector);
131  MMM::KinematicSensorMeasurementPtr measurementptr(measurement);
132  interBreakpointSensor->addSensorMeasurement(measurementptr);
133  }
134  interBreakpointSensor->setName(trajectory->getRns()->getName());
135  interBreakpointSensor->appendSensorXML(interBreakpointTrajectoryNode);
136  }
137  modelPoseSensor.setName(trajectory->getRns()->getName());
138  //ARMARX_INFO << "Adding Sensor for " << trajectory->getRns()->getName();
139  m->addSensor(boost::make_shared<MMM::ModelPoseSensor>(modelPoseSensor), 0);
140 
141  MMM::MotionPtr mptr(m);
142  motions.push_back(mptr);
143 
144  MMM::KinematicSensorPtr kinematicSensor(new MMM::KinematicSensor(trajectory->getRns()->getNodeNames(), trajectory->getRns()->getName()));
145  /*100FPS*///for (double t = 0; t < trajectory->getFinalTrajectory()->getLength(); t += 0.01)
146  //Model implements fps conversion for finalTrajectory
147  for (double t : trajectory->getFinalTrajectory()->getTimestamps())
148  {
149  std::vector<double> positions = trajectory->getFinalTrajectory()->getStates(t, 0);
150  const Eigen::VectorXd vectord = Eigen::VectorXd::Map(positions.data(), positions.size());
151  const Eigen::VectorXf vector = vectord.cast<float>();
152  MMM::KinematicSensorMeasurement* measurement = new MMM::KinematicSensorMeasurement(t, vector);
153  MMM::KinematicSensorMeasurementPtr measurementptr(measurement);
154  kinematicSensor->addSensorMeasurement(measurementptr);
155  }
156  kinematicSensor->setName(trajectory->getRns()->getName());
157  kinematicMotion->addSensor(kinematicSensor, 0);
158  }
159  //ARMARX_INFO << "Done with Sensors";
160 
161  //Write the motion to the target xml file
162  //ARMARX_INFO << "Writing motion";
163  std::string motionString = motionWriter.toXMLString(motions, file);
164  //ARMARX_INFO << "Wrote Motion";
165  std::string metaDataString = writer.print(false);
166 
167  //Cut and merge strings
168  motionString = motionString.substr(0, motionString.find("</MMM>"));
169  //ARMARX_INFO << metaDataString.find("<RobotTrajectoryDesignerData") << "loc";
170  metaDataString = metaDataString.substr(metaDataString.find("<RobotTrajectoryDesignerData"));
171  motionString = motionString + metaDataString + '\n' + "</MMM>";
172 
173  //Autoformat strings to xml format
174  QString xmlInput = QString::fromStdString(motionString);
175  QString xmlOutput;
176  QXmlStreamReader qxmlreader(xmlInput);
177  QXmlStreamWriter qxmlwriter(&xmlOutput);
178  qxmlwriter.setAutoFormatting(true);
179  while (!qxmlreader.atEnd())
180  {
181  qxmlreader.readNext();
182  if (!qxmlreader.isWhitespace())
183  {
184  qxmlwriter.writeCurrentToken(qxmlreader);
185  }
186  }
187 
188  std::ofstream output;
189  output.open(file);
190  output << xmlOutput.toStdString();
191  output.close();
192 }
armarx::UserWaypointPtr
std::shared_ptr< UserWaypoint > UserWaypointPtr
Definition: UserWaypoint.h:137
index
uint8_t index
Definition: EtherCATFrame.h:59
armarx::VariantType::Map
const VariantContainerType Map
Definition: StringValueMap.h:247
armarx::EnvironmentPtr
std::shared_ptr< Environment > EnvironmentPtr
Definition: Environment.h:29
armarx::MMMExporter::exportTrajectory
void exportTrajectory(std::vector< armarx::DesignerTrajectoryPtr > trajectories, const std::string file)
Exports a trajectory to the target file as a MMM file.
Definition: MMMExporter.cpp:44
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:40
CMakePackageFinder.h
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:601
armarx::DesignerTrajectoryPtr
std::shared_ptr< DesignerTrajectory > DesignerTrajectoryPtr
Definition: DesignerTrajectory.h:165
armarx::MMMExporter::MMMExporter
MMMExporter(EnvironmentPtr environment)
Definition: MMMExporter.cpp:39
MMMExporter.h