ocra-recipes
Doxygen documentation for the ocra-recipes repository
GHCJTController.cpp
Go to the documentation of this file.
1 
10 
11 #include <iostream>
12 
17 #include "ocra/control/FullState.h"
18 #include "ocra/control/Feature.h"
19 #include "ocra/control/Model.h"
21 
22 #include "gocra/Tasks/GHCJTTask.h"
23 #include "gocra/Performances.h"
25 //#include <QDebug>
26 
27 namespace gocra
28 {
29 
30 
31 
32 
34 {
38  bool useGrav;
39 
40  // STATIC EQUILIBRIUM EQUATION
42 
43  std::vector< GHCJTTask* > createdTask;
44  std::vector< GHCJTTask* > activeTask;
48 
49  // PERFORMANCE RECORDERS
52 
53  Pimpl(const std::string& name, Model& m, ocra::OneLevelSolver& s, bool useGrav)
54  : innerModel(m)
55  , innerSolver(s)
56  , isFreeFloating(m.nbDofs() - m.nbInternalDofs()>0)
57  , useGrav(useGrav)
58  , seConstraint( new SumOfLinearFunctions(m.nbDofs() - m.nbInternalDofs()) )
59  , createdTask()
60  , activeTask()
61  , nbActiveTask(0)
62  , totalActiveTaskDim(0)
63  , augmentedJacobian(MatrixXd::Zero(1,m.nbDofs()))
64  {
65 
66 // createdTask.reserve(20);
67 // activeTask.reserve(20);
68  }
69 
71  {
72 
73  }
74 };
75 
76 
77 
86  : Controller(ctrlName, innerModel)
87  , pimpl( new Pimpl(ctrlName, innerModel, innerSolver, useGrav) )
88 {
89  if (pimpl->isFreeFloating)
90  pimpl->innerSolver.addConstraint(pimpl->seConstraint.getConstraint());
91 }
92 
96 {
97 
98  for (size_t i=0; i<pimpl->createdTask.size(); ++i)
99  {
100  pimpl->createdTask[i]->disconnectFromController();
101  delete pimpl->createdTask[i];
102  }
103 
104  if (pimpl->isFreeFloating)
105  pimpl->innerSolver.removeConstraint(pimpl->seConstraint.getConstraint());
106 
107 }
108 
109 
114 {
115  return pimpl->innerModel;
116 }
117 
122 {
123  return pimpl->innerSolver;
124 }
125 
126 
128 {
129 
130 }
131 
132 
133 
135 {
136  pimpl->innerSolver.addConstraint(constraint);
137 }
138 
139 
141 {
142  pimpl->innerSolver.removeConstraint(constraint);
143 }
144 
145 /*
146 void GHCJTController::addConstraint(gOcraConstraint& constraint) const
147 {
148  pimpl->innerSolver.addConstraint(constraint.getConstraint());
149 }
150 
151 
152 void GHCJTController::removeConstraint(gOcraConstraint& constraint) const
153 {
154  pimpl->innerSolver.removeConstraint(constraint.getConstraint());
155 }
156 */
157 
158 
164 {
165  try {
166  GHCJTTask& ctask = dynamic_cast<GHCJTTask&>(task);
167  ctask.connectToController(pimpl->innerSolver, pimpl->seConstraint.getFunction());
168  }
169  catch(const std::exception & e) {
170  std::cerr << e.what() ;
171  throw std::runtime_error("[GHCJTController::doAddTask] cannot add task to controller (wrong type)");
172  }
173 }
174 
181 {
182  throw std::runtime_error("[GHCJTController::doAddTask] not implemented");
183 }
184 
185 
186 
187 
188 GHCJTTask& GHCJTController::createGHCJTTask(const std::string& name, Feature::Ptr feature, Feature::Ptr featureDes) const
189 {
190  auto taskPtr = createTask(name, feature, featureDes).get();
191  return dynamic_cast<GHCJTTask&>(*taskPtr);
192 }
193 
194 GHCJTTask& GHCJTController::createGHCJTTask(const std::string& name, Feature::Ptr feature) const
195 {
196  auto taskPtr = createTask(name, feature).get();
197  return dynamic_cast<GHCJTTask&>(*taskPtr);
198 }
199 
200 GHCJTTask& GHCJTController::createGHCJTContactTask(const std::string& name, PointContactFeature::Ptr feature, double mu, double margin) const
201 {
202  auto taskPtr = createContactTask(name, feature, mu, margin).get();
203  return dynamic_cast<GHCJTTask&>(*taskPtr);
204 }
205 
206 
207 
208 
209 
220 Task* GHCJTController::doCreateTask(const std::string& name, Feature::Ptr feature, Feature::Ptr featureDes) const
221 {
222  GHCJTTask* nTask = new GHCJTTask(name, pimpl->innerModel, feature, featureDes);
223  pimpl->createdTask.push_back(nTask);
224  return nTask;
225 }
226 
236 Task* GHCJTController::doCreateTask(const std::string& name, Feature::Ptr feature) const
237 {
238  GHCJTTask* nTask = new GHCJTTask(name, pimpl->innerModel, feature);
239  pimpl->createdTask.push_back(nTask);
240  return nTask;
241 }
242 
254 Task* GHCJTController::doCreateContactTask(const std::string& name, PointContactFeature::Ptr feature, double mu, double margin) const
255 {
256  GHCJTTask* nTask = new GHCJTTask(name, pimpl->innerModel, feature);
257  pimpl->createdTask.push_back(nTask);
258  return nTask;
259 }
260 
261 
262 
263 
264 //MOST IMPORTANT FUNCTION: COMPUTE OUTPUT TORQUE
272 void GHCJTController::doComputeOutput(Eigen::VectorXd& tau)
273 {
274  pimpl->updateTasksRecorder.initializeTime();
275 
276  const std::vector<Task*>& tasks = getActiveTasks();
277 
278  if(tasks.size()==0)
279  {
280  tau.resize(pimpl->innerModel.nbInternalDofs());
281  tau.setZero();
282  return;
283  }
284  if (pimpl->useGrav && pimpl->isFreeFloating)
285  {
286  // linear function : Ax + b = 0
287  VectorXd b = pimpl->innerModel.getGravityTerms().head(pimpl->innerModel.nbDofs() - pimpl->innerModel.nbInternalDofs());
288 
289  pimpl->seConstraint.getFunction().changeb(b);
290 
291  }
292  for(size_t i=0; i< tasks.size(); ++i)
293  {
294  GHCJTTask* cTask = static_cast<GHCJTTask*>(tasks[i]); // addTask throws if this cast is not possible
295  cTask->update();
296 
297  }
298 
299 
300  pimpl->updateTasksRecorder.saveRelativeTime();
301  pimpl->solveProblemRecorder.initializeTime();
302  if(!pimpl->innerSolver.solve().info)
303  {
304  if(pimpl->useGrav)
305  tau = pimpl->innerModel.getGravityTerms().tail(pimpl->innerModel.nbInternalDofs());
306 
307  for(int i = 0; i < tasks.size(); ++i)
308  {
309  GHCJTTask& currentTask = static_cast<GHCJTTask&>(*tasks[i]);
310 
311  if(!currentTask.isBodyContactConstraint())
312  {
313 
314  if(currentTask.isPointContactTask())
315  tau += currentTask.getJacobian().transpose().bottomRows(pimpl->innerModel.nbInternalDofs()) * currentTask.getVariable().getValue();
316  else
317  tau += (currentTask.getProjector()*currentTask.getJacobian().transpose()).bottomRows(pimpl->innerModel.nbInternalDofs()) * currentTask.getVariable().getValue();
318 
319  }
320 
321  }
322  }
323  else
324  {
325  setErrorMessage("solver error");
327  }
328  pimpl->solveProblemRecorder.saveRelativeTime();
329 }
330 
341 void GHCJTController::writePerformanceInStream(std::ostream& outstream, bool addCommaAtEnd) const
342 {
343  pimpl->updateTasksRecorder.writeInStream("controller_update_tasks", outstream, true);
344  pimpl->solveProblemRecorder.writeInStream("controller_solve_problem", outstream, true);
345  pimpl->innerSolver.writePerformanceInStream(outstream, addCommaAtEnd);
346 }
347 
348 
349 
372 {
373  std::ostringstream osstream;
374  // Write it in a json style
375  osstream <<"{\n";
376  writePerformanceInStream(osstream, false);
377  osstream <<"}";
378  return osstream.str();
379 }
380 
382 {
383  pimpl->activeTask.clear();
384  int totalTaskDim = 0;
385  for (int i=0; i<pimpl->createdTask.size(); ++i)
386  {
387  if (pimpl->createdTask[i]->isActiveAsObjective())
388  {
389  if(!pimpl->createdTask[i]->isPointContactTask())
390  {
391  pimpl->activeTask.push_back(pimpl->createdTask[i]);
392  totalTaskDim += pimpl->createdTask[i]->getTaskDimension();
393  pimpl->createdTask[i]->setWeight(1);
394  }
395  }
396  }
397  pimpl->nbActiveTask = pimpl->activeTask.size();
398  pimpl->totalActiveTaskDim = totalTaskDim;
399 
402 
403 }
404 
406 {
407  int nDof = pimpl->innerModel.nbDofs();
408  MatrixXd jacobian=MatrixXd::Zero(pimpl->totalActiveTaskDim, nDof);
409  int rowindex = 0;
410  int taskdim;
411 // int index = pimpl->innerModel.hasFixedRoot() ? 0 : 6;
412 
413  for (int i=0; i<pimpl->nbActiveTask; ++i)
414  {
415  taskdim = pimpl->activeTask[i]->getDimension();
416  jacobian.block(rowindex,0, taskdim, nDof)=pimpl->activeTask[i]->getJacobian();
417  rowindex += taskdim;
418  }
419  pimpl->augmentedJacobian = jacobian;
420 }
421 
423 {
425  const int nDof = pimpl->innerModel.nbDofs();
426  MatrixXd proj(nDof,nDof);
427  MatrixXd taskiProj(nDof,nDof);
428  for (int i=0; i<pimpl->nbActiveTask; ++i)
429  {
430 // std::cout<<"tp"<<i<<"="<<pimpl->activeTask[i]->getPriority()<<std::endl;
431  computeProjector(pimpl->activeTask[i]->getPriority(), pimpl->augmentedJacobian, proj);
432  pimpl->activeTask[i]->setProjector(proj);
433  computeTaskiProjector(pimpl->activeTask[i]->getJacobian(), taskiProj);
434  pimpl->activeTask[i]->setTaskiProjector(taskiProj);
435  }
436 }
437 std::vector< GHCJTTask* >& GHCJTController::getActiveTask()
438 {
439  return pimpl->activeTask;
440 }
441 
443 {
444  return pimpl->nbActiveTask;
445 }
446 
448 {
449  return pimpl->totalActiveTaskDim;
450 }
451 
453 {
454  int dim;
455  int dim_alpha = 0;
456  for (int i=0; i<pimpl->activeTask.size(); ++i)
457  {
458  dim = pimpl->activeTask[i]->getTaskDimension();
459  pimpl->activeTask[i]->setIndexBegin(dim_alpha);
460  pimpl->activeTask[i]->setIndexEnd(dim_alpha + dim);
461  dim_alpha += dim;
462  }
463 // MatrixXd m_alpha = MatrixXd::Zero(dim_alpha,dim_alpha);
464 
465 }
466 
467 std::pair<VectorXd, MatrixXd> GHCJTController::sortRows(const MatrixXd &C, const MatrixXd &J)
468 {
469  int totalTaskDim = J.rows();
470  int nDof = J.cols();
471  MatrixXd Cii_J = MatrixXd::Zero(totalTaskDim, 1+nDof);
472 
473  Cii_J.col(0) = C.diagonal();
474  Cii_J.block(0,1,totalTaskDim,nDof) = J;
475 
476  int rdim = Cii_J.rows();
477  VectorXd tmp= VectorXd::Zero(1+nDof);
478  for (int rmin=0; rmin<rdim-1;++rmin)
479  {
480  for(int i=rdim-1; i>rmin; --i)
481  {
482  if (Cii_J(i,0)>Cii_J(i-1,0))
483  {
484  tmp = Cii_J.row(i-1);
485  Cii_J.row(i-1) = Cii_J.row(i);
486  Cii_J.row(i) = tmp;
487  }
488  }
489  }
490 
491  return std::pair<VectorXd, MatrixXd>(Cii_J.col(0),Cii_J.block(0,1,totalTaskDim,nDof));
492 }
493 
494 void GHCJTController::computeProjector(const MatrixXd &C, const MatrixXd &J, MatrixXd& projector)
495 {
496  int totalTaskDim = J.rows();
497  const int nDof = pimpl->innerModel.nbDofs();
498  VectorXd Cs(nDof);
499  MatrixXd Js(totalTaskDim, nDof);
500 
501  std::pair<VectorXd, MatrixXd> sortedMatrix = sortRows(C,J);
502  Cs = sortedMatrix.first;
503  Js = sortedMatrix.second;
504  gocra::OrthonormalFamily onfamily(Js, 1e-9);
505  onfamily.computeOrthonormalFamily();
506  MatrixXd onb_Js = onfamily.getOnf();
507  VectorXi origin = onfamily.getOrigin();
508 // std::cout<<"origin"<<std::endl;
509 // std::cout<<origin<<std::endl;
510  int k = onfamily.getIndex();
511  VectorXd Chat(k);
512 
513  for (int j=0; j<k; ++j)
514  {
515  Chat(j)=Cs(origin(j));
516  }
517 
518 
519  MatrixXd alpha = MatrixXd(Chat.asDiagonal());
520 // std::cout<<"Cs"<<std::endl;
521 // std::cout<<Cs<<std::endl;
522 // std::cout<<"Chat"<<std::endl;
523 // std::cout<<Chat<<std::endl;
524 // std::cout<<"onb_js"<<std::endl;
525 // std::cout<<onb_Js<<std::endl;
526 // std::cout<<"alpha"<<std::endl;
527 // std::cout<<alpha<<std::endl;
528 // projector = MatrixXd::Zero(nDof,nDof);
529  projector = MatrixXd::Identity(nDof,nDof) - onb_Js.transpose()*alpha*onb_Js;
530 }
531 
532 void GHCJTController::computeTaskiProjector(const MatrixXd &J, MatrixXd& projector)
533 {
534 
535  gocra::OrthonormalFamily onfamily(J, 1e-9);
536  onfamily.computeOrthonormalFamily();
537  MatrixXd onb_Js = onfamily.getOnf();
538  const int nDof = pimpl->innerModel.nbDofs();
539 
540  projector = MatrixXd::Identity(nDof,nDof) - onb_Js.transpose()*onb_Js;
541 }
542 
543 
545 {
546 // initPriorityMatrix(param);
547 
548  VectorXd vec_ij;
549  int dim_j;
550  MatrixXd m_priority(pimpl->totalActiveTaskDim,pimpl->totalActiveTaskDim);
551  m_priority.setZero();
552 
553  int nt = pimpl->nbActiveTask;
554  for (int i=0; i<nt; ++i)
555  {
556  for (int j=0; j<nt; ++j)
557  {
558  dim_j = pimpl->activeTask[j]->getTaskDimension();
559  vec_ij = VectorXd::Zero(dim_j);
560  vec_ij = vec_ij.setConstant(param(i,j));
561  m_priority.block(pimpl->activeTask[j]->getIndexBegin(), pimpl->activeTask[j]->getIndexBegin(),dim_j,dim_j) = MatrixXd(vec_ij.asDiagonal());
562  }
563 
564  pimpl->activeTask[i]->setPriority(m_priority);
565 // std::cout<<"mp="<<m_priority<<std::endl;
566  }
567 
568  const int nDof = pimpl->innerModel.nbDofs();
569  MatrixXd proj(nDof,nDof);
570  MatrixXd taskiProj(nDof,nDof);
571 
572  for (int i=0; i<pimpl->nbActiveTask; ++i)
573  {
574  computeProjector(pimpl->activeTask[i]->getPriority(), pimpl->augmentedJacobian, proj);
575  pimpl->activeTask[i]->setProjector(proj);
576  computeTaskiProjector(pimpl->activeTask[i]->getJacobian(), taskiProj);
577  pimpl->activeTask[i]->setTaskiProjector(taskiProj);
578  }
579 
580 }
581 
582 
583 } // namespace gocra
void setErrorFlag(int eflag)
Definition: Controller.cpp:401
GHCJTController(const std::string &ctrlName, Model &innerModel, ocra::OneLevelSolver &innerSolver, bool useGrav)
ocra::OneLevelSolver & innerSolver
Define task class for GHCJT controller. It inherits from the task class defined in the ocra framework...
const Eigen::MatrixXd & getJacobian() const
Definition: Task.cpp:600
std::pair< Eigen::VectorXd, Eigen::MatrixXd > sortRows(const Eigen::MatrixXd &C, const Eigen::MatrixXd &J)
const Eigen::VectorXi & getOrigin() const
Factory classes and functions to build sets of contact frames.
ocra::OneLevelSolver & getSolver()
const VectorXd & getValue() const
Definition: Variable.cpp:94
int getTotalActiveTaskDimensions() const
PerformanceRecorder solveProblemRecorder
EqualZeroConstraintPtr< SumOfLinearFunctions > seConstraint
Contact task factory.
Definition: ContactSet.h:59
void connectToController(ocra::OneLevelSolver &_solver, SumOfLinearFunctions &seConstraint)
Definition: GHCJTTask.cpp:171
void addConstraint(ocra::LinearConstraint &constraint) const
void removeConstraint(ocra::LinearConstraint &constraint) const
Define the internal solver class that can be used in the wOcra controller.
Declaration file of the Model class.
std::vector< GHCJTTask * > & getActiveTask()
const Variable & getVariable() const
Definition: GHCJTTask.cpp:518
A class hierarchy to compute task errors based on control frames.
Model class.
Definition: Model.h:38
void takeIntoAccountGravity(bool useGrav)
std::vector< GHCJTTask * > activeTask
virtual void doAddContactSet(const ContactSet &contacts)
bool isBodyContactConstraint() const
Definition: Task.cpp:512
std::string getPerformances() const
void computeProjector(const Eigen::MatrixXd &C, const Eigen::MatrixXd &J, Eigen::MatrixXd &projector)
Interface for controllers.
Definition: Controller.h:53
Define the Generalized Hierarchical Controller based on Jacobian transpose (GHCJT) in quasi-static ca...
Constraint class.
Definition: Constraint.h:100
virtual Task * doCreateContactTask(const std::string &name, PointContactFeature::Ptr feature, double mu, double margin) const
const Eigen::MatrixXd & getOnf() const
A generic abstract task for the GHCJT controller.
Definition: GHCJTTask.h:41
virtual void doAddTask(Task &task)
GHCJTTask & createGHCJTContactTask(const std::string &name, PointContactFeature::Ptr feature, double mu, double margin) const
std::shared_ptr< Task > createContactTask(const std::string &name, PointContactFeature::Ptr feature, double mu, double margin) const
Creates a contact task.
Definition: Controller.cpp:378
const Eigen::MatrixXd & getProjector() const
Definition: GHCJTTask.cpp:498
void computeTaskiProjector(const Eigen::MatrixXd &J, Eigen::MatrixXd &projector)
virtual Task * doCreateTask(const std::string &name, Feature::Ptr feature, Feature::Ptr featureDes) const
void setTaskProjectors(Eigen::MatrixXd &param)
A generic abstract class the solvers that can be used in the wOcra Controller.
void setErrorMessage(const std::string &msg)
Definition: Controller.cpp:406
virtual void doComputeOutput(Eigen::VectorXd &tau)
PerformanceRecorder updateTasksRecorder
bool isPointContactTask() const
Definition: Task.cpp:517
std::shared_ptr< Task > createTask(const std::string &name, Feature::Ptr feature, Feature::Ptr featureDes) const
Generic task creation.
Definition: Controller.cpp:354
void writePerformanceInStream(std::ostream &myOstream, bool addCommaAtEnd) const
To get and save time information to collect some data on performances.
Pimpl(const std::string &name, Model &m, ocra::OneLevelSolver &s, bool useGrav)
GHCJTTask & createGHCJTTask(const std::string &name, Feature::Ptr feature, Feature::Ptr featureDes) const
const std::vector< std::shared_ptr< Task > > & getActiveTasks() const
Definition: Controller.cpp:394
std::vector< GHCJTTask * > createdTask
Declaration file of the QuadraticFunction class.