Skip to content

Commit 6be935e

Browse files
jmirabelolivier-stasse
authored andcommitted
Add check of position and velocity bounds.
1 parent fcdd0df commit 6be935e

File tree

2 files changed

+143
-1
lines changed

2 files changed

+143
-1
lines changed

include/sot/core/device.hh

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,22 @@ namespace dynamicgraph {
7575
protected:
7676
dg::Vector state_;
7777
dg::Vector velocity_;
78+
bool sanityCheck_;
7879
dg::Vector vel_control_;
7980
ControlInput controlInputType_;
8081
bool withForceSignals[4];
8182
PeriodicCall periodicCallBefore_;
8283
PeriodicCall periodicCallAfter_;
84+
85+
/// \name Robot bounds used for sanity checks
86+
/// \{
87+
Vector upperPosition_;
88+
Vector upperVelocity_;
89+
Vector upperTorque_;
90+
Vector lowerPosition_;
91+
Vector lowerVelocity_;
92+
Vector lowerTorque_;
93+
/// \}
8394
public:
8495

8596
/* --- CONSTRUCTION --- */
@@ -96,6 +107,14 @@ namespace dynamicgraph {
96107
virtual void setControlInputType(const std::string& cit);
97108
virtual void increment(const double & dt = 5e-2);
98109

110+
/// \name Sanity check parameterization
111+
/// \{
112+
void setSanityCheck (const bool & enableCheck);
113+
void setPositionBounds(const Vector& lower, const Vector& upper);
114+
void setVelocityBounds(const Vector& lower, const Vector& upper);
115+
void setTorqueBounds (const Vector& lower, const Vector& upper);
116+
/// \}
117+
99118
public: /* --- DISPLAY --- */
100119
virtual void display(std::ostream& os) const;
101120
SOT_CORE_EXPORT friend std::ostream&
@@ -144,6 +163,17 @@ namespace dynamicgraph {
144163
/// Store Position of free flyer joint
145164
MatrixHomogeneous ffPose_;
146165
/// Compute the new position, from the current control.
166+
///
167+
/// When sanity checks are enabled, this checks that the control is within
168+
/// bounds. There are three cases, depending on what the control is:
169+
/// - position: checks that the position is within bounds,
170+
/// - velocity: checks that the velocity and the future position are
171+
/// within bounds,
172+
/// - acceleration: checks that the acceleration, the future velocity and
173+
/// position are within bounds.
174+
/// \todo in order to check the acceleration, we need
175+
/// pinocchio and the contact forces in order to estimate
176+
/// the joint torques for the given acceleration.
147177
virtual void integrate( const double & dt );
148178
protected:
149179
/// Get freeflyer pose

src/tools/device.cpp

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Device::
8888
Device( const std::string& n )
8989
:Entity(n)
9090
,state_(6)
91-
,vel_controlInit_(false)
91+
,sanityCheck_(true)
9292
,controlInputType_(CONTROL_INPUT_ONE_INTEGRATION)
9393
,controlSIN( NULL,"Device("+n+")::input(double)::control" )
9494
,attitudeSIN(NULL,"Device("+ n +")::input(vector3)::attitudeIN")
@@ -282,6 +282,88 @@ setControlInputType(const std::string& cit)
282282
sotDEBUG(25)<<"Unrecognized control input type: "<<cit<<endl;
283283
}
284284

285+
void Device::
286+
setSanityCheck(const bool & enableCheck)
287+
{
288+
if (enableCheck) {
289+
const Vector::Index& s = state_.size();
290+
switch (controlInputType_) {
291+
case CONTROL_INPUT_TWO_INTEGRATION:
292+
dgRTLOG()
293+
<< "Sanity check for this control is not well supported. "
294+
"In order to make it work, use pinocchio and the contact forces "
295+
"to estimate the joint torques for the given acceleration.\n";
296+
if ( s != lowerTorque_.size()
297+
|| s != upperTorque_.size() )
298+
throw std::invalid_argument ("Upper and/or lower torque bounds "
299+
"do not match state size. Set them first with setTorqueBounds");
300+
case CONTROL_INPUT_ONE_INTEGRATION:
301+
if ( s != lowerVelocity_.size()
302+
|| s != upperVelocity_.size() )
303+
throw std::invalid_argument ("Upper and/or lower velocity bounds "
304+
"do not match state size. Set them first with setVelocityBounds");
305+
case CONTROL_INPUT_NO_INTEGRATION:
306+
if ( s != lowerPosition_.size()
307+
|| s != upperPosition_.size() )
308+
throw std::invalid_argument ("Upper and/or lower position bounds "
309+
"do not match state size. Set them first with setPositionBounds");
310+
break;
311+
default:
312+
throw std::invalid_argument ("Invalid control mode type.");
313+
}
314+
}
315+
sanityCheck_ = enableCheck;
316+
}
317+
318+
void Device::
319+
setPositionBounds(const Vector& lower, const Vector& upper)
320+
{
321+
std::ostringstream oss;
322+
if (lower.size() != state_.size()) {
323+
oss << "Lower bound size should be " << state_.size();
324+
throw std::invalid_argument (oss.str());
325+
}
326+
if (upper.size() != state_.size()) {
327+
oss << "Upper bound size should be " << state_.size();
328+
throw std::invalid_argument (oss.str());
329+
}
330+
lowerPosition_ = lower;
331+
upperPosition_ = upper;
332+
}
333+
334+
void Device::
335+
setVelocityBounds(const Vector& lower, const Vector& upper)
336+
{
337+
std::ostringstream oss;
338+
if (lower.size() != velocity_.size()) {
339+
oss << "Lower bound size should be " << velocity_.size();
340+
throw std::invalid_argument (oss.str());
341+
}
342+
if (upper.size() != velocity_.size()) {
343+
oss << "Upper bound size should be " << velocity_.size();
344+
throw std::invalid_argument (oss.str());
345+
}
346+
lowerVelocity_ = lower;
347+
upperVelocity_ = upper;
348+
}
349+
350+
void Device::
351+
setTorqueBounds (const Vector& lower, const Vector& upper)
352+
{
353+
// TODO I think the torque bounds size are state_.size()-6...
354+
std::ostringstream oss;
355+
if (lower.size() != state_.size()) {
356+
oss << "Lower bound size should be " << state_.size();
357+
throw std::invalid_argument (oss.str());
358+
}
359+
if (upper.size() != state_.size()) {
360+
oss << "Lower bound size should be " << state_.size();
361+
throw std::invalid_argument (oss.str());
362+
}
363+
lowerTorque_ = lower;
364+
upperTorque_ = upper;
365+
}
366+
285367
void Device::
286368
increment( const double & dt )
287369
{
@@ -371,6 +453,23 @@ increment( const double & dt )
371453
motorcontrolSOUT .setConstant( state_ );
372454
}
373455

456+
// Return true if it saturates.
457+
inline bool
458+
saturateBounds (double& val, const double& lower, const double& upper)
459+
{
460+
assert (lower <= upper);
461+
if (val < lower) { val = lower; return true; }
462+
if (upper < val) { val = upper; return true; }
463+
return false;
464+
}
465+
466+
#define CHECK_BOUNDS(val, lower, upper, what) \
467+
for (int i = 0; i < val.size(); ++i) { \
468+
if (saturateBounds (val(i), lower(i), upper(i))) \
469+
dgRTLOG () << "A robot "what" bound would be violated at DoF " << i << \
470+
" " << val(i); \
471+
}
472+
374473
void Device::integrate( const double & dt )
375474
{
376475
const Vector & controlIN = controlSIN.accessCopy();
@@ -379,6 +478,7 @@ void Device::integrate( const double & dt )
379478
{
380479
assert(state_.size()==controlIN.size()+6);
381480
state_.tail(controlIN.size()) = controlIN;
481+
CHECK_BOUNDS(state_, lowerPosition_, upperPosition_, "position");
382482
return;
383483
}
384484

@@ -391,6 +491,7 @@ void Device::integrate( const double & dt )
391491

392492
if (controlInputType_==CONTROL_INPUT_TWO_INTEGRATION)
393493
{
494+
// TODO check acceleration
394495
// Position increment
395496
vel_control_ = velocity_.tail(controlIN.size()) + (0.5*dt)*controlIN;
396497
// Velocity integration.
@@ -401,12 +502,23 @@ void Device::integrate( const double & dt )
401502
vel_control_ = controlIN;
402503
}
403504

505+
// Velocity bounds check
506+
if (sanityCheck_) {
507+
CHECK_BOUNDS(velocity_, lowerVelocity_, upperVelocity_, "velocity");
508+
}
509+
510+
// Freeflyer integration
404511
if (vel_control_.size() == state_.size()) {
405512
integrateRollPitchYaw(state_, vel_control_, dt);
406513
}
407514

408515
// Position integration
409516
state_.tail(controlIN.size()) += vel_control_ * dt;
517+
518+
// Position bounds check
519+
if (sanityCheck_) {
520+
CHECK_BOUNDS(state_, lowerPosition_, upperPosition_, "position");
521+
}
410522
}
411523

412524
/* --- DISPLAY ------------------------------------------------------------ */

0 commit comments

Comments
 (0)