MMMImporter.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#include "MMMImporter.h"
23
24#include <iostream>
25#include <sstream>
26
27#include <boost/lexical_cast.hpp>
28#include <boost/make_shared.hpp>
29
30#include <VirtualRobot/RobotNodeSet.h>
31
32#include "../Environment.h"
33#include "../KinematicSolver.h"
35#include <MMM/Motion/MotionReaderXML.h>
36#include <MMM/Motion/Plugin/KinematicPlugin/KinematicSensor.h>
37#include <MMM/Motion/Plugin/KinematicPlugin/KinematicSensorFactory.h>
38#include <MMM/Motion/Plugin/ModelPosePlugin/ModelPoseSensor.h>
39#include <MMM/RapidXML/RapidXMLReader.h>
40#include <MMM/RapidXML/rapidxml.hpp>
41
42static constexpr const char* NODE_METADATA = "RobotTrajectoryDesignerData";
43static constexpr const char* NODE_USERWAYPOINTS = "UserWaypoints";
44static constexpr const char* NODE_USERWAYPOINT = "UserWaypoint";
45static constexpr const char* NODE_JOINTANGLES = "JointAngles";
46static constexpr const char* NODE_TIMEOPTIMALTIMESTAMP = "TimeOptimalTimeStamp";
47static constexpr const char* NODE_ISBREAKPOINT = "IsBreakPoint";
48static constexpr const char* NODE_IKSELECTION = "CartesianSelection";
49
50static constexpr const char* NODE_TRANSITIONS = "Transitions";
51static constexpr const char* NODE_TRANSITION = "Transition";
52static constexpr const char* NODE_TIMEOPTIMALDURATION = "TimeOptimalDuration";
53static constexpr const char* NODE_USERDURATION = "UserDuration";
54static constexpr const char* NODE_INTERPOLATIONTYPE = "InterpolationType";
55
56static constexpr const char* NODE_INTERBREAKPOINTTRAJECTORIES = "InterBreakpointTrajectories";
57static constexpr const char* NODE_INTERBREAKPOINTTRAJECTORY = "InterBreakpointTrajectory";
58
59static constexpr const char* NODE_ROBOT = "Robot";
60
61armarx::MMMImporter::MMMImporter(armarx::EnvironmentPtr environment) : environment(environment)
62{
63}
64
65std::vector<armarx::DesignerTrajectoryPtr>
67{
68 //ARMARX_INFO << "Creating MotionReader";
69 std::vector<std::string> libpaths;
70 MMM::MotionReaderXMLPtr motionReader = boost::make_shared<MMM::MotionReaderXML>(libpaths);
71 //ARMARX_INFO << "Getting motions";
72 MMM::MotionList motions = motionReader->loadAllMotions(file, true);
73 //motions.pop_back(); //Do not scan RobotTrajectoryDesignerData
74 //ARMARX_INFO << motions.size() << "Motions detected";
75 std::vector<DesignerTrajectoryPtr> trajectories;
76 std::set<std::string> nodeSets;
77 //ARMARX_INFO << "Scanning Motions";
78 MMM::RapidXMLReaderPtr metaDataReader = MMM::RapidXMLReader::FromFile(file);
79 MMM::RapidXMLReaderNodePtr mmmNode = metaDataReader->getRoot();
80 MMM::RapidXMLReaderNodePtr metaDataNode = mmmNode->first_node(NODE_METADATA);
81 MMM::RapidXMLReaderNodePtr robotNode = metaDataNode->first_node(NODE_ROBOT);
82 if (robotNode->value() != environment->getRobot()->getFilename())
83 {
84 //ARMARX_INFO << "MMM file was exported for another robot";
85 throw InvalidArgumentException("MMM file was exported for another robot");
86 }
87 for (MMM::MotionPtr motion : motions)
88 {
89 if (motion->getSensorsByType("ModelPoseSensor").size() >
90 1) //Assert that one ModelPoseSensor or none (one RobotNodeset or none) are affected
91 {
92 //ARMARX_INFO << "Motion with multiple RobotNodeSets";
93 //Ignore every sensor except the first one
94 }
95 //ARMARX_INFO << "Making ModelPoseSensor from Motion";
96 MMM::SensorPtr sensor = motion->getSensorsByType("ModelPose")[0];
97 if (sensor == NULL)
98 {
99 break;
100 }
101 MMM::ModelPoseSensor mp = dynamic_cast<MMM::ModelPoseSensor&>(
102 *sensor); //Will throw if sensor is not a modelposesensor
103 MMM::ModelPoseSensorPtr modelPoseSensor = boost::make_shared<MMM::ModelPoseSensor>(mp);
104 if (!environment->getRobot()->hasRobotNodeSet(motion->getName()))
105 {
106 //ARMARX_INFO << motion->getName() << " is not a rns";
107 //Skip the motion
108 continue;
109 }
110 //ARMARX_INFO << motion->getName() << " being imported";
111 VirtualRobot::RobotNodeSetPtr rns =
112 environment->getRobot()->getRobotNodeSet(motion->getName());
113 MMM::RapidXMLReaderNodePtr trajectoryNode =
114 metaDataNode->first_node(motion->getName().c_str());
115 MMM::RapidXMLReaderNodePtr userWaypointsNode =
116 trajectoryNode->first_node(NODE_USERWAYPOINTS);
117 MMM::RapidXMLReaderNodePtr transitionsNode = trajectoryNode->first_node(NODE_TRANSITIONS);
118
119 MMM::RapidXMLReaderNodePtr userWaypointNode =
120 userWaypointsNode->first_node(NODE_USERWAYPOINT);
121 MMM::RapidXMLReaderNodePtr transitionNode = transitionsNode->first_node(NODE_TRANSITION);
122 std::vector<float> times = modelPoseSensor->getTimesteps();
123 std::vector<UserWaypointPtr> userPoints;
124 unsigned int breakpoints = 1;
125 //ARMARX_INFO << "Filling in time info";
126 for (double t : times)
127 {
128 if (t != 0)
129 {
130 userWaypointNode = userWaypointNode->next_sibling(NODE_USERWAYPOINT);
131 }
132 MMM::ModelPoseSensorMeasurementPtr measurement =
133 modelPoseSensor->getDerivedMeasurement(t);
134
135
136 //Get metaData
137 //ARMARX_INFO << "Getting meta data";
138 MMM::RapidXMLReaderNodePtr jointAnglesNode =
139 userWaypointNode->first_node(NODE_JOINTANGLES);
140 std::string jointAngleValues = jointAnglesNode->value();
141 std::vector<double> jointAngles;
142 std::istringstream js(jointAngleValues);
143 std::string j;
144 //ARMARX_INFO << "Reading jointangles";
145 while (getline(js, j, ' '))
146 {
147 jointAngles.push_back(boost::lexical_cast<double>(j));
148 }
149 KinematicSolverPtr ks = KinematicSolver::getInstance(NULL, environment->getRobot());
150 PoseBasePtr pose = ks->doForwardKinematicRelative(rns, jointAngles);
151 UserWaypointPtr userPoint = std::make_shared<UserWaypoint>(UserWaypoint(pose));
152 userPoint->setUserTimestamp(t);
153 userPoint->setJointAngles(jointAngles);
154 //ARMARX_INFO << "Reading timeOptimalTimeStamp";
155 MMM::RapidXMLReaderNodePtr timeOptimalTimeStampNode =
156 userWaypointNode->first_node(NODE_TIMEOPTIMALTIMESTAMP);
157 userPoint->setTimeOptimalTimestamp(
158 boost::lexical_cast<double>(timeOptimalTimeStampNode->value()));
159 //ARMARX_INFO << "Reading ikSelection";
160 MMM::RapidXMLReaderNodePtr ikSelectionNode =
161 userWaypointNode->first_node(NODE_IKSELECTION);
162 userPoint->setIKSelection((IKSelection)(std::stoi(ikSelectionNode->value())));
163 //ARMARX_INFO << "Reading isTimeOptimalBreakpoint";
164 MMM::RapidXMLReaderNodePtr isTimeOptimalBreakPointNode =
165 userWaypointNode->first_node(NODE_ISBREAKPOINT);
166 userPoint->setIsTimeOptimalBreakpoint(
167 boost::lexical_cast<bool>(isTimeOptimalBreakPointNode->value()));
168 if (boost::lexical_cast<bool>(isTimeOptimalBreakPointNode->value()))
169 {
170 if (t > 0 && t != times.back())
171 {
172 breakpoints++;
173 }
174 }
175 userPoints.push_back(userPoint);
176 }
178 std::make_shared<DesignerTrajectory>(DesignerTrajectory(userPoints[0], rns));
179 for (unsigned int i = 0; i < userPoints.size(); i++)
180 {
181 if (i > 0)
182 {
183 trajectory->addLastUserWaypoint(userPoints[i]);
184 }
185 }
186 //ARMARX_INFO << "Processing transitions";
187 for (unsigned int i = 0; i < userPoints.size() - 1; i++)
188 {
189 if (i > 0)
190 {
191 transitionNode = transitionNode->next_sibling(NODE_TRANSITION);
192 }
193 TransitionPtr transition = trajectory->getTransition(i);
194 //ARMARX_INFO << "Reading timeOptimalDuration";
195 MMM::RapidXMLReaderNodePtr timeOptimalDurationNode =
196 transitionNode->first_node(NODE_TIMEOPTIMALDURATION);
197 transition->setTimeOptimalDuration(
198 boost::lexical_cast<double>(timeOptimalDurationNode->value()));
199 //ARMARX_INFO << "Reading userDuration";
200 MMM::RapidXMLReaderNodePtr userDurationNode =
201 transitionNode->first_node(NODE_USERDURATION);
202 transition->setUserDuration(boost::lexical_cast<double>(userDurationNode->value()));
203 //ARMARX_INFO << "Reading interpolationType";
204 MMM::RapidXMLReaderNodePtr interpolationTypeNode =
205 transitionNode->first_node(NODE_INTERPOLATIONTYPE);
206 transition->setInterpolationType(
207 (InterpolationType)(std::stoi(interpolationTypeNode->value())));
208 }
209 //ARMARX_INFO << "Processing interbreakpoint trajectories";
210 std::vector<armarx::TrajectoryPtr> interBreakpointTrajectories;
211 MMM::RapidXMLReaderNodePtr interBreakpointTrajectoriesNode =
212 trajectoryNode->first_node(NODE_INTERBREAKPOINTTRAJECTORIES);
213 MMM::RapidXMLReaderNodePtr interBreakpointTrajectoryNode =
214 interBreakpointTrajectoriesNode->first_node(NODE_INTERBREAKPOINTTRAJECTORY);
215 //ARMARX_INFO << breakpoints << " interbreakpoint trajectories";
216 for (unsigned int i = 0; i < breakpoints; i++)
217 {
218 if (i > 0)
219 {
220 interBreakpointTrajectoryNode =
221 interBreakpointTrajectoryNode->next_sibling(NODE_INTERBREAKPOINTTRAJECTORY);
222 }
223 MMM::KinematicSensorFactory factory;
224 MMM::SensorPtr sensorPtr = factory.createSensor(
225 interBreakpointTrajectoryNode->first_node(MMM::XML::NODE_SENSOR));
226 MMM::KinematicSensor interBreakpointTrajectorySensor =
227 dynamic_cast<MMM::KinematicSensor&>(*sensorPtr);
228 std::vector<float> interBreakpointTimeStamps =
229 interBreakpointTrajectorySensor.getTimesteps();
230 std::vector<std::vector<double>> nodeData;
231 //Initialize the vectors for the respective joints, fill in the first timestamp (0)
232 for (unsigned int i = 0; i < rns->getSize(); i++)
233 {
234 MMM::KinematicSensorMeasurementPtr measurement =
235 interBreakpointTrajectorySensor.getDerivedMeasurement(0);
236 nodeData.push_back({measurement->getJointAngles()[i]});
237 }
238 //Fill in the data for all other timestamps into the now existing joint values
239 for (float t : interBreakpointTimeStamps)
240 {
241 if (t == interBreakpointTimeStamps[0])
242 {
243 continue;
244 }
245 MMM::KinematicSensorMeasurementPtr measurement =
246 interBreakpointTrajectorySensor.getDerivedMeasurement(t);
247 Eigen::VectorXf floatPositions = measurement->getJointAngles();
248 std::vector<double> doublePositions;
249 for (int j = 0; j < floatPositions.size(); j++)
250 {
251 doublePositions.push_back(floatPositions[j]);
252 }
253 Eigen::VectorXd positions =
254 Eigen::VectorXd::Map(&doublePositions[0], doublePositions.size());
255 for (unsigned int i = 0; i < positions.size(); i++)
256 {
257 nodeData[i].push_back(positions[i]);
258 }
259 }
260 //Get the correct names for the dimensions
261 Ice::StringSeq dimensionNames = rns->getNodeNames();
262 //Construct the armarx Trajectory from the given data
263 std::vector<double> doubleTimeStamps(interBreakpointTimeStamps.begin(),
264 interBreakpointTimeStamps.end());
265 TrajectoryPtr traj = new Trajectory(nodeData, doubleTimeStamps, dimensionNames);
266 interBreakpointTrajectories.push_back(traj);
267 }
268 trajectory->setInterBreakpointTrajectories(interBreakpointTrajectories);
269 trajectories.push_back(trajectory);
270 if (nodeSets.find(rns->getName()) != nodeSets.end())
271 {
272 //ARMARX_INFO << "Multiple motions using the same RobotNodeSet";
273 trajectories.clear();
274 return trajectories;
275 }
276 nodeSets.insert(rns->getName());
277 }
278 //ARMARX_INFO << trajectories.size() << "RobotNodeSet Trajectories have been found and could be imported";
279 for (DesignerTrajectoryPtr designerTrajectory : trajectories)
280 {
281 //ARMARX_INFO << "Trajectory with " << designerTrajectory->getAllUserWaypoints().size() << " points";
282 }
283 return trajectories;
284 throw("Not implemented");
285}
static std::shared_ptr< KinematicSolver > getInstance(VirtualRobot::ScenePtr scenario, VirtualRobot::RobotPtr robot)
SINGLETON-FEATURES///////////////////////////////////////////////////////////////////////////////////...
std::vector< DesignerTrajectoryPtr > importTrajectory(std::string file)
Import a trajectory from the target file in MMM format.
MMMImporter(EnvironmentPtr environment)
The Trajectory class represents n-dimensional sampled trajectories.
Definition Trajectory.h:77
The UserWaypoint class represents a waypoint of the trajectory.
std::shared_ptr< KinematicSolver > KinematicSolverPtr
VirtualRobot::IKSolver::CartesianSelection IKSelection
IceInternal::Handle< Trajectory > TrajectoryPtr
Definition Trajectory.h:52
std::shared_ptr< Environment > EnvironmentPtr
Definition Environment.h:29
InterpolationType
The InterpolationType enum lists all available interpolation types eLinearInterpolation: represents l...
std::shared_ptr< Transition > TransitionPtr
Definition Transition.h:143
std::shared_ptr< DesignerTrajectory > DesignerTrajectoryPtr
std::shared_ptr< UserWaypoint > UserWaypointPtr