Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
Motion.cpp
00001 /* 00002 * Motion.cpp 00003 * Copyright (c) 2017, ZHAW 00004 * All rights reserved. 00005 * 00006 * Created on: 02.02.2017 00007 * Author: Marcel Honegger 00008 */ 00009 00010 #include <cmath> 00011 #include <algorithm> 00012 #include "Motion.h" 00013 00014 using namespace std; 00015 00016 const float Motion::DEFAULT_LIMIT = 1.0f; // default value for limits 00017 const float Motion::MINIMUM_LIMIT = 1.0e-6f; // smallest value allowed for limits 00018 00019 /** 00020 * Creates a <code>Motion</code> object. 00021 * The values for position, velocity and acceleration are set to 0. 00022 */ 00023 Motion::Motion() { 00024 00025 position = 0.0; 00026 velocity = 0.0f; 00027 acceleration = 0.0f; 00028 00029 profileVelocity = DEFAULT_LIMIT; 00030 profileAcceleration = DEFAULT_LIMIT; 00031 profileDeceleration = DEFAULT_LIMIT; 00032 } 00033 00034 /** 00035 * Creates a <code>Motion</code> object with given values for position and velocity. 00036 * @param position the initial position value of this motion, given in [m] or [rad]. 00037 * @param velocity the initial velocity value of this motion, given in [m/s] or [rad/s]. 00038 */ 00039 Motion::Motion(double position, float velocity) { 00040 00041 this->position = position; 00042 this->velocity = velocity; 00043 this->acceleration = 0.0f; 00044 00045 profileVelocity = DEFAULT_LIMIT; 00046 profileAcceleration = DEFAULT_LIMIT; 00047 profileDeceleration = DEFAULT_LIMIT; 00048 } 00049 00050 /** 00051 * Creates a <code>Motion</code> object with given values for position, velocity and acceleration. 00052 * @param position the initial position value of this motion, given in [m] or [rad]. 00053 * @param velocity the initial velocity value of this motion, given in [m/s] or [rad/s]. 00054 * @param acceleration the initial acceleration value of this motion, given in [m/s²] or [rad/s²]. 00055 */ 00056 Motion::Motion(double position, float velocity, float acceleration) { 00057 00058 this->position = position; 00059 this->velocity = velocity; 00060 this->acceleration = acceleration; 00061 00062 profileVelocity = DEFAULT_LIMIT; 00063 profileAcceleration = DEFAULT_LIMIT; 00064 profileDeceleration = DEFAULT_LIMIT; 00065 } 00066 00067 /** 00068 * Creates a <code>Motion</code> object with given values for position, velocity and acceleration. 00069 * @param position the initial position value of this motion, given in [m] or [rad]. 00070 * @param velocity the initial velocity value of this motion, given in [m/s] or [rad/s]. 00071 * @param profileVelocity the limit of the velocity. 00072 * @param profileAcceleration the limit of the acceleration. 00073 * @param profileDeceleration equal to profileAcceleration. 00074 */ 00075 Motion::Motion(double position, float velocity, float profileVelocity, float profileAcceleration) { 00076 00077 this->position = position; 00078 this->velocity = velocity; 00079 this->acceleration = 0.0f; 00080 00081 this->profileVelocity = profileVelocity; 00082 this->profileAcceleration = profileAcceleration; 00083 this->profileDeceleration = profileAcceleration; 00084 } 00085 00086 /** 00087 * Creates a <code>Motion</code> object with given values for position and velocity. 00088 * @param motion another <code>Motion</code> object to copy the values from. 00089 */ 00090 Motion::Motion(const Motion& motion) { 00091 00092 position = motion.position; 00093 velocity = motion.velocity; 00094 acceleration = motion.acceleration; 00095 00096 profileVelocity = motion.profileVelocity; 00097 profileAcceleration = motion.profileAcceleration; 00098 profileDeceleration = motion.profileDeceleration; 00099 } 00100 00101 Motion::~Motion() {} 00102 00103 /** 00104 * Sets the values for position and velocity. 00105 * @param position the desired position value of this motion, given in [m] or [rad]. 00106 * @param velocity the desired velocity value of this motion, given in [m/s] or [rad/s]. 00107 */ 00108 void Motion::set(double position, float velocity) { 00109 00110 this->position = position; 00111 this->velocity = velocity; 00112 } 00113 00114 /** 00115 * Sets the values for position, velocity and acceleration. 00116 * @param position the desired position value of this motion, given in [m] or [rad]. 00117 * @param velocity the desired velocity value of this motion, given in [m/s] or [rad/s]. 00118 * @param acceleration the desired acceleration value of this motion, given in [m/s²] or [rad/s²]. 00119 */ 00120 void Motion::set(double position, float velocity, float acceleration) { 00121 00122 this->position = position; 00123 this->velocity = velocity; 00124 this->acceleration = acceleration; 00125 } 00126 00127 /** 00128 * Sets the values for position, velocity and acceleration. 00129 * @param motion another <code>Motion</code> object to copy the values from. 00130 */ 00131 void Motion::set(const Motion& motion) { 00132 00133 position = motion.position; 00134 velocity = motion.velocity; 00135 acceleration = motion.acceleration; 00136 } 00137 00138 /** 00139 * Sets the position value. 00140 * @param position the desired position value of this motion, given in [m] or [rad]. 00141 */ 00142 void Motion::setPosition(double position) { 00143 00144 this->position = position; 00145 } 00146 00147 /** 00148 * Gets the position value. 00149 * @return the position value of this motion, given in [m] or [rad]. 00150 */ 00151 double Motion::getPosition() { 00152 00153 return position; 00154 } 00155 00156 /** 00157 * Sets the velocity value. 00158 * @param velocity the desired velocity value of this motion, given in [m/s] or [rad/s]. 00159 */ 00160 void Motion::setVelocity(float velocity) { 00161 00162 this->velocity = velocity; 00163 } 00164 00165 /** 00166 * Gets the velocity value. 00167 * @return the velocity value of this motion, given in [m/s] or [rad/s]. 00168 */ 00169 float Motion::getVelocity() { 00170 00171 return velocity; 00172 } 00173 00174 /** 00175 * Sets the acceleration value. 00176 * @param acceleration the desired acceleration value of this motion, given in [m/s²] or [rad/s²]. 00177 */ 00178 void Motion::setAcceleration(float acceleration) { 00179 00180 this->acceleration = acceleration; 00181 } 00182 00183 /** 00184 * Gets the acceleration value. 00185 * @return the acceleration value of this motion, given in [m/s²] or [rad/s²]. 00186 */ 00187 float Motion::getAcceleration() { 00188 00189 return acceleration; 00190 } 00191 00192 /** 00193 * Sets the limit for the velocity value. 00194 * @param profileVelocity the limit of the velocity. 00195 */ 00196 void Motion::setProfileVelocity(float profileVelocity) { 00197 00198 if (profileVelocity > MINIMUM_LIMIT) this->profileVelocity = profileVelocity; else this->profileVelocity = MINIMUM_LIMIT; 00199 } 00200 00201 /** 00202 * Sets the limit for the acceleration value. 00203 * @param profileAcceleration the limit of the acceleration. 00204 */ 00205 void Motion::setProfileAcceleration(float profileAcceleration) { 00206 00207 if (profileAcceleration > MINIMUM_LIMIT) this->profileAcceleration = profileAcceleration; else this->profileAcceleration = MINIMUM_LIMIT; 00208 } 00209 00210 /** 00211 * Sets the limit for the deceleration value. 00212 * @param profileDeceleration the limit of the deceleration. 00213 */ 00214 void Motion::setProfileDeceleration(float profileDeceleration) { 00215 00216 if (profileDeceleration > MINIMUM_LIMIT) this->profileDeceleration = profileDeceleration; else this->profileDeceleration = MINIMUM_LIMIT; 00217 } 00218 00219 /** 00220 * Sets the limits for velocity, acceleration and deceleration values. 00221 * @param profileVelocity the limit of the velocity. 00222 * @param profileAcceleration the limit of the acceleration. 00223 * @param profileDeceleration the limit of the deceleration. 00224 */ 00225 void Motion::setLimits(float profileVelocity, float profileAcceleration, float profileDeceleration) { 00226 00227 if (profileVelocity > MINIMUM_LIMIT) this->profileVelocity = profileVelocity; else this->profileVelocity = MINIMUM_LIMIT; 00228 if (profileAcceleration > MINIMUM_LIMIT) this->profileAcceleration = profileAcceleration; else this->profileAcceleration = MINIMUM_LIMIT; 00229 if (profileDeceleration > MINIMUM_LIMIT) this->profileDeceleration = profileDeceleration; else this->profileDeceleration = MINIMUM_LIMIT; 00230 } 00231 00232 /** 00233 * Gets the time needed to move to a given target position. 00234 * @param targetPosition the desired target position given in [m] or [rad]. 00235 * @return the time to move to the target position, given in [s]. 00236 */ 00237 float Motion::getTimeToPosition(double targetPosition) { 00238 00239 // calculate position, when velocity is reduced to zero 00240 00241 double stopPosition = (velocity > 0.0f) ? position+static_cast<double>(velocity*velocity/profileDeceleration*0.5f) : position-static_cast<double>(velocity*velocity/profileDeceleration*0.5f); 00242 00243 if (targetPosition > stopPosition) { // positive velocity required 00244 00245 if (velocity > profileVelocity) { // slow down to profile velocity first 00246 00247 float t1 = (velocity-profileVelocity)/profileDeceleration; 00248 float t2 = static_cast<float>(targetPosition-stopPosition)/profileVelocity; 00249 float t3 = profileVelocity/profileDeceleration; 00250 00251 return t1+t2+t3; 00252 00253 } else if (velocity > 0.0f) { // speed up to profile velocity 00254 00255 float t1 = (profileVelocity-velocity)/profileAcceleration; 00256 float t3 = profileVelocity/profileDeceleration; 00257 float t2 = (static_cast<float>(targetPosition-position)-(velocity+profileVelocity)*0.5f*t1)/profileVelocity-0.5f*t3; 00258 00259 if (t2 < 0.0f) { 00260 float maxVelocity = sqrt((2.0f*static_cast<float>(targetPosition-position)*profileAcceleration+velocity*velocity)*profileDeceleration/(profileAcceleration+profileDeceleration)); 00261 t1 = (maxVelocity-velocity)/profileAcceleration; 00262 t2 = 0.0f; 00263 t3 = maxVelocity/profileDeceleration; 00264 } 00265 00266 return t1+t2+t3; 00267 00268 } else { // slow down to zero first, and then speed up to profile velocity 00269 00270 float t1 = -velocity/profileDeceleration; 00271 float t2 = profileVelocity/profileAcceleration; 00272 float t4 = profileVelocity/profileDeceleration; 00273 float t3 = (static_cast<float>(targetPosition-position)-velocity*0.5f*t1)/profileVelocity-0.5f*(t2+t4); 00274 00275 if (t3 < 0.0f) { 00276 float maxVelocity = sqrt((2.0f*static_cast<float>(targetPosition-position)*profileDeceleration+velocity*velocity)*profileAcceleration/(profileAcceleration+profileDeceleration)); 00277 t2 = maxVelocity/profileAcceleration; 00278 t3 = 0.0f; 00279 t4 = maxVelocity/profileDeceleration; 00280 } 00281 00282 return t1+t2+t3+t4; 00283 } 00284 00285 } else { // negative velocity required 00286 00287 if (velocity < -profileVelocity) { // slow down to (negative) profile velocity first 00288 00289 float t1 = (-profileVelocity-velocity)/profileDeceleration; 00290 float t2 = static_cast<float>(stopPosition-targetPosition)/profileVelocity; 00291 float t3 = profileVelocity/profileDeceleration; 00292 00293 return t1+t2+t3; 00294 00295 } else if (velocity < 0.0f) { // speed up to (negative) profile velocity 00296 00297 float t1 = (velocity+profileVelocity)/profileAcceleration; 00298 float t3 = profileVelocity/profileDeceleration; 00299 float t2 = (static_cast<float>(position-targetPosition)+(velocity-profileVelocity)*0.5f*t1)/profileVelocity-0.5f*t3; 00300 00301 if (t2 < 0.0f) { 00302 float minVelocity = -sqrt((-2.0f*static_cast<float>(targetPosition-position)*profileAcceleration+velocity*velocity)*profileDeceleration/(profileAcceleration+profileDeceleration)); 00303 t1 = (velocity-minVelocity)/profileAcceleration; 00304 t2 = 0.0f; 00305 t3 = -minVelocity/profileDeceleration; 00306 } 00307 00308 return t1+t2+t3; 00309 00310 } else { // slow down to zero first, and then speed up to (negative) profile velocity 00311 00312 float t1 = velocity/profileDeceleration; 00313 float t2 = profileVelocity/profileAcceleration; 00314 float t4 = profileVelocity/profileDeceleration; 00315 float t3 = (-static_cast<float>(targetPosition-position)+velocity*0.5f*t1)/profileVelocity-0.5f*(t2+t4); 00316 00317 if (t3 < 0.0f) { 00318 float minVelocity = -sqrt((-2.0f*static_cast<float>(targetPosition-position)*profileDeceleration+velocity*velocity)*profileAcceleration/(profileAcceleration+profileDeceleration)); 00319 t2 = -minVelocity/profileAcceleration; 00320 t3 = 0.0f; 00321 t4 = -minVelocity/profileDeceleration; 00322 } 00323 00324 return t1+t2+t3+t4; 00325 } 00326 } 00327 } 00328 00329 /** 00330 * Gets the distance moved until the velocity reaches zero. 00331 * @return the distance to the stop position. 00332 */ 00333 double Motion::getDistanceToStop() { 00334 00335 return static_cast<double>(velocity*velocity/profileDeceleration*0.5f); 00336 } 00337 00338 /** 00339 * Increments the current motion towards a given target velocity. 00340 * @param targetVelocity the desired target velocity given in [m/s] or [rad/s]. 00341 * @param period the time period to increment the motion values for, given in [s]. 00342 */ 00343 void Motion::incrementToVelocity(float targetVelocity, float period) { 00344 00345 if (targetVelocity < -profileVelocity) targetVelocity = -profileVelocity; 00346 else if (targetVelocity > profileVelocity) targetVelocity = profileVelocity; 00347 00348 if (targetVelocity > 0.0f) { 00349 00350 if (velocity > targetVelocity) { // slow down to target velocity 00351 00352 float t1 = (velocity-targetVelocity)/profileDeceleration; 00353 00354 if (t1 > period) { 00355 position += static_cast<double>((velocity-profileDeceleration*0.5f*period)*period); 00356 velocity += -profileDeceleration*period; 00357 acceleration = -profileDeceleration; 00358 } else { 00359 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00360 velocity += -profileDeceleration*t1; 00361 position += static_cast<double>(velocity*(period-t1)); 00362 acceleration = 0.0f; 00363 } 00364 00365 } else if (velocity > 0.0f) { // speed up to target velocity 00366 00367 float t1 = (targetVelocity-velocity)/profileAcceleration; 00368 00369 if (t1 > period) { 00370 position += static_cast<double>((velocity+profileAcceleration*0.5f*period)*period); 00371 velocity += profileAcceleration*period; 00372 acceleration = profileAcceleration; 00373 } else { 00374 position += static_cast<double>((velocity+profileAcceleration*0.5f*t1)*t1); 00375 velocity += profileAcceleration*t1; 00376 position += static_cast<double>(velocity*(period-t1)); 00377 acceleration = 0.0f; 00378 } 00379 00380 } else { // slow down to zero first, and then speed up to target velocity 00381 00382 float t1 = -velocity/profileDeceleration; 00383 float t2 = targetVelocity/profileAcceleration; 00384 00385 if (t1 > period) { 00386 position += static_cast<double>((velocity+profileDeceleration*0.5f*period)*period); 00387 velocity += profileDeceleration*period; 00388 acceleration = profileDeceleration; 00389 } else if (t1+t2 > period) { 00390 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00391 velocity += profileDeceleration*t1; 00392 position += static_cast<double>((velocity+profileAcceleration*0.5f*(period-t1))*(period-t1)); 00393 velocity += profileAcceleration*(period-t1); 00394 acceleration = profileAcceleration; 00395 } else { 00396 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00397 velocity += profileDeceleration*t1; 00398 position += static_cast<double>((velocity+profileAcceleration*0.5f*t2)*t2); 00399 velocity += profileAcceleration*t2; 00400 position += static_cast<double>(velocity*(period-t1-t2)); 00401 acceleration = 0.0f; 00402 } 00403 } 00404 00405 } else { 00406 00407 if (velocity < targetVelocity) { // slow down to (negative) target velocity 00408 00409 float t1 = (targetVelocity-velocity)/profileDeceleration; 00410 00411 if (t1 > period) { 00412 position += static_cast<double>((velocity+profileDeceleration*0.5f*period)*period); 00413 velocity += profileDeceleration*period; 00414 acceleration = profileDeceleration; 00415 } else { 00416 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00417 velocity += profileDeceleration*t1; 00418 position += static_cast<double>(velocity*(period-t1)); 00419 acceleration = 0.0f; 00420 } 00421 00422 } else if (velocity < 0.0f) { // speed up to (negative) target velocity 00423 00424 float t1 = (velocity-targetVelocity)/profileAcceleration; 00425 00426 if (t1 > period) { 00427 position += static_cast<double>((velocity-profileAcceleration*0.5f*period)*period); 00428 velocity += -profileAcceleration*period; 00429 acceleration = -profileAcceleration; 00430 } else { 00431 position += static_cast<double>((velocity-profileAcceleration*0.5f*t1)*t1); 00432 velocity += -profileAcceleration*t1; 00433 position += static_cast<double>(velocity*(period-t1)); 00434 acceleration = 0.0f; 00435 } 00436 00437 } else { // slow down to zero first, and then speed up to (negative) target velocity 00438 00439 float t1 = velocity/profileDeceleration; 00440 float t2 = -targetVelocity/profileAcceleration; 00441 00442 if (t1 > period) { 00443 position += static_cast<double>((velocity-profileDeceleration*0.5f*period)*period); 00444 velocity += -profileDeceleration*period; 00445 acceleration = -profileDeceleration; 00446 } else if (t1+t2 > period) { 00447 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00448 velocity += -profileDeceleration*t1; 00449 position += static_cast<double>((velocity-profileAcceleration*0.5f*(period-t1))*(period-t1)); 00450 velocity += -profileAcceleration*(period-t1); 00451 acceleration = -profileAcceleration; 00452 } else { 00453 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00454 velocity += -profileDeceleration*t1; 00455 position += static_cast<double>((velocity-profileAcceleration*0.5f*t2)*t2); 00456 velocity += -profileAcceleration*t2; 00457 position += static_cast<double>(velocity*(period-t1-t2)); 00458 acceleration = 0.0f; 00459 } 00460 } 00461 } 00462 } 00463 00464 /** 00465 * Increments the current motion towards a given target position. 00466 * @param targetPosition the desired target position given in [m] or [rad]. 00467 * @param period the time period to increment the motion values for, given in [s]. 00468 */ 00469 void Motion::incrementToPosition(double targetPosition, float period) { 00470 00471 // calculate position, when velocity is reduced to zero 00472 00473 double stopPosition = (velocity > 0.0f) ? position+static_cast<double>(velocity*velocity/profileDeceleration*0.5f) : position-static_cast<double>(velocity*velocity/profileDeceleration*0.5f); 00474 00475 if (targetPosition > stopPosition) { // positive velocity required 00476 00477 if (velocity > profileVelocity) { // slow down to profile velocity first 00478 00479 float t1 = (velocity-profileVelocity)/profileDeceleration; 00480 float t2 = static_cast<float>(targetPosition-stopPosition)/profileVelocity; 00481 float t3 = profileVelocity/profileDeceleration; 00482 00483 if (t1 > period) { 00484 position += static_cast<double>((velocity-profileDeceleration*0.5f*period)*period); 00485 velocity += -profileDeceleration*period; 00486 acceleration = -profileDeceleration; 00487 } else if (t1+t2 > period) { 00488 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00489 velocity += -profileDeceleration*t1; 00490 position += static_cast<double>(velocity*(period-t1)); 00491 acceleration = 0.0f; 00492 } else if (t1+t2+t3 > period) { 00493 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00494 velocity += -profileDeceleration*t1; 00495 position += static_cast<double>(velocity*t2); 00496 position += static_cast<double>((velocity-profileDeceleration*0.5f*(period-t1-t2))*(period-t1-t2)); 00497 velocity += -profileDeceleration*(period-t1-t2); 00498 acceleration = -profileDeceleration; 00499 } else { 00500 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00501 velocity += -profileDeceleration*t1; 00502 position += static_cast<double>(velocity*t2); 00503 position += static_cast<double>((velocity-profileDeceleration*0.5f*t3)*t3); 00504 velocity += -profileDeceleration*t3; 00505 acceleration = 0.0f; 00506 } 00507 00508 } else if (velocity > 0.0f) { // speed up to profile velocity 00509 00510 float t1 = (profileVelocity-velocity)/profileAcceleration; 00511 float t3 = profileVelocity/profileDeceleration; 00512 float t2 = (static_cast<float>(targetPosition-position)-(velocity+profileVelocity)*0.5f*t1)/profileVelocity-0.5f*t3; 00513 00514 if (t2 < 0.0f) { 00515 float maxVelocity = sqrt((2.0f*static_cast<float>(targetPosition-position)*profileAcceleration+velocity*velocity)*profileDeceleration/(profileAcceleration+profileDeceleration)); 00516 t1 = (maxVelocity-velocity)/profileAcceleration; 00517 t2 = 0.0f; 00518 t3 = maxVelocity/profileDeceleration; 00519 } 00520 00521 if (t1 > period) { 00522 position += static_cast<double>((velocity+profileAcceleration*0.5f*period)*period); 00523 velocity += profileAcceleration*period; 00524 acceleration = profileAcceleration; 00525 } else if (t1+t2 > period) { 00526 position += static_cast<double>((velocity+profileAcceleration*0.5f*t1)*t1); 00527 velocity += profileAcceleration*t1; 00528 position += static_cast<double>(velocity*(period-t1)); 00529 acceleration = 0.0f; 00530 } else if (t1+t2+t3 > period) { 00531 position += static_cast<double>((velocity+profileAcceleration*0.5f*t1)*t1); 00532 velocity += profileAcceleration*t1; 00533 position += static_cast<double>(velocity*t2); 00534 position += static_cast<double>((velocity-profileDeceleration*0.5f*(period-t1-t2))*(period-t1-t2)); 00535 velocity += -profileDeceleration*(period-t1-t2); 00536 acceleration = -profileDeceleration; 00537 } else { 00538 position += static_cast<double>((velocity+profileAcceleration*0.5f*t1)*t1); 00539 velocity += profileAcceleration*t1; 00540 position += static_cast<double>(velocity*t2); 00541 position += static_cast<double>((velocity-profileDeceleration*0.5f*t3)*t3); 00542 velocity += -profileDeceleration*t3; 00543 acceleration = 0.0f; 00544 } 00545 00546 } else { // slow down to zero first, and then speed up to profile velocity 00547 00548 float t1 = -velocity/profileDeceleration; 00549 float t2 = profileVelocity/profileAcceleration; 00550 float t4 = profileVelocity/profileDeceleration; 00551 float t3 = (static_cast<float>(targetPosition-position)-velocity*0.5f*t1)/profileVelocity-0.5f*(t2+t4); 00552 00553 if (t3 < 0.0f) { 00554 float maxVelocity = sqrt((2.0f*static_cast<float>(targetPosition-position)*profileDeceleration+velocity*velocity)*profileAcceleration/(profileAcceleration+profileDeceleration)); 00555 t2 = maxVelocity/profileAcceleration; 00556 t3 = 0.0f; 00557 t4 = maxVelocity/profileDeceleration; 00558 } 00559 00560 if (t1 > period) { 00561 position += static_cast<double>((velocity+profileDeceleration*0.5f*period)*period); 00562 velocity += profileDeceleration*period; 00563 acceleration = profileDeceleration; 00564 } else if (t1+t2 > period) { 00565 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00566 velocity += profileDeceleration*t1; 00567 position += static_cast<double>((velocity+profileAcceleration*0.5f*(period-t1))*(period-t1)); 00568 velocity += profileAcceleration*(period-t1); 00569 acceleration = profileAcceleration; 00570 } else if (t1+t2+t3 > period) { 00571 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00572 velocity += profileDeceleration*t1; 00573 position += static_cast<double>((velocity+profileAcceleration*0.5f*t2)*t2); 00574 velocity += profileAcceleration*t2; 00575 position += static_cast<double>(velocity*(period-t1-t2)); 00576 acceleration = 0.0f; 00577 } else if (t1+t2+t3+t4 > period) { 00578 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00579 velocity += profileDeceleration*t1; 00580 position += static_cast<double>((velocity+profileAcceleration*0.5f*t2)*t2); 00581 velocity += profileAcceleration*t2; 00582 position += static_cast<double>(velocity*t3); 00583 position += static_cast<double>((velocity-profileDeceleration*0.5f*(period-t1-t2-t3))*(period-t1-t2-t3)); 00584 velocity += -profileDeceleration*(period-t1-t2-t3); 00585 acceleration = -profileDeceleration; 00586 } else { 00587 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00588 velocity += profileDeceleration*t1; 00589 position += static_cast<double>((velocity+profileAcceleration*0.5f*t2)*t2); 00590 velocity += profileAcceleration*t2; 00591 position += static_cast<double>(velocity*t3); 00592 position += static_cast<double>((velocity-profileDeceleration*0.5f*t4)*t4); 00593 velocity += -profileDeceleration*t4; 00594 acceleration = 0.0f; 00595 } 00596 } 00597 00598 } else { // negative velocity required 00599 00600 if (velocity < -profileVelocity) { // slow down to (negative) profile velocity first 00601 00602 float t1 = (-profileVelocity-velocity)/profileDeceleration; 00603 float t2 = static_cast<float>(stopPosition-targetPosition)/profileVelocity; 00604 float t3 = profileVelocity/profileDeceleration; 00605 00606 if (t1 > period) { 00607 position += static_cast<double>((velocity+profileDeceleration*0.5f*period)*period); 00608 velocity += profileDeceleration*period; 00609 acceleration = profileDeceleration; 00610 } else if (t1+t2 > period) { 00611 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00612 velocity += profileDeceleration*t1; 00613 position += static_cast<double>(velocity*(period-t1)); 00614 acceleration = 0.0f; 00615 } else if (t1+t2+t3 > period) { 00616 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00617 velocity += profileDeceleration*t1; 00618 position += static_cast<double>(velocity*t2); 00619 position += static_cast<double>((velocity+profileDeceleration*0.5f*(period-t1-t2))*(period-t1-t2)); 00620 velocity += profileDeceleration*(period-t1-t2); 00621 acceleration = profileDeceleration; 00622 } else { 00623 position += static_cast<double>((velocity+profileDeceleration*0.5f*t1)*t1); 00624 velocity += profileDeceleration*t1; 00625 position += static_cast<double>(velocity*t2); 00626 position += static_cast<double>((velocity+profileDeceleration*0.5f*t3)*t3); 00627 velocity += profileDeceleration*t3; 00628 acceleration = 0.0f; 00629 } 00630 00631 } else if (velocity < 0.0f) { // speed up to (negative) profile velocity 00632 00633 float t1 = (velocity+profileVelocity)/profileAcceleration; 00634 float t3 = profileVelocity/profileDeceleration; 00635 float t2 = (static_cast<float>(position-targetPosition)+(velocity-profileVelocity)*0.5f*t1)/profileVelocity-0.5f*t3; 00636 00637 if (t2 < 0.0f) { 00638 float minVelocity = -sqrt((-2.0f*static_cast<float>(targetPosition-position)*profileAcceleration+velocity*velocity)*profileDeceleration/(profileAcceleration+profileDeceleration)); 00639 t1 = (velocity-minVelocity)/profileAcceleration; 00640 t2 = 0.0f; 00641 t3 = -minVelocity/profileDeceleration; 00642 } 00643 00644 if (t1 > period) { 00645 position += static_cast<double>((velocity-profileAcceleration*0.5f*period)*period); 00646 velocity += -profileAcceleration*period; 00647 acceleration = -profileAcceleration; 00648 } else if (t1+t2 > period) { 00649 position += static_cast<double>((velocity-profileAcceleration*0.5f*t1)*t1); 00650 velocity += -profileAcceleration*t1; 00651 position += static_cast<double>(velocity*(period-t1)); 00652 acceleration = 0.0f; 00653 } else if (t1+t2+t3 > period) { 00654 position += static_cast<double>((velocity-profileAcceleration*0.5f*t1)*t1); 00655 velocity += -profileAcceleration*t1; 00656 position += static_cast<double>(velocity*t2); 00657 position += static_cast<double>((velocity+profileDeceleration*0.5f*(period-t1-t2))*(period-t1-t2)); 00658 velocity += profileDeceleration*(period-t1-t2); 00659 acceleration = profileDeceleration; 00660 } else { 00661 position += static_cast<double>((velocity-profileAcceleration*0.5f*t1)*t1); 00662 velocity += -profileAcceleration*t1; 00663 position += static_cast<double>(velocity*t2); 00664 position += static_cast<double>((velocity+profileDeceleration*0.5f*t3)*t3); 00665 velocity += profileDeceleration*t3; 00666 acceleration = 0.0f; 00667 } 00668 00669 } else { // slow down to zero first, and then speed up to (negative) profile velocity 00670 00671 float t1 = velocity/profileDeceleration; 00672 float t2 = profileVelocity/profileAcceleration; 00673 float t4 = profileVelocity/profileDeceleration; 00674 float t3 = (-static_cast<float>(targetPosition-position)+velocity*0.5f*t1)/profileVelocity-0.5f*(t2+t4); 00675 00676 if (t3 < 0.0f) { 00677 float minVelocity = -sqrt((-2.0f*static_cast<float>(targetPosition-position)*profileDeceleration+velocity*velocity)*profileAcceleration/(profileAcceleration+profileDeceleration)); 00678 t2 = -minVelocity/profileAcceleration; 00679 t3 = 0.0f; 00680 t4 = -minVelocity/profileDeceleration; 00681 } 00682 00683 if (t1 > period) { 00684 position += static_cast<double>((velocity-profileDeceleration*0.5f*period)*period); 00685 velocity += -profileDeceleration*period; 00686 acceleration = -profileDeceleration; 00687 } else if (t1+t2 > period) { 00688 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00689 velocity += -profileDeceleration*t1; 00690 position += static_cast<double>((velocity-profileAcceleration*0.5f*(period-t1))*(period-t1)); 00691 velocity += -profileAcceleration*(period-t1); 00692 acceleration = -profileAcceleration; 00693 } else if (t1+t2+t3 > period) { 00694 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00695 velocity += -profileDeceleration*t1; 00696 position += static_cast<double>((velocity-profileAcceleration*0.5f*t2)*t2); 00697 velocity += -profileAcceleration*t2; 00698 position += static_cast<double>(velocity*(period-t1-t2)); 00699 acceleration = 0.0f; 00700 } else if (t1+t2+t3+t4 > period) { 00701 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00702 velocity += -profileDeceleration*t1; 00703 position += static_cast<double>((velocity-profileAcceleration*0.5f*t2)*t2); 00704 velocity += -profileAcceleration*t2; 00705 position += static_cast<double>(velocity*t3); 00706 position += static_cast<double>((velocity+profileDeceleration*0.5f*(period-t1-t2-t3))*(period-t1-t2-t3)); 00707 velocity += profileDeceleration*(period-t1-t2-t3); 00708 acceleration = profileDeceleration; 00709 } else { 00710 position += static_cast<double>((velocity-profileDeceleration*0.5f*t1)*t1); 00711 velocity += -profileDeceleration*t1; 00712 position += static_cast<double>((velocity-profileAcceleration*0.5f*t2)*t2); 00713 velocity += -profileAcceleration*t2; 00714 position += static_cast<double>(velocity*t3); 00715 position += static_cast<double>((velocity+profileDeceleration*0.5f*t4)*t4); 00716 velocity += profileDeceleration*t4; 00717 acceleration = 0.0f; 00718 } 00719 } 00720 } 00721 }
Generated on Wed Jul 20 2022 10:02:38 by
1.7.2