#include "Move.h" Move* Move::_singleton = 0; Move* Move::singleton() { if (_singleton==0) _singleton = new Move(); return _singleton; } Move::Move() { Serial.println("Move manager created !"); inversedSense = false; sensorEnabled = true; performKind = MOVE_NONE; performStartTimer = 0; performTimeLeft = 0; performRunning = false; // Create the Servos wheelLeft = new Servo(); wheelRight = new Servo(); // Init the servos wheelLeft->attach(PIN_WL,210,2400); //100,1500 || 200,2400 wheelRight->attach(PIN_WR,230,2400); //80,1500 || 220,2400 // Init the sharp sensors initSharp(); actionList = (MoveAction**) malloc(sizeof(MoveAction*) * ACTION_NUMBERS); actionNumber = 0; actionCurrent = 0; performSpeed = 0; performIsAccelerating = false; // Location x = 4.; y = 20.; angle = 0.; previousTime = micros(); stop(); } Move::~Move() { //dtor } void Move::initSharp() { sharpList = (Sharp**) malloc(sizeof(Sharp*) * SHARP_NUMBERS); sharpList[SHARP_FRONT_L] = new Sharp(A1); sharpList[SHARP_FRONT_R] = new Sharp(A3); sharpList[SHARP_FRONT_C] = new Sharp(A4); sharpList[SHARP_BEHIND] = new Sharp(A0); } void Move::updateSharp() { for(int i(0); iupdate(); } void Move::update(int timeSinceLastFrame) { updateSharp(); /*Serial.print(" Sharps (FL, FC, FL, B) : "); Serial.print(sharpList[SHARP_FRONT_L]->getValue()); Serial.print(" "); Serial.print(sharpList[SHARP_FRONT_C]->getValue()); Serial.print(" "); Serial.print(sharpList[SHARP_FRONT_R]->getValue()); Serial.print(" "); Serial.print(analogRead(A1)); Serial.print(" "); Serial.print(sharpList[SHARP_BEHIND]->getValue()); Serial.print("\n");*/ if (performKind!=MOVE_NONE) { if (placeFree(performKind) || performKind==DELAY || performKind==ENABLE_SHARPS || performKind==DISABLE_SHARPS) { if (!performRunning) { Serial.println("Robot no longer Detected, resume action"); DiodeMgr::singleton()->getLed(2)->off(); startAction(performKind); } doAction(performKind); // Timer update if (performIsAccelerating) { if (performSpeed<1.) performSpeed += W_ACC; //if (performTimeLeft < WF_SPEED*performSpeed*W_INVACC) else performIsAccelerating = false; //Serial.println(performSpeed); } else { /*if (performSpeed>0.4) performSpeed -= W_ACC; else */if (performSpeed<0.3) performSpeed = 0.3; } int factor = (micros() - previousTime)*performSpeed; previousTime = micros(); //Serial.println(factor); performTimeLeft -= factor; switch(performKind) { case MOVE_45ANTICLOCK: angle += factor/8334.; break; case MOVE_45CLOCK: angle -= factor/8334.; break; default: x += cos(angle) * factor / MOVE_TIME_DISTANCE_RATIO; y += sin(angle) * factor / MOVE_TIME_DISTANCE_RATIO; break; } if (performTimeLeft <= 0) { performIsAccelerating = false; Serial.print(" Finished ! position (x,y,angle) : ("); Serial.print(x); Serial.print(" "); Serial.print(y); Serial.print(" "); Serial.print(angle); Serial.print(")\n"); Serial.print(" Time spent over the limit : "); Serial.print(-performTimeLeft); Serial.print(" microseconds\n"); stop(); delay(150); } } else if (performRunning) { Serial.println(" Robot Detected, pause..."); Serial.print(" Sharps (FL, FC, FL, B) : "); Serial.print(sharpList[SHARP_FRONT_L]->getValue()); Serial.print(" "); Serial.print(sharpList[SHARP_FRONT_C]->getValue()); Serial.print(" "); Serial.print(sharpList[SHARP_FRONT_R]->getValue()); Serial.print(" "); Serial.print(sharpList[SHARP_BEHIND]->getValue()); Serial.print("\n"); DiodeMgr::singleton()->getLed(2)->on(); pause(); previousTime = micros(); } else previousTime = micros(); } else { // Treat the list if (actionNumber>actionCurrent) { DiodeMgr::singleton()->getLed(1)->on(); perform(actionList[actionCurrent]->getKind(), actionList[actionCurrent]->getDistance()); actionCurrent += 1; } else DiodeMgr::singleton()->getLed(1)->off(); previousTime = micros(); } } bool Move::perform(MOVE_KIND kind, float distance, bool overwrite) { if (kind==MOVE_NONE) { stop(); return true; } if (overwrite || isReady()) { Serial.print("Starting action... "); performStartTimer = micros(); switch(kind) { case DELAY: Serial.print("Delaying Skarabi"); performTimeLeft = distance * 1000; break; case MOVE_45ANTICLOCK: Serial.print(45*distance); Serial.print(" degrees anti-clockwise"); performTimeLeft = W_45ANTITIME * distance; break; case MOVE_45CLOCK: Serial.print(45*distance); Serial.print(" degrees clockwise"); performTimeLeft = W_45CLOCKTIME * distance; break; case DISABLE_SHARPS: setSensor(false); Serial.print(" DISABLING SHARPS"); performTimeLeft = 0; break; case ENABLE_SHARPS: setSensor(true); Serial.print(" ENABLING SHARPS"); performTimeLeft = 0; break; default: performTimeLeft = distance * MOVE_TIME_DISTANCE_RATIO; break; } if (distance>0) { Serial.print(", duration : "); Serial.print(performTimeLeft/1000); Serial.print(" ms"); } Serial.print("\n"); startAction(kind); return true; } else { Serial.println("Can't start an action : the previous one wasn't finished !"); return false; } } void Move::startAction(MOVE_KIND kind) { performKind = kind; performRunning = true; performIsAccelerating = true; performSpeed = 1.; doAction(kind); } void Move::doAction(MOVE_KIND kind) { switch(kind) { case MOVE_FORWARD: wheelLeft->write(WL_STOP + WL_FORWARD*WF_SPEED*performSpeed); wheelRight->write(WR_STOP + WR_FORWARD*WF_SPEED*performSpeed); break; case MOVE_BACKWARD: wheelLeft->write(WL_STOP + WL_BACKWARD*WF_SPEED*performSpeed); wheelRight->write(WR_STOP + WR_BACKWARD*WF_SPEED*performSpeed); break; case MOVE_45ANTICLOCK: wheelLeft->write(WL_STOP + WL_45ANTI*WF_SPEED*performSpeed); wheelRight->write(WR_STOP + WR_45ANTI*WF_SPEED*performSpeed); break; case MOVE_45CLOCK: wheelLeft->write(WL_STOP + WL_45CLOCK*WF_SPEED*performSpeed); wheelRight->write(WR_STOP + WR_45CLOCK*WF_SPEED*performSpeed); break; } } void Move::pause() { performSpeed = 0; wheelLeft->write(WL_STOP); wheelRight->write(WR_STOP); performRunning = false; } void Move::stop() { performSpeed = 0; Serial.println("Robot halted !"); Serial.println(""); wheelLeft->write(WL_STOP); wheelRight->write(WR_STOP); performKind = MOVE_NONE; performRunning = false; } bool Move::isReady() { return (performKind == MOVE_NONE); } void Move::setSensor(bool enable) { sensorEnabled = enable; } void Move::setInversedSense(bool inversed) { inversedSense = inversed; Serial.println("Sense of rotation changed !"); } bool Move::placeFree(MOVE_KIND kind) { if (!sensorEnabled) return true; switch(kind) { case MOVE_FORWARD: return (!(sharpList[SHARP_FRONT_L]->getValue()||sharpList[SHARP_FRONT_R]->getValue()||sharpList[SHARP_FRONT_C]->getValue())); break; case MOVE_BACKWARD: return (!(sharpList[SHARP_BEHIND]->getValue())); break; case MOVE_45ANTICLOCK: return (!sharpList[SHARP_FRONT_L]->getValue()); break; case MOVE_45CLOCK: return (!sharpList[SHARP_FRONT_R]->getValue()); break; default: return false; break; } } void Move::addAction(MOVE_KIND kind, float distance) { if (actionNumber < ACTION_NUMBERS-1) { Serial.println("Action added to the queue !"); // Inverse if needed if (inversedSense) { if (kind==MOVE_45ANTICLOCK) kind = MOVE_45CLOCK; else if (kind==MOVE_45CLOCK) kind = MOVE_45ANTICLOCK; } actionList[actionNumber] = new MoveAction(kind,distance); actionNumber+=1; } else Serial.println("Can't queue action : too many actions !"); }