20 #include "worldsimconfig.h"
21 #include "motorcontrollers.h"
24 #include "phymarxbot.h"
29 #ifdef FARSA_USE_YARP_AND_ICUB
32 #pragma GCC diagnostic ignored "-Wunused-parameter"
34 #include <yarp/os/Searchable.h>
36 #pragma GCC diagnostic warning "-Wunused-parameter"
39 using namespace yarp::dev;
40 using namespace yarp::os;
65 double wPID::pidloop(
double PV ) {
73 this_target = next_target;
76 if ( accel_r > 0 && this_target != setpt) {
77 if ( this_target < setpt ) {
78 next_target += accel_r;
79 if ( next_target > setpt ) {
83 next_target -= accel_r;
84 if ( next_target < setpt ) {
94 accel = next_target - this_target;
97 this_error = this_target - PV;
100 deriv = this_error - last_error;
105 friction = ( PV == 0.0 && next_target != 0.0 );
107 integral += this_target - PV;
111 this_output = p_gain * this_error
115 + vel_ff * next_target
118 last_error = this_error;
121 if ( this_output - last_output > slew ) {
122 this_output = last_output + slew;
123 }
else if ( last_output - this_output > slew ) {
124 this_output = last_output - slew;
128 if ( this_output <
min ) {
130 }
else if ( this_output >
max ) {
135 return last_output = this_output;
147 MotorController::MotorController(
World* world ) {
152 MotorController::~MotorController() {
156 MultiMotorController::MultiMotorController( QVector<PhyDOF*> dofs,
World* world ) :
158 #ifdef FARSA_USE_YARP_AND_ICUB
165 controlModes.fill( 1, motorsv.size() );
166 refsacc.fill( 1.0, motorsv.size() );
168 refs.fill( 0.0, motorsv.size() );
169 refsvel.fill( 1.0, motorsv.size() );
170 xfx0.fill( 0.0, motorsv.size() );
171 x0.fill( 0.0, motorsv.size() );
172 dx0.fill( 0.0, motorsv.size() );
173 t.fill( 0.0, motorsv.size() );
174 T.fill( 0.0, motorsv.size() );
175 stops.fill(
true, motorsv.size() );
176 lastErrors.fill( 0.0, motorsv.size() );
177 lastIs.fill( 0.0, motorsv.size() );
178 lastTorques.fill( 0.0, motorsv.size() );
180 pos_pids.resize( motorsv.size() );
181 for(
int i=0; i<motorsv.size(); i++ ) {
182 pos_pids[i] =
new wPID();
183 pos_pids[i]->p_gain = 0.8;
184 pos_pids[i]->i_gain = 0.05;
185 pos_pids[i]->d_gain = 0.0;
186 pos_pids[i]->accel_r = 0;
187 pos_pids[i]->min = -PI_GRECO/2.0;
188 pos_pids[i]->max = +PI_GRECO/2.0;
191 desiredVel.fill( 0.0, motorsv.size() );
193 vel_pids.resize( motorsv.size() );
194 for(
int i=0; i<motorsv.size(); i++ ) {
195 vel_pids[i] =
new wPID();
196 vel_pids[i]->p_gain = 0.8;
197 vel_pids[i]->i_gain = 0.1;
198 vel_pids[i]->d_gain = 0.0;
201 vel_pids[i]->min = -
toRad( 120 );
202 vel_pids[i]->max = +
toRad( 120 );
205 loLimits.resize( motorsv.size() );
206 hiLimits.resize( motorsv.size() );
207 for(
int i=0; i<motorsv.size(); i++ ) {
209 motorsv[i]->limits( fmin, fmax );
216 for(
int i=0; i<motorsv.size(); i++ ) {
217 delete (vel_pids[i]);
218 delete (pos_pids[i]);
224 for(
int i=0; i<motorsv.size(); i++ ) {
225 switch( controlModes[i] ) {
228 real tFracT = t[i] / T[i];
229 real tFracT3= tFracT * tFracT * tFracT;
230 real tFracT4= tFracT * tFracT3;
231 real tFracT5= tFracT * tFracT4;
236 accum = dx0[i] * tFracT;
237 accum = accum + tFracT3 * (10.0*xfx0[i] - 6.0*dx0[i]);
238 accum = accum - tFracT4 * (15.0*xfx0[i] - 8.0*dx0[i]);
239 accum = accum + tFracT5 * (6.0*xfx0[i] - 3.0*dx0[i]);
246 pos_pids[i]->setpt = accum;
248 motorsv[i]->setDesiredPosition( toRawPosition(accum, i) );
252 stops[i] = ( t[i] / T[i] > 1.0 );
256 vel_pids[i]->setpt = desiredVel[i];
257 wishvel = vel_pids[i]->pidloop( motorsv[i]->velocity() );
258 motorsv[i]->setDesiredVelocity( wishvel );
268 #ifdef FARSA_USE_YARP_AND_ICUB
285 *ax = motorsv.size();
295 if ( j < 0 && j >= motorsv.size() ) {
298 if ( motorsv[j]->translate() ) {
301 refs[j] =
toRad( ref );
303 if ( motorsv[j]->isLimited() ) {
307 real offset = (fabs(hiLimits[j])-fabs(loLimits[j]))*0.005;
308 refs[j] =
ramp( loLimits[j]+offset, hiLimits[j]-offset, refs[j] );
311 x0[j] = fromRawPosition(j);
312 xfx0[j] = refs[j] - x0[j];
313 dx0[j] = motorsv[j]->velocity();
314 T[j] = fabs( xfx0[j] ) / refsvel[j];
318 stops[j] = ( T[j] < 0.010 );
324 for(
int i=0; i<refs.size(); i++ ) {
325 if ( motorsv[i]->translate() ) {
326 refs[i] = newrefs[i];
328 refs[i] =
toRad( newrefs[i] );
330 if ( motorsv[i]->isLimited() ) {
334 real offset = (fabs(hiLimits[i])-fabs(loLimits[i]))*0.005;
335 refs[i] =
ramp( loLimits[i]+offset, hiLimits[i]-offset, refs[i] );
338 x0[i] = fromRawPosition( i );
339 xfx0[i] = refs[i] - x0[i];
340 dx0[i] = motorsv[i]->velocity();
341 T[i] = fabs( xfx0[i] ) / refsvel[i];
345 stops[i] = ( T[i] < 0.010 );
352 if ( j < 0 && j >= motorsv.size() ) {
355 if ( motorsv[j]->translate() ) {
358 refs[j] +=
toRad( delta );
360 if ( motorsv[j]->isLimited() ) {
364 real offset = (fabs(hiLimits[j])-fabs(loLimits[j]))*0.005;
365 refs[j] =
ramp( loLimits[j]+offset, hiLimits[j]-offset, refs[j] );
368 x0[j] = fromRawPosition(j);
369 xfx0[j] = refs[j] - x0[j];
370 dx0[j] = motorsv[j]->velocity();
371 T[j] = fabs( xfx0[j] ) / refsvel[j];
380 for(
int i=0; i<refs.size(); i++ ) {
381 if ( motorsv[i]->translate() ) {
382 refs[i] += deltas[i];
384 refs[i] +=
toRad( deltas[i] );
386 if ( motorsv[i]->isLimited() ) {
390 real offset = (fabs(hiLimits[i])-fabs(loLimits[i]))*0.005;
391 refs[i] =
ramp( loLimits[i]+offset, hiLimits[i]-offset, refs[i] );
394 x0[i] = fromRawPosition( i );
395 xfx0[i] = refs[i] - x0[i];
396 dx0[i] = motorsv[i]->velocity();
397 T[i] = fabs( xfx0[i] ) / refsvel[i];
407 if ( j < 0 && j >= motorsv.size() ) {
411 *flag = ( fabs(fromRawPosition(j) - refs[j]) < 0.01745329 );
418 for(
int i=0; i<refs.size(); i++ ) {
420 ends &= ( fabs(fromRawPosition(i) - refs[i]) < 0.01745329 );
429 if ( j < 0 && j >= motorsv.size() ) {
432 if ( motorsv[j]->translate() ) {
435 refsvel[j] =
toRad(sp);
437 motorsv[j]->setMaxVelocity( refsvel[j] );
442 for(
int i=0; i<refs.size(); i++ ) {
443 if ( motorsv[i]->translate() ) {
444 refsvel[i] = spds[i];
446 refsvel[i] =
toRad(spds[i]);
448 motorsv[i]->setMaxVelocity( refsvel[i] );
454 if ( j < 0 && j >= motorsv.size() ) {
457 if ( motorsv[j]->translate() ) {
460 refsacc[j] =
toRad(acc);
466 for(
int i=0; i<refs.size(); i++ ) {
467 if ( motorsv[i]->translate() ) {
468 refsacc[i] = accs[i];
470 refsacc[i] =
toRad(accs[i]);
477 if ( j < 0 && j >= motorsv.size() ) {
480 if ( motorsv[j]->translate() ) {
489 for(
int i=0; i<refsvel.size(); i++ ) {
490 if ( motorsv[i]->translate() ) {
491 spds[i] = refsvel[i];
500 if ( j < 0 && j >= motorsv.size() ) {
503 if ( motorsv[j]->translate() ) {
512 for(
int i=0; i<refsvel.size(); i++ ) {
513 if ( motorsv[i]->translate() ) {
514 accs[i] = refsacc[i];
523 if ( j < 0 && j >= motorsv.size() ) {
526 refs[j] = fromRawPosition(j);
529 motorsv[j]->setVelocity(0.0);
531 vel_pids[j]->reset();
536 for(
int i=0; i<motorsv.size(); i++ ) {
537 refs[i] = fromRawPosition(i);
540 motorsv[i]->setVelocity(0.0);
542 vel_pids[i]->reset();
553 if ( j < 0 && j >= motorsv.size() ) {
557 desiredVel[j] =
toRad(sp);
562 for(
int i=0; i<desiredVel.size(); i++ ) {
563 desiredVel[i] =
toRad(sp[i]);
570 if ( j < 0 && j >= motorsv.size() ) {
574 refs[j] = fromRawPosition(j);
581 if ( j < 0 && j >= motorsv.size() ) {
592 if ( j < 0 && j >= motorsv.size() ) {
600 if ( j < 0 && j >= motorsv.size() ) {
603 *mode = controlModes[j];
608 for(
int i=0; i<motorsv.size(); i++ ) {
609 modes[i] = controlModes[i];
635 if ( j < 0 && j >= motorsv.size() ) {
638 if ( motorsv[j]->translate() ) {
639 (*v) = fromRawPosition(j);
641 (*v) =
toDegree( fromRawPosition(j) );
647 for(
int i=0; i<motorsv.size(); i++ ) {
648 if ( motorsv[i]->translate() ) {
649 encs[i] = fromRawPosition(i);
651 encs[i] =
toDegree( fromRawPosition(i) );
658 if ( j < 0 && j >= motorsv.size() ) {
661 if ( motorsv[j]->translate() ) {
662 (*sp) = motorsv[j]->velocity();
664 (*sp) =
toDegree(motorsv[j]->velocity());
670 for(
int i=0; i<motorsv.size(); i++ ) {
671 if ( motorsv[i]->translate() ) {
672 spds[i] = motorsv[i]->velocity();
674 spds[i] =
toDegree(motorsv[i]->velocity());
689 if ( axis < 0 && axis >= motorsv.size() ) {
692 if ( motorsv[axis]->translate() ) {
693 loLimits[axis] =
min;
694 hiLimits[axis] =
max;
696 loLimits[axis] =
toRad( min );
697 hiLimits[axis] =
toRad( max );
703 if ( axis < 0 && axis >= motorsv.size() ) {
706 if ( motorsv[axis]->translate() ) {
707 *min = loLimits[axis];
708 *max = hiLimits[axis];
717 if ( axis < 0 && axis >= motorsv.size() ) {
720 if ( motorsv[axis]->translate() ) {
721 motorsv[axis]->setLimits( min, max );
723 motorsv[axis]->setLimits(
toRad(min),
toRad(max) );
729 if ( axis < 0 && axis >= motorsv.size() ) {
733 motorsv[axis]->limits( fmin, fmax );
734 if ( motorsv[axis]->translate() ) {
745 if ( axis < 0 && axis >= motorsv.size() ) {
749 motorsv[axis]->enableLimits();
751 motorsv[axis]->disableLimits();
756 real MultiMotorController::fromRawPosition(
int i ) {
758 motorsv[i]->limits( rmin, rmax );
759 return linearMap( motorsv[i]->position(), rmin, rmax, loLimits[i], hiLimits[i] );
762 real MultiMotorController::toRawPosition( real norawpos,
int i ) {
764 motorsv[i]->limits( rmin, rmax );
765 return linearMap( norawpos, loLimits[i], hiLimits[i], rmin, rmax );
768 void wheeledRobotsComputeKinematicMovement(wMatrix &mtr, real leftWheelVelocity, real rightWheelVelocity, real wheelr, real axletrack, real timestep)
770 const wMatrix origMtr = mtr;
779 const real leftSpeed = leftWheelVelocity * wheelr;
780 const real rightSpeed = rightWheelVelocity * wheelr;
784 if (fabs(leftSpeed - rightSpeed) < 0.00001f) {
786 mtr.w_pos += -mtr.y_ax.scale(rightSpeed * timestep);
833 const wVector L(0.0, -leftSpeed, 0.0);
834 const wVector A(axletrack, -(rightSpeed - leftSpeed), 0.0);
835 const real a = -(L.y / A.y);
836 const wVector C = L + A.
scale(a);
843 const real distLeftWheel = -C.x;
844 const real distRightWheel = -(C.x - A.x);
845 const real angularVelocity = (fabs(distLeftWheel) > fabs(distRightWheel)) ? (-leftSpeed / distLeftWheel) : (-rightSpeed / distRightWheel);
851 const real angularDisplacement = angularVelocity * timestep;
852 const wVector centerOfRotation = origMtr.transformVector(C - wVector(axletrack / 2.0, 0.0, 0.0));
853 const wVector axisOfRotation = origMtr.z_ax;
856 mtr = mtr.
rotateAround(axisOfRotation, centerOfRotation, angularDisplacement);
863 desiredVel.fill( 0.0, motorsv.size() );
864 minVel.fill( -1.0, motorsv.size() );
865 maxVel.fill( 1.0, motorsv.size() );
873 for(
int i=0; i<motorsv.size(); i++ ) {
874 motorsv[i]->setDesiredVelocity( desiredVel[i] );
879 for(
int i=0; i<qMin(speeds.size(), desiredVel.size()); i++ ) {
880 if ( speeds[i] < minVel[i] ) {
881 desiredVel[i] = minVel[i];
882 }
else if ( speeds[i] > maxVel[i] ) {
883 desiredVel[i] = maxVel[i];
885 desiredVel[i] = speeds[i];
891 if ( sp1 < minVel[0] ) {
892 desiredVel[0] = minVel[0];
893 }
else if ( sp1 > maxVel[0] ) {
894 desiredVel[0] = maxVel[0];
899 if ( sp2 < minVel[1] ) {
900 desiredVel[1] = minVel[1];
901 }
else if ( sp2 > maxVel[1] ) {
902 desiredVel[1] = maxVel[1];
910 for(
int i=0; i<motorsv.size(); i++ ) {
911 speeds.append(motorsv[i]->velocity());
916 sp1 = motorsv[0]->velocity();
917 sp2 = motorsv[1]->velocity();
926 minVel[0] = minSpeed1;
927 minVel[1] = minSpeed2;
928 maxVel[0] = maxSpeed1;
929 maxVel[1] = maxSpeed2;
938 minSpeed1 = minVel[0];
939 minSpeed2 = minVel[1];
940 maxSpeed1 = maxVel[0];
941 maxSpeed2 = maxVel[1];
948 m_desiredStatus(Open),
950 m_attachedRobot(NULL),
951 m_otherAttachedRobots()
964 if (m_desiredStatus == m_status) {
969 const Status previousStatus = m_status;
970 m_status = m_desiredStatus;
979 if (m_attachedRobot != NULL) {
985 m_attachedRobot = NULL;
991 if (previousStatus == Open) {
993 m_attachedRobot = tryToAttach();
997 if (m_attachedRobot != NULL) {
1002 if (m_attachedRobot != NULL) {
1007 m_joint->
dofs()[0]->disableLimits();
1008 m_joint->
dofs()[0]->switchOff();
1011 if (previousStatus == Open) {
1019 if (previousStatus == Open) {
1021 m_attachedRobot = tryToAttach();
1025 if (m_attachedRobot != NULL) {
1030 if (m_attachedRobot != NULL) {
1035 if (previousStatus == Open) {
1118 m_desiredStatus = status;
1122 PhyMarXbot* MarXbotAttachmentDeviceMotorController::tryToAttach()
const
1132 QSet<PhyMarXbot*> discardedRobots;
1133 QSet<PhyMarXbot*> candidateRobots;
1134 foreach (
const Contact& c, contacts) {
1136 if ((otherRobot != NULL) && (otherRobot->
attachmentDeviceEnabled()) && (!discardedRobots.contains(otherRobot))) {
1140 candidateRobots.insert(otherRobot);
1143 discardedRobots.insert(otherRobot);
1144 candidateRobots.remove(otherRobot);
1152 if (candidateRobots.isEmpty()) {
1155 return *(candidateRobots.begin());
1159 void MarXbotAttachmentDeviceMotorController::attachmentDeviceAboutToBeDestroyed()
1164 m_desiredStatus = Open;
1168 if (m_attachedRobot != NULL) {
1173 m_attachedRobot = NULL;
1177 foreach (
PhyMarXbot* other, m_otherAttachedRobots) {
1180 other->attachmentDeviceController()->m_joint = NULL;
1181 other->attachmentDeviceController()->m_attachedRobot = NULL;