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"
34 #include "../Model/UserWaypoint.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 
42 static constexpr const char* NODE_METADATA = "RobotTrajectoryDesignerData";
43 static constexpr const char* NODE_USERWAYPOINTS = "UserWaypoints";
44 static constexpr const char* NODE_USERWAYPOINT = "UserWaypoint";
45 static constexpr const char* NODE_JOINTANGLES = "JointAngles";
46 static constexpr const char* NODE_TIMEOPTIMALTIMESTAMP = "TimeOptimalTimeStamp";
47 static constexpr const char* NODE_ISBREAKPOINT = "IsBreakPoint";
48 static constexpr const char* NODE_IKSELECTION = "CartesianSelection";
49 
50 static constexpr const char* NODE_TRANSITIONS = "Transitions";
51 static constexpr const char* NODE_TRANSITION = "Transition";
52 static constexpr const char* NODE_TIMEOPTIMALDURATION = "TimeOptimalDuration";
53 static constexpr const char* NODE_USERDURATION = "UserDuration";
54 static constexpr const char* NODE_INTERPOLATIONTYPE = "InterpolationType";
55 
56 static constexpr const char* NODE_INTERBREAKPOINTTRAJECTORIES = "InterBreakpointTrajectories";
57 static constexpr const char* NODE_INTERBREAKPOINTTRAJECTORY = "InterBreakpointTrajectory";
58 
59 static constexpr const char* NODE_ROBOT = "Robot";
60 
61 armarx::MMMImporter::MMMImporter(armarx::EnvironmentPtr environment) : environment(environment)
62 {
63 }
64 
65 std::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  }
177  DesignerTrajectoryPtr trajectory =
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 }
armarx::UserWaypointPtr
std::shared_ptr< UserWaypoint > UserWaypointPtr
Definition: UserWaypoint.h:142
armarx::MMMImporter::MMMImporter
MMMImporter(EnvironmentPtr environment)
Definition: MMMImporter.cpp:61
armarx::MMMImporter::importTrajectory
std::vector< DesignerTrajectoryPtr > importTrajectory(std::string file)
Import a trajectory from the target file in MMM format.
Definition: MMMImporter.cpp:66
armarx::VariantType::Map
const VariantContainerType Map
Definition: StringValueMap.h:263
armarx::UserWaypoint
The UserWaypoint class represents a waypoint of the trajectory.
Definition: UserWaypoint.h:47
armarx::DesignerTrajectory
Definition: DesignerTrajectory.h:36
armarx::IKSelection
VirtualRobot::IKSolver::CartesianSelection IKSelection
Definition: UserWaypoint.h:42
IceInternal::Handle< Trajectory >
armarx::EnvironmentPtr
std::shared_ptr< Environment > EnvironmentPtr
Definition: Environment.h:29
armarx::InterpolationType
InterpolationType
The InterpolationType enum lists all available interpolation types eLinearInterpolation: represents l...
Definition: InterpolationType.h:32
armarx::TransitionPtr
std::shared_ptr< Transition > TransitionPtr
Definition: Transition.h:143
armarx::VariantType::Trajectory
const VariantTypeId Trajectory
Definition: Trajectory.h:44
MMMImporter.h
armarx::channels::KinematicUnitObserver::jointAngles
const KinematicUnitDatafieldCreator jointAngles("jointAngles")
armarx::KinematicSolver::getInstance
static std::shared_ptr< KinematicSolver > getInstance(VirtualRobot::ScenePtr scenario, VirtualRobot::RobotPtr robot)
SINGLETON-FEATURES///////////////////////////////////////////////////////////////////////////////////...
Definition: KinematicSolver.cpp:105
armarx::DesignerTrajectoryPtr
std::shared_ptr< DesignerTrajectory > DesignerTrajectoryPtr
Definition: DesignerTrajectory.h:163
armarx::KinematicSolverPtr
std::shared_ptr< KinematicSolver > KinematicSolverPtr
Definition: KinematicSolver.h:287