ocra-recipes
Doxygen documentation for the ocra-recipes repository
Controller.cpp
Go to the documentation of this file.
2 
3 namespace
4 {
5  template<class T>
6  class TaskMap
7  {
8  private:
9  std::map<std::string, std::shared_ptr<T>> data;
10  const std::string id;
11 
12  public:
13  TaskMap(const std::string& id_): id(id_) {}
14 
15  const std::shared_ptr<T> get(const std::string& name) const
16  {
17  typename std::map<std::string, std::shared_ptr<T>>::const_iterator it = data.find(name);
18  if(it == data.end()) {
19  std::cout << "[Controller::"+id+" set]: element with name "+name+" not found!" << std::endl;
20  // throw std::runtime_error("[Controller::"+id+" set]: element with name "+name+" not found!");
21  }
22  return it->second;
23  }
24 
25  std::shared_ptr<T> get(const std::string& name)
26  {
27  typename std::map<std::string, std::shared_ptr<T>>::iterator it = data.find(name);
28  if(it == data.end()) {
29  std::cout << "[Controller::"+id+" set]: element with name "+name+" not found!" << std::endl;
30  // throw std::runtime_error("[Controller::"+id+" set]: element with name "+name+" not found!");
31  }
32  return it->second;
33  }
34 
35  void add(const std::string& name, std::shared_ptr<T> elm)
36  {
37  typename std::map<std::string, std::shared_ptr<T>>::const_iterator it = data.find(name);
38  if(it != data.end()) {
39  std::cout << "[Controller::"+id+" set]: element with name "+name+" already registered!" << std::endl;
40  // throw std::runtime_error("[Controller::"+id+" set]: element with name "+name+" already registered!");
41  }
42  data[name] = elm;
43  }
44 
45  const std::map<std::string, std::shared_ptr<T>>& getData() const
46  {
47  return data;
48  }
49 
50  void erase(const std::string& name)
51  {
52  this->data.erase(name);
53  }
54 
55  template<class P>
56  void getIf(P predicate, std::vector<std::shared_ptr<T>>& result) const
57  {
58  typename std::map<std::string, std::shared_ptr<T>>::const_iterator it = data.begin();
59  for(; it != data.end(); ++it)
60  {
61  if(predicate(it->second))
62  result.push_back(it->second);
63  }
64  }
65  };
66 
67 
68  struct isTaskActive
69  {
70  bool operator()(const std::shared_ptr<ocra::Task> task)
71  {
72  return (task->isActiveAsObjective() ||task->isActiveAsConstraint());
73  }
74  };
75 }
76 
77 namespace ocra
78 {
80  {
81  const Model& model;
82  VectorXd tau_max;
83  VectorXd tau;
84  TaskMap<Task> tasks;
85  TaskMap<TaskYarpInterface> taskInterfaces;
86  std::vector<std::shared_ptr<Task>> activeTasks;
87  std::string errorMessage;
88  double maxTau;
89  int errorFlag;
91 
92  Pimpl(const Model& m)
93  : model(m)
94  , tau_max( VectorXd::Constant(m.nbInternalDofs(), std::numeric_limits<double>::max()) )
95  , tau( VectorXd::Constant(m.nbInternalDofs(), 0.) )
96  , tasks("tasks")
97  , taskInterfaces("taskInterfaces")
98  , activeTasks()
99  , errorMessage("")
100  , maxTau(500.)
101  , errorFlag(Controller::SUCCESS)
102  , handleError(false)
103  {}
104  };
105 
106  Controller::Controller(const std::string& name, Model& model)
107  : NamedInstance(name)
108  , pimpl(new Pimpl(model))
109  {
110  // Assuming by default that humnanoid robots start in double support face
111  this->_isInLeftSupport = 1;
112  this->_isInRightSupport = 1;
113  }
114 
116  {
117  }
118 
119  void Controller::printInfo(int level, const std::string& filename)
120  {
121  std::ofstream file;
122  if(!filename.empty())
123  file.open(filename.c_str(), std::ios::app);
124  std::ostream& os = filename.empty() ? std::cout : file;
125 
126  os << "Controller Info {\nController name: " << getName() << std::endl;
127 
128  if(level > 1)
129  {
130  os << "\tError flag: " << getErrorFlag() << std::endl;
131  os << "\tError message: " << getErrorMessage() << std::endl;
132  }
133 
134  const std::vector<std::shared_ptr<Task>>& activeTasks = getActiveTasks();
135 
136  if(activeTasks.empty())
137  os << "\tNo active task" << std::endl;
138  else
139  os << "\tList of active tasks:" << std::endl;
140 
141  for(size_t i = 0; i < activeTasks.size(); ++i)
142  {
143  Task& t = *activeTasks[i];
144  os << "\t- " << t.getName() << ":" << std::endl;
145  if(level > 1)
146  {
147  os << "\t\tLast output: " << t.getOutput().transpose() << std::endl;
148  os << "\t\tError: " << t.getError().transpose() << std::endl;
149  os << "\t\tErrorDot: " << t.getErrorDot().transpose() << std::endl;
150  os << "\t\tJacobian\n" << t.getJacobian() << std::endl;
151  }
152  if(level > 0)
153  {
154  os << "\t\tWeight: " << t.getWeight().transpose() << std::endl;
155  os << "\t\tDesired mass\n" << t.getDesiredMass() << std::endl;
156  os << "\t\tApparent mass changed: " << !t.isDesiredMassTheActualOne() << std::endl;
157  os << "\t\tDamping\n" << t.getDamping() << std::endl;
158  os << "\t\tStiffness\n" << t.getStiffness() << std::endl;
159  os << "\t\tRef force: " << t.getEffort().transpose() << std::endl;
160  os << "\t\tContact task: " << t.isContactModeActive() << std::endl;
161  if(t.isContactModeActive())
162  {
163  os << "\t\t\tmu: " << t.getFrictionCoeff() << std::endl;
164  os << "\t\t\tmargin: " << t.getMargin() << std::endl;
165  }
166  }
167  }
168 
169  os << "}" << std::endl;
170  }
171 
172  void Controller::setMaxJointTorques(const VectorXd& tau_max)
173  {
174  pimpl->tau_max = tau_max;
175  doSetMaxJointTorques(tau_max);
176  };
177  void Controller::doSetMaxJointTorques(const VectorXd& tau_max) {}
178 
179  const VectorXd& Controller::getMaxJointTorques() const
180  {
181  return pimpl->tau_max;
182  }
183 
184  void Controller::addTask(std::shared_ptr<Task> task)
185  {
186  pimpl->tasks.add(task->getName(), task);
187  doAddTask(task);
188  pimpl->taskInterfaces.add(task->getName(), std::make_shared<TaskYarpInterface>(task));
189  }
190 
191  void Controller::addTasks(const std::vector<std::shared_ptr<Task>>& tasks)
192  {
193  for(size_t i = 0; i < tasks.size(); ++i)
194  addTask(tasks[i]);
195  }
196 
197  void Controller::removeTask(const std::string& taskName)
198  {
199  pimpl->taskInterfaces.erase(taskName);
200  pimpl->tasks.erase(taskName);
201  }
202 
203  void Controller::removeTasks(const std::vector<std::string> tasks)
204  {
205  for(auto task : tasks)
206  removeTask(task);
207  }
208 
209  void Controller::addContactSet(const ContactSet& contacts)
210  {
211  doAddContactSet(contacts);
212  }
213 
214  std::shared_ptr<Task> Controller::getTask(const std::string& name)
215  {
216  return pimpl->tasks.get(name);
217  }
218 
219  std::vector<std::string> Controller::getTaskNames()
220  {
221  std::vector<std::string> taskNames;
222  for (auto mapItem : pimpl->tasks.getData()) {
223  taskNames.push_back(mapItem.first);
224  }
225  return taskNames;
226  }
227 
228  std::string Controller::getTaskPortName(const std::string& taskName)
229  {
230  auto interface = pimpl->taskInterfaces.get(taskName);
231  if (interface) {
232  return interface->getPortName();
233  } else {
234  return "";
235  }
236  }
237 
238  std::vector<std::string> Controller::getTaskPortNames()
239  {
240  std::vector<std::string> taskPortNames;
241  for (auto mapItem : pimpl->taskInterfaces.getData()) {
242  taskPortNames.push_back(mapItem.second->getPortName());
243  }
244  return taskPortNames;
245  }
246 
247  const std::shared_ptr<Task> Controller::getTask(const std::string& name) const
248  {
249  return pimpl->tasks.get(name);
250  }
251 
252  const Eigen::VectorXd& Controller::computeOutput()
253  {
254  computeOutput(pimpl->tau);
255  return pimpl->tau;
256  }
257 
258  void Controller::computeOutput(Eigen::VectorXd& tau)
259  {
260  if(pimpl->errorFlag & CRITICAL_ERROR)
261  {
262  if(pimpl->handleError)
263  {
264  tau.resize(pimpl->model.nbInternalDofs());
265  tau.setZero();
266  return;
267  }
268  }
269 
270  doComputeOutput(tau);
271 
272  if(pimpl->errorFlag & CRITICAL_ERROR)
273  {
274  if(pimpl->handleError)
275  {
276  tau.resize(pimpl->model.nbInternalDofs());
277  tau.setZero();
278  return;
279  }
280  }
281 
282  const double tauNorm = tau.norm();
283  if(tauNorm > pimpl->maxTau)
284  {
285  if(pimpl->handleError)
286  {
287  tau.resize(pimpl->model.nbInternalDofs());
288  tau.setZero();
289  }
290 
291  std::stringstream ss;
292  ss << "Instability suspected: norm of joint torques is " << tauNorm << " Nm.\n"
293  << "Maximum authorized is " << pimpl->maxTau << " Nm." << std::endl;
294 
295  setErrorMessage(ss.str());
297  }
298  }
299 
300  void Controller::setFixedLinkForOdometry(std::string newFixedLink)
301  {
302  this->_fixedLink = newFixedLink;
303 // std::cout << "[DEBUG-JORH] Controller::setFixedLinkForOdometry: Changed _fixedLink = " << newFixedLink.c_str() << std::endl;
304  }
305 
306  void Controller::getContactState(int& leftSupport, int& rightSupport)
307  {
308  leftSupport = this->_isInLeftSupport;
309  rightSupport = this->_isInRightSupport;
310 // std::cout << "[DEBUG] Controller::getContactState set leftSupport to: " << leftSupport << " and rightSupport to: " << rightSupport << std::endl;
311  }
312 
314  {
315  pimpl->handleError = true;
316  }
317 
319  {
320  pimpl->handleError = false;
321  }
322 
324  {
325  return pimpl->handleError;
326  }
327 
328  const std::string& Controller::getErrorMessage() const
329  {
330  return pimpl->errorMessage;
331  }
332 
334  {
335  pimpl->errorFlag = SUCCESS;
336  pimpl->errorMessage = "";
337  }
338 
340  {
341  return pimpl->errorFlag;
342  }
343 
345  {
346  pimpl->maxTau = maxTau;
347  }
348 
350  {
351  return pimpl->maxTau;
352  }
353 
354  std::shared_ptr<Task> Controller::createTask(const std::string& name, Feature::Ptr feature, Feature::Ptr featureDes) const
355  {
356  std::shared_ptr<Task> task(doCreateTask(name, feature, featureDes));
357  task->setDesiredMassToActualOne();
358  task->setDamping(0.);
359  task->setStiffness(0.);
360  task->setWeight(1.);
361  // return *task;
362  return task;
363  }
364 
365  std::shared_ptr<Task> Controller::createTask(const std::string& name, Feature::Ptr feature) const
366  {
367  // Task* task = doCreateTask(name, feature);
368  std::shared_ptr<Task> task(doCreateTask(name, feature));
369  task->setDesiredMassToActualOne();
370  task->setDamping(0.);
371  task->setStiffness(0.);
372  task->setWeight(1.);
373  // return *task;
374  return task;
375  }
376 
377  // Task& Controller::createContactTask(const std::string& name, PointContactFeature::Ptr feature, double mu, double margin) const
378  std::shared_ptr<Task> Controller::createContactTask(const std::string& name, PointContactFeature::Ptr feature, double mu, double margin) const
379  {
380  // Task* task = doCreateContactTask(name, feature, mu, margin);
381  std::shared_ptr<Task> task(doCreateContactTask(name, feature, mu, margin));
382 
383  task->setDesiredMassToActualOne();
384  task->setDamping(0.);
385  task->setStiffness(0.);
386  task->setFrictionCoeff(mu);
387  task->setMargin(margin);
388  task->setWeight(1.);
389  task->activateContactMode();
390  // return *task;
391  return task;
392  }
393 
394  const std::vector<std::shared_ptr<Task>>& Controller::getActiveTasks() const
395  {
396  pimpl->activeTasks.clear();
397  pimpl->tasks.getIf(isTaskActive(), pimpl->activeTasks);
398  return pimpl->activeTasks;
399  }
400 
401  void Controller::setErrorFlag(int eflag)
402  {
403  pimpl->errorFlag = eflag;
404  }
405 
406  void Controller::setErrorMessage(const std::string& msg)
407  {
408  pimpl->errorMessage = msg;
409  }
410 
411  const std::map<std::string, std::shared_ptr<Task>>& Controller::getTasks() const
412  {
413  return pimpl->tasks.getData();
414  }
415 }
416 
417 // cmake:sourcegroup=Api
virtual void doAddTask(std::shared_ptr< Task > task)=0
void setErrorFlag(int eflag)
Definition: Controller.cpp:401
const Eigen::MatrixXd & getJacobian() const
Definition: Task.cpp:600
void addContactSet(const ContactSet &contacts)
Definition: Controller.cpp:209
std::vector< std::shared_ptr< Task > > activeTasks
Definition: Controller.cpp:86
double getMargin() const
Definition: Task.cpp:527
virtual void doSetMaxJointTorques(const Eigen::VectorXd &tauMax)
Definition: Controller.cpp:177
void enableErrorHandling()
Definition: Controller.cpp:313
void removeTask(const std::string &taskName)
Definition: Controller.cpp:197
int getErrorFlag() const
Definition: Controller.cpp:339
void printInfo(int level, const std::string &filename)
Definition: Controller.cpp:119
void setMaxJointTorqueNorm(double maxTau)
Definition: Controller.cpp:344
Contact task factory.
Definition: ContactSet.h:59
void disableErrorHandling()
Definition: Controller.cpp:318
const Eigen::VectorXd & getErrorDot() const
Definition: Task.cpp:582
virtual ~Controller()=0
Definition: Controller.cpp:115
const std::string & getErrorMessage() const
Definition: Controller.cpp:328
TaskMap< Task > tasks
Definition: Controller.cpp:84
bool isErrorHandlingEnabled() const
Definition: Controller.cpp:323
const Eigen::MatrixXd & getDamping() const
Definition: Task.cpp:466
const std::string & getName() const
const Eigen::VectorXd & getError() const
Definition: Task.cpp:576
void addTasks(const std::vector< std::shared_ptr< Task >> &tasks)
Definition: Controller.cpp:191
Model class.
Definition: Model.h:38
void removeTasks(const std::vector< std::string > tasks)
Definition: Controller.cpp:203
Optimization-based Robot Controller namespace. a library of classes to write and solve optimization p...
void getContactState(int &leftSupport, int &rightSupport)
Definition: Controller.cpp:306
virtual void doAddContactSet(const ContactSet &contacts)=0
std::vector< std::string > getTaskPortNames()
Definition: Controller.cpp:238
Interface for controllers.
Definition: Controller.h:53
std::shared_ptr< Task > getTask(const std::string &name)
Definition: Controller.cpp:214
void setFixedLinkForOdometry(std::string newFixedLink)
Definition: Controller.cpp:300
std::string errorMessage
Definition: Controller.cpp:87
TaskMap< TaskYarpInterface > taskInterfaces
Definition: Controller.cpp:85
const Eigen::VectorXd & getMaxJointTorques() const
Definition: Controller.cpp:179
std::string getTaskPortName(const std::string &taskName)
Definition: Controller.cpp:228
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
virtual void doComputeOutput(Eigen::VectorXd &tau)=0
virtual std::shared_ptr< Task > doCreateTask(const std::string &name, Feature::Ptr feature, Feature::Ptr featureDes) const =0
virtual std::shared_ptr< Task > doCreateContactTask(const std::string &name, PointContactFeature::Ptr feature, double mu, double margin) const =0
const Eigen::VectorXd & computeOutput()
Definition: Controller.cpp:252
bool isDesiredMassTheActualOne() const
Definition: Task.cpp:436
Pimpl(const Model &m)
Definition: Controller.cpp:92
void setMaxJointTorques(const Eigen::VectorXd &tau_max)
Definition: Controller.cpp:172
double getMaxJointTorqueNorm() const
Definition: Controller.cpp:349
void setErrorMessage(const std::string &msg)
Definition: Controller.cpp:406
double getFrictionCoeff() const
Definition: Task.cpp:522
Controller interface.
const std::map< std::string, std::shared_ptr< Task > > & getTasks() const
Definition: Controller.cpp:411
std::shared_ptr< Task > createTask(const std::string &name, Feature::Ptr feature, Feature::Ptr featureDes) const
Generic task creation.
Definition: Controller.cpp:354
const Eigen::VectorXd & getEffort() const
Definition: Task.cpp:594
bool isContactModeActive() const
Definition: Task.cpp:507
void addTask(std::shared_ptr< Task > task)
Definition: Controller.cpp:184
const Eigen::VectorXd & getOutput() const
Definition: Task.cpp:570
const Eigen::VectorXd & getWeight() const
Definition: Task.cpp:560
std::vector< std::string > getTaskNames()
Definition: Controller.cpp:219
const std::vector< std::shared_ptr< Task > > & getActiveTasks() const
Definition: Controller.cpp:394
const Eigen::MatrixXd & getStiffness() const
Definition: Task.cpp:471
const Eigen::MatrixXd & getDesiredMass() const
Definition: Task.cpp:441