20 #include "worldsimconfig.h"
21 #include "motorcontrollers.h"
24 #include "phymarxbot.h"
26 #include "mathutils.h"
60 this_target = next_target;
64 if ( this_target <
setpt ) {
66 if ( next_target >
setpt ) {
71 if ( next_target <
setpt ) {
81 accel = next_target - this_target;
84 this_error = this_target - PV;
87 deriv = this_error - last_error;
92 friction = ( PV == 0.0 && next_target != 0.0 );
94 integral += this_target - PV;
98 this_output =
p_gain * this_error
105 last_error = this_error;
108 if ( this_output - last_output >
slew ) {
109 this_output = last_output +
slew;
110 }
else if ( last_output - this_output >
slew ) {
111 this_output = last_output -
slew;
115 if ( this_output <
min ) {
117 }
else if ( this_output >
max ) {
122 return last_output = this_output;
142 void wheeledRobotsComputeKinematicMovement(
wMatrix &mtr,
real leftWheelVelocity,
real rightWheelVelocity,
real wheelr,
real axletrack,
real timestep)
153 const real leftSpeed = leftWheelVelocity * wheelr;
154 const real rightSpeed = rightWheelVelocity * wheelr;
158 if (fabs(leftSpeed - rightSpeed) < 0.00001f) {
160 mtr.w_pos += -mtr.y_ax.
scale(rightSpeed * timestep);
207 const wVector L(0.0, -leftSpeed, 0.0);
208 const wVector A(axletrack, -(rightSpeed - leftSpeed), 0.0);
209 const real a = -(L.y / A.y);
210 const wVector C = L + A.
scale(a);
217 const real distLeftWheel = -C.x;
218 const real distRightWheel = -(C.x - A.x);
219 const real angularVelocity = (fabs(distLeftWheel) > fabs(distRightWheel)) ? (-leftSpeed / distLeftWheel) : (-rightSpeed / distRightWheel);
225 const real angularDisplacement = angularVelocity * timestep;
226 const wVector centerOfRotation = origMtr.
transformVector(C - wVector(axletrack / 2.0, 0.0, 0.0));
227 const wVector axisOfRotation = origMtr.z_ax;
230 mtr = mtr.
rotateAround(axisOfRotation, centerOfRotation, angularDisplacement);
234 bool FARSA_WSIM_API wheeledRobotsComputeWheelsSpeed(
const wMatrix& start,
const wMatrix& end,
real wheelr,
real axletrack,
real timestep,
real& leftWheelVelocity,
real& rightWheelVelocity)
253 const real epsilon = 0.0001f;
254 const wVector& Xs = start.x_ax; FARSA_DEBUG_TEST_INVALID(Xs.x) FARSA_DEBUG_TEST_INVALID(Xs.y) FARSA_DEBUG_TEST_INVALID(Xs.z)
255 const wVector& Xe = end.x_ax; FARSA_DEBUG_TEST_INVALID(Xe.x) FARSA_DEBUG_TEST_INVALID(Xe.y) FARSA_DEBUG_TEST_INVALID(Xe.z)
256 const
real halfAxletrack = axletrack / 2.0f;
257 const wVector displacementVector = end.w_pos - start.w_pos; FARSA_DEBUG_TEST_INVALID(displacementVector.x) FARSA_DEBUG_TEST_INVALID(displacementVector.y) FARSA_DEBUG_TEST_INVALID(displacementVector.z)
258 const
real displacement = displacementVector.norm(); FARSA_DEBUG_TEST_INVALID(displacement)
260 const wVector direction = displacementVector.scale(1.0f / displacement);
263 real leftWheelDistance = 0.0f;
264 real rightWheelDistance = 0.0f;
272 const farsa::
real dotX =
min(1.0f,
max(-1.0f, Xs % Xe)); FARSA_DEBUG_TEST_INVALID(dotX)
273 if (fabs(1.0f - dotX) < epsilon) {
275 if (fabs(displacement) < epsilon) {
276 leftWheelDistance = 0.0f;
277 rightWheelDistance = 0.0f;
282 const farsa::real dotDirY = direction % (-start.y_ax); FARSA_DEBUG_TEST_INVALID(dotDirY)
284 if (fabs(1.0f - dotDirY) < epsilon) {
286 leftWheelDistance = displacement;
287 rightWheelDistance = displacement;
288 }
else if (fabs(1.0f + dotDirY) < epsilon) {
290 leftWheelDistance = -displacement;
291 rightWheelDistance = -displacement;
295 leftWheelDistance = dotDirY * displacement; FARSA_DEBUG_TEST_INVALID(leftWheelDistance)
296 rightWheelDistance = dotDirY * displacement; FARSA_DEBUG_TEST_INVALID(rightWheelDistance)
300 } else if (fabs(1.0f + dotX) < epsilon) {
302 if (fabs(displacement) < epsilon) {
303 leftWheelDistance = PI_GRECO * axletrack;
304 rightWheelDistance = -leftWheelDistance;
308 const farsa::real dotDirX = direction % Xs; FARSA_DEBUG_TEST_INVALID(dotDirX)
310 const
real distCenterOfRotationToCenterOfRobot = displacement / 2.0f; FARSA_DEBUG_TEST_INVALID(distCenterOfRotationToCenterOfRobot)
311 const
real slowWheel = (distCenterOfRotationToCenterOfRobot - halfAxletrack) * PI_GRECO; FARSA_DEBUG_TEST_INVALID(slowWheel)
312 const
real fastWheel = (distCenterOfRotationToCenterOfRobot + halfAxletrack) * PI_GRECO; FARSA_DEBUG_TEST_INVALID(fastWheel)
314 if (fabs(1.0f - dotDirX) < epsilon) {
315 leftWheelDistance = slowWheel;
316 rightWheelDistance = fastWheel;
317 }
else if (fabs(1.0f + dotDirX) < epsilon) {
318 leftWheelDistance = fastWheel;
319 rightWheelDistance = slowWheel;
323 if (dotDirX > 0.0f) {
324 leftWheelDistance = dotDirX * slowWheel; FARSA_DEBUG_TEST_INVALID(leftWheelDistance)
325 rightWheelDistance = dotDirX * fastWheel; FARSA_DEBUG_TEST_INVALID(rightWheelDistance)
327 leftWheelDistance = dotDirX * fastWheel; FARSA_DEBUG_TEST_INVALID(leftWheelDistance)
328 rightWheelDistance = dotDirX * slowWheel; FARSA_DEBUG_TEST_INVALID(rightWheelDistance)
335 const real delta = (Xs.y * Xe.x) - (Xs.x * Xe.y);
336 const real invDelta = 1.0 / delta;
337 const real k1 = invDelta * (Xe.x * displacementVector.y - Xe.y * displacementVector.x);
338 const real k2 = invDelta * (Xs.x * displacementVector.y - Xs.y * displacementVector.x);
343 const real k = (k1 + k2) / 2.0f;
344 if ((delta < epsilon) && (delta > -epsilon)) {
348 leftWheelDistance = displacement;
349 rightWheelDistance = displacement;
351 if (fabs(k1 - k2) >= epsilon) {
357 const real rotationSign = (((Xs * Xe) % start.z_ax) < 0.0f) ? -1.0f : 1.0f; FARSA_DEBUG_TEST_INVALID(rotationSign)
358 const
real angle = acos(dotX) * rotationSign; FARSA_DEBUG_TEST_INVALID(angle)
362 const
real distLeftWheel = k + halfAxletrack; FARSA_DEBUG_TEST_INVALID(distLeftWheel)
363 const
real distRightWheel = k - halfAxletrack; FARSA_DEBUG_TEST_INVALID(distRightWheel)
367 leftWheelDistance = distLeftWheel * angle; FARSA_DEBUG_TEST_INVALID(leftWheelDistance)
368 rightWheelDistance = distRightWheel * angle; FARSA_DEBUG_TEST_INVALID(rightWheelDistance)
373 leftWheelVelocity = (leftWheelDistance / wheelr) / timestep; FARSA_DEBUG_TEST_INVALID(leftWheelVelocity)
374 rightWheelVelocity = (rightWheelDistance / wheelr) / timestep; FARSA_DEBUG_TEST_INVALID(rightWheelVelocity)
382 desiredVel.fill( 0.0, motorsv.size() );
383 minVel.fill( -1.0, motorsv.size() );
384 maxVel.fill( 1.0, motorsv.size() );
392 for(
int i=0; i<motorsv.size(); i++ ) {
393 motorsv[i]->setDesiredVelocity( desiredVel[i] );
398 for(
int i=0; i<qMin(speeds.size(), desiredVel.size()); i++ ) {
399 if ( speeds[i] < minVel[i] ) {
400 desiredVel[i] = minVel[i];
401 }
else if ( speeds[i] > maxVel[i] ) {
402 desiredVel[i] = maxVel[i];
404 desiredVel[i] = speeds[i];
410 if ( sp1 < minVel[0] ) {
411 desiredVel[0] = minVel[0];
412 }
else if ( sp1 > maxVel[0] ) {
413 desiredVel[0] = maxVel[0];
418 if ( sp2 < minVel[1] ) {
419 desiredVel[1] = minVel[1];
420 }
else if ( sp2 > maxVel[1] ) {
421 desiredVel[1] = maxVel[1];
429 for(
int i=0; i<motorsv.size(); i++ ) {
430 speeds.append(motorsv[i]->velocity());
435 sp1 = motorsv[0]->velocity();
436 sp2 = motorsv[1]->velocity();
454 minVel[0] = minSpeed1;
455 minVel[1] = minSpeed2;
456 maxVel[0] = maxSpeed1;
457 maxVel[1] = maxSpeed2;
466 minSpeed1 = minVel[0];
467 minSpeed2 = minVel[1];
468 maxSpeed1 = maxVel[0];
469 maxSpeed2 = maxVel[1];
473 for (
int i = 0; i < motorsv.size(); ++i) {
474 motorsv[i]->setMaxForce( maxTorque );
479 return motorsv[0]->maxForce();
486 m_desiredStatus(Open),
488 m_attachedRobot(NULL),
489 m_otherAttachedRobots()
502 if (m_desiredStatus == m_status) {
507 const Status previousStatus = m_status;
508 m_status = m_desiredStatus;
517 if (m_attachedRobot != NULL) {
523 m_attachedRobot = NULL;
529 if (previousStatus == Open) {
531 m_attachedRobot = tryToAttach();
535 if (m_attachedRobot != NULL) {
540 if (m_attachedRobot != NULL) {
545 m_joint->
dofs()[0]->disableLimits();
546 m_joint->
dofs()[0]->switchOff();
549 if (previousStatus == Open) {
557 if (previousStatus == Open) {
559 m_attachedRobot = tryToAttach();
563 if (m_attachedRobot != NULL) {
568 if (m_attachedRobot != NULL) {
573 if (previousStatus == Open) {
656 m_desiredStatus = status;
660 PhyMarXbot* MarXbotAttachmentDeviceMotorController::tryToAttach()
const
670 QSet<PhyMarXbot*> discardedRobots;
671 QSet<PhyMarXbot*> candidateRobots;
672 foreach (
const Contact& c, contacts) {
674 if ((otherRobot != NULL) && (otherRobot->
attachmentDeviceEnabled()) && (!discardedRobots.contains(otherRobot))) {
678 candidateRobots.insert(otherRobot);
681 discardedRobots.insert(otherRobot);
682 candidateRobots.remove(otherRobot);
690 if (candidateRobots.isEmpty()) {
693 return *(candidateRobots.begin());
697 void MarXbotAttachmentDeviceMotorController::attachmentDeviceAboutToBeDestroyed()
702 m_desiredStatus = Open;
706 if (m_attachedRobot != NULL) {
711 m_attachedRobot = NULL;
715 foreach (
PhyMarXbot* other, m_otherAttachedRobots) {
718 other->attachmentDeviceController()->m_joint = NULL;
719 other->attachmentDeviceController()->m_attachedRobot = NULL;