ocra-recipes
Doxygen documentation for the ocra-recipes repository
TaskConstructionManager.cpp
Go to the documentation of this file.
2 
3 using namespace ocra;
4 
5 
7 {
8 
9 }
10 
11 TaskConstructionManager::TaskConstructionManager(Model::Ptr model, Controller::Ptr controller, std::vector<TaskBuilderOptions> optionsVector)
12 {
13  addTasksToController(model, controller, optionsVector);
14 }
15 
16 TaskConstructionManager::TaskConstructionManager(Model::Ptr model, Controller::Ptr controller, const std::string& optionsXmlFilePath)
17 {
18  addTasksToController(model, controller, parseTaskOptionsFromXml(optionsXmlFilePath));
19 }
20 
22 {
23 
24 }
25 
26 void TaskConstructionManager::addTasksToController(Model::Ptr model, Controller::Ptr controller, std::vector<TaskBuilderOptions> optionsVector)
27 {
28  for(auto options : optionsVector){
29  TaskBuilder::Ptr builder = getBuilder(options, model);
30  if (builder) {
31  builder->buildTask();
32  controller->addTask(builder->getTask());
33  builder->setTaskParameters();
34  }
35  }
36 }
37 
38 TaskBuilder::Ptr TaskConstructionManager::getBuilder(TaskBuilderOptions options, Model::Ptr model)
39 {
40  TaskBuilder::Ptr TaskBldrPtr;
41  correctArticularVariables(options, model);
42 
43  if (options.taskType=="cartesian") {
44  TaskBldrPtr = std::make_shared<CartesianTaskBuilder>(options, model);
45  } else if (options.taskType == "pose") {
46  TaskBldrPtr = std::make_shared<PoseTaskBuilder>(options, model);
47  } else if (options.taskType == "orientation") {
48  TaskBldrPtr = std::make_shared<OrientationTaskBuilder>(options, model);
49  } else if (options.taskType == "com") {
50  TaskBldrPtr = std::make_shared<ComTaskBuilder>(options, model);
51  } else if (options.taskType == "fullposture") {
52  TaskBldrPtr = std::make_shared<FullPostureTaskBuilder>(options, model);
53  } else if (options.taskType == "partialposture") {
54  TaskBldrPtr = std::make_shared<PartialPostureTaskBuilder>(options, model);
55  } else if (options.taskType == "pointcontact") {
56  TaskBldrPtr = std::make_shared<PointContactTaskBuilder>(options, model);
57  } else {
58  std::cout << "[ERROR] (TaskConstructionManager::getBuilder): The task type: '" << options.taskType << "' does not exist. Returning NULL." << std::endl;
59  }
60  return TaskBldrPtr;
61 }
62 
63 std::vector<TaskBuilderOptions> TaskConstructionManager::parseTaskOptionsFromXml(const std::string& optionsXmlFilePath)
64 {
65  std::vector<TaskBuilderOptions> emptyOptionsVector;
66  if(boost::filesystem::exists(optionsXmlFilePath.c_str()))
67  {
68  TiXmlDocument newTasksFile( optionsXmlFilePath.c_str() );
69  if(!newTasksFile.LoadFile())
70  {
71  std::cout << "[ERROR] (TaskConstructionManager::parseTaskOptionsFromXml): Could not read the XML file: " << optionsXmlFilePath << std::endl;
72  return emptyOptionsVector;
73  }
74  else
75  return parseTaskOptionsFromXml(&newTasksFile);
76  }
77  else
78  {
79  std::cout << "[ERROR] (TaskConstructionManager::parseTaskOptionsFromXml): Filepath provided does not exist: "<< optionsXmlFilePath << std::endl;
80  return emptyOptionsVector;
81  }
82 }
83 
84 std::vector<TaskBuilderOptions> TaskConstructionManager::parseTaskOptionsFromXml(TiXmlDocument* newTasksFile)
85 {
86  std::vector<TaskBuilderOptions> optionsVector;
87 
88  if(newTasksFile == NULL) {
89  std::cout << "[ERROR] newTasksFile argument is NULL" << std::endl;
90  } else {
91  for(TiXmlElement* xmlTask = newTasksFile->FirstChildElement("task"); xmlTask != NULL; xmlTask = xmlTask->NextSiblingElement("task")) {
92  TaskBuilderOptions options;
93  if(parseTaskXmlElement(xmlTask, options)) {
94  optionsVector.push_back(options);
95  }
96  }
97  }
98  return optionsVector;
99 }
100 
101 bool TaskConstructionManager::parseTaskXmlElement(TiXmlElement* xmlTask, TaskBuilderOptions& options)
102 {
103  if (parseTaskNameAndType(xmlTask, options)) {
104 
105  for(TiXmlElement* taskElem = xmlTask->FirstChildElement(); taskElem != NULL; taskElem = taskElem->NextSiblingElement()) {
106 
107  std::string currentElemString = taskElem->Value();
108 
109  if (currentElemString == "params") {
110  parseParamXmlElement(taskElem, options);
111  } else if (currentElemString == "offset") {
112  parseOffsetXmlElement(taskElem, options);
113  } else if (currentElemString == "desired") {
114  parseDesiredXmlElement(taskElem, options);
115  } else if (currentElemString == "segment") {
116  parseSegmentXmlElement(taskElem, options);
117  } else if (currentElemString == "jointIndexes") {
118  parseJointIndexesXmlElement(taskElem, options);
119  } else if (currentElemString == "joints") {
120  parseJointsXmlElement(taskElem, options);
121  } else if (currentElemString == "weights") {
122  parseWeightsXmlElement(taskElem, options);
123  } else {
124  std::cout << "[WARNING] (parseTaskOptionsFromXml): Found a task manager tag --> "<< currentElemString <<" <-- that doesn't match any known tags. Ignoring." << std::endl;
125  }
126  }
127  return true;
128  }
129  return false;
130 }
131 
132 bool TaskConstructionManager::parseTaskNameAndType(TiXmlElement* xmlTask, TaskBuilderOptions& options)
133 {
134  if ( (xmlTask->Attribute("name") != NULL) && (xmlTask->Attribute("type") != NULL) ) {
135  options.taskName = xmlTask->Attribute("name");
136  options.taskType = util::convertToLowerCase(xmlTask->Attribute("type"));
137  return true;
138  } else {
139  return false;
140  }
141 }
142 
143 void TaskConstructionManager::parseParamXmlElement(TiXmlElement* paramElement, TaskBuilderOptions& options)
144 {
145  // Parse the stiffness gain
146  if (paramElement->QueryDoubleAttribute("kp", &options.kp)==TIXML_NO_ATTRIBUTE) {
147  options.kp=0.0;
148  }
149 
150  // Parse the damping gain
151  if (paramElement->QueryDoubleAttribute("kd", &options.kd)==TIXML_NO_ATTRIBUTE) {
152  if (options.kp > 0.0) {
153  options.kd=2.0*sqrt(options.kp);
154  }else{options.kd=0.0;}
155  }
156 
157  // Parse the scalar weight
158  if (paramElement->QueryDoubleAttribute("weight", &options.weight)==TIXML_NO_ATTRIBUTE) {
159  options.weight=0.0; options.useWeightVectorConstructor=false;
160  } else {
161  options.useWeightVectorConstructor=false;
162  }
163 
164  // Parse the hierarchy level
165  if (paramElement->QueryIntAttribute("hierarchyLevel", &options.hierarchyLevel)==TIXML_NO_ATTRIBUTE) {
166  options.hierarchyLevel=-1;
167  }
168 
169  // Parse the cartesian axes to be controlled. Because ECartesianDof is not a standard type we first get the user's string then convert it to the proper type.
170  std::string axesString;
171  if (paramElement->QueryStringAttribute("axes", &axesString)==TIXML_NO_ATTRIBUTE) {
172  options.axes=ECartesianDof::XYZ;
173  } else {
174  options.axes=utils::cartesianDofFromString(axesString);
175  }
176 
177  // Parse the friction coefficient mu
178  if (paramElement->QueryDoubleAttribute("mu", &options.mu)==TIXML_NO_ATTRIBUTE) {
179  options.mu=1.0;
180  }
181 
182  // Parse the friction parameter marging
183  if (paramElement->QueryDoubleAttribute("margin", &options.margin)==TIXML_NO_ATTRIBUTE) {
184  options.margin=0.05;
185  }
186 
187  // TODO: Remove...
188  if (paramElement->Attribute("usesYarp") != NULL) {
189  bool yarpBool;
190  std::string yarpString = std::string(paramElement->Attribute("usesYarp"));
191  if (yarpString=="true" || yarpString=="1") {
192  yarpBool = true;
193  }
194  else if (yarpString=="false" || yarpString=="0") {
195  yarpBool = false;
196  }
197  else {
198  yarpBool = true;
199  }
200  options.usesYarp = yarpBool;
201  } else {
202  options.usesYarp=true;
203  }
204 
205 
206 }
207 
208 void TaskConstructionManager::parseOffsetXmlElement(TiXmlElement* offsetElement, TaskBuilderOptions& options)
209 {
210  // If the offset is written out in the element then convert it to a displacement.
211  if (offsetElement->GetText() != NULL) {
212  options.offset = util::eigenVectorToDisplacementd(util::stringToVectorXd(offsetElement->GetText()));
213  } else {
214  // If the displacement is given by attributes are there then parse them otherwise it will be a no-offset offset...
216  }
217 }
218 
219 void TaskConstructionManager::parseDesiredXmlElement(TiXmlElement* desiredElement, TaskBuilderOptions& options)
220 {
221  if (desiredElement->GetText() != NULL) {
222  options.desired = util::stringToVectorXd(desiredElement->GetText());
223  } else {
224  options.desired = util::stringToVectorXd(util::getDisplacementArgs(desiredElement).c_str());
225  }
226 }
227 
228 void TaskConstructionManager::parseSegmentXmlElement(TiXmlElement* segmentElement, TaskBuilderOptions& options)
229 {
230  options.segment = segmentElement->GetText();
231 }
232 
233 void TaskConstructionManager::parseJointIndexesXmlElement(TiXmlElement* jointIndexesElement, TaskBuilderOptions& options)
234 {
235  options.jointIndexes = util::stringToVectorXi(jointIndexesElement->GetText());
236 }
237 
238 void TaskConstructionManager::parseJointsXmlElement(TiXmlElement* jointsElement, TaskBuilderOptions& options)
239 {
240  std::string jointIndexString, indexDesiredValueString, nameDesiredValueString, indexWeightString, nameWeightString;
241  for(TiXmlElement* jointElem = jointsElement->FirstChildElement("joint"); jointElem != NULL; jointElem = jointElem->NextSiblingElement("joint"))
242  {
243  if ( (jointElem->Attribute("name") != NULL) || (jointElem->Attribute("index") != NULL) )
244  {
245  if(jointElem->Attribute("index") != NULL)
246  {
247  jointIndexString += jointElem->Attribute("index");
248  jointIndexString += " ";
249  if (jointElem->Attribute("des") != NULL)
250  {
251  indexDesiredValueString += jointElem->Attribute("des");
252  indexDesiredValueString += " ";
253  }else{
254  indexDesiredValueString += "-1000.0 ";
255  }
256  if (jointElem->Attribute("weight") != NULL)
257  {
258  indexWeightString += jointElem->Attribute("weight");
259  indexWeightString += " ";
260  options.useWeightVectorConstructor = true;
261 
262  }else{
263  indexWeightString += "-1.0 ";
264  }
265  }
266 
267  else if(jointElem->Attribute("name") != NULL)
268  {
269  options.jointNames.push_back(jointElem->Attribute("name"));
270  if (jointElem->Attribute("des") != NULL)
271  {
272  nameDesiredValueString += jointElem->Attribute("des");
273  nameDesiredValueString += " ";
274  }else{
275  nameDesiredValueString += "-1000.0 ";
276  }
277  if (jointElem->Attribute("weight") != NULL)
278  {
279  nameWeightString += jointElem->Attribute("weight");
280  nameWeightString += " ";
281  options.useWeightVectorConstructor = true;
282 
283  }else{
284  nameWeightString += "-1.0 ";
285  }
286  }
287 
288  }
289 
290  options.jointIndexes = util::stringToVectorXi(jointIndexString.c_str());
291  options.indexDesired = util::stringToVectorXd(indexDesiredValueString.c_str());
292  options.nameDesired = util::stringToVectorXd(nameDesiredValueString.c_str());
293  options.indexWeightVector = util::stringToVectorXd(indexWeightString.c_str());
294  options.nameWeightVector = util::stringToVectorXd(nameWeightString.c_str());
295  }
296 }
297 
298 void TaskConstructionManager::parseWeightsXmlElement(TiXmlElement* weightsElement, TaskBuilderOptions& options)
299 {
300  options.useWeightVectorConstructor = true;
301  options.weightVector = util::stringToVectorXd(weightsElement->GetText());
302 }
303 
304 void TaskConstructionManager::correctArticularVariables(TaskBuilderOptions& options, Model::Ptr model)
305 {
306  int sizeDof = model->nbInternalDofs();
307 
308  int sizeDesired = options.desired.rows();
309  int sizeIndexDesired = options.indexDesired.rows();
310  int sizeNameDesired = options.nameDesired.rows();
311  int sizeWeightVector = options.weightVector.rows();
312  int sizeIndexWeightVector = options.indexWeightVector.rows();
313  int sizeNameWeightVector = options.nameWeightVector.rows();
314  int sizeJointIndexes = options.jointIndexes.rows();
315  int sizeJointNames = options.jointNames.size();
316 
317 
318  if ((options.taskType == "fullposture") || (options.taskType == "partialposture"))
319  {
320  int sizeDofConcerned;
321  if(options.taskType == "fullposture")
322  {
323  sizeDofConcerned = sizeDof;
324  }else if(options.taskType == "partialposture"){
325  sizeDofConcerned = sizeIndexDesired+sizeNameDesired;
326  }
327 
328  if (sizeDesired == 0)
329  {
330  if(options.taskType == "fullposture")
331  {
332  options.desired = model->getJointPositions();
333  }else if(options.taskType == "partialposture"){
334  options.desired = Eigen::VectorXd::Zero(sizeDofConcerned);
335  }
336  }
337  else
338  {
339  if (sizeDesired == 1)
340  {
341  options.desired = Eigen::VectorXd::Constant(sizeDofConcerned, options.desired[0]);
342  }
343  else if (sizeDesired != sizeDofConcerned)
344  {
345  if(options.taskType == "fullposture")
346  {
347  options.desired = model->getJointPositions();
348  }else if(options.taskType == "partialposture"){
349  options.desired = Eigen::VectorXd::Zero(sizeDofConcerned);
350  }
351  }
352  }
353  if (options.useWeightVectorConstructor)
354  {
355  if (sizeWeightVector != sizeDofConcerned)
356  {
357  options.weightVector = Eigen::VectorXd::Constant(sizeDofConcerned, options.weight);
358  }
359  }
360 
361 
362  if(options.taskType == "fullposture")
363  {
364  if (sizeJointIndexes>0 && sizeJointIndexes == sizeIndexDesired)
365  {
366  for(int i=0; i<sizeJointIndexes; i++)
367  {
368  if(options.indexDesired(i) != -1000.0)
369  {
370  options.desired(options.jointIndexes(i)) = options.indexDesired(i);
371  }
372  if (options.useWeightVectorConstructor)
373  {
374  if (options.indexWeightVector(i) >= 0.0)
375  {
376  options.weightVector(options.jointIndexes(i)) = options.indexWeightVector(i);
377  }
378  }
379  }
380  }
381  if (sizeJointNames>0 && sizeJointNames == sizeNameDesired)
382  {
383  for(int i=0; i<sizeJointNames; i++)
384  {
385  if(options.nameDesired(i) != -1000.0)
386  {
387  options.desired(model->getDofIndex(options.jointNames[i])) = options.nameDesired(i);
388  }
389  if (options.useWeightVectorConstructor)
390  {
391  if (options.nameWeightVector(i) >= 0.0)
392  {
393  options.weightVector(model->getDofIndex(options.jointNames[i])) = options.nameWeightVector(i);
394  }
395  }
396  }
397  }
398  }
399  else if(options.taskType == "partialposture")
400  {
401  Eigen::VectorXi jointIndexesTemp(sizeDofConcerned);
402  int indexCounter = 0;
403 
404  if (sizeJointIndexes>0 && sizeJointIndexes == sizeIndexDesired)
405  {
406  for(int i=0; i<sizeJointIndexes; i++)
407  {
408  jointIndexesTemp(indexCounter) = options.jointIndexes(i);
409  if(options.indexDesired(i) != -1000.0)
410  {
411  options.desired(indexCounter) = options.indexDesired(i);
412  }
413  if (options.useWeightVectorConstructor)
414  {
415  if (options.indexWeightVector(i) >= 0.0)
416  {
417  options.weightVector(indexCounter) = options.indexWeightVector(i);
418  }
419  }
420  indexCounter++;
421  }
422  }
423  if (sizeJointNames>0 && sizeJointNames == sizeNameDesired)
424  {
425  for(int i=0; i<sizeJointNames; i++)
426  {
427  jointIndexesTemp(indexCounter) = model->getDofIndex(options.jointNames[i]);
428  if(options.nameDesired(i) == -1000.0)
429  {
430  options.desired(indexCounter) = model->getJointPositions()(model->getDofIndex(options.jointNames[i]));
431  }
432  else{
433  options.desired(indexCounter) = options.nameDesired(i);
434  }
435  if (options.useWeightVectorConstructor)
436  {
437  if (options.nameWeightVector(i) >= 0.0)
438  {
439  options.weightVector(indexCounter) = options.nameWeightVector(i);
440  }
441  }
442  indexCounter++;
443  }
444  }
445  options.jointIndexes.resize(sizeDofConcerned);
446  options.jointIndexes = jointIndexesTemp;
447 
448  }
449 
450  }
451 
452 
453 
454 
455 
456 }
Eigen::VectorXd indexWeightVector
Optimization-based Robot Controller namespace. a library of classes to write and solve optimization p...
std::vector< TaskBuilderOptions > parseTaskOptionsFromXml(const std::string &optionsXmlFilePath)
ECartesianDof cartesianDofFromString(const std::string &dofString)
Definition: ControlEnum.h:58
Eigen::Displacementd eigenVectorToDisplacementd(const Eigen::VectorXd &eigenVector)
std::vector< std::string > jointNames
Eigen::VectorXd stringToVectorXd(const char *valueString)
Eigen::VectorXi stringToVectorXi(const char *valueString)
Eigen::VectorXd nameWeightVector
void addTasksToController(Model::Ptr model, Controller::Ptr controller, std::vector< TaskBuilderOptions > optionsVector)
std::string getDisplacementArgs(TiXmlElement *xmlElem)
Definition: XmlUtilities.h:13
Eigen::Displacementd offset
TaskBuilder::Ptr getBuilder(TaskBuilderOptions options, Model::Ptr model)
std::string convertToLowerCase(const std::string &originalString)