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