My Version of CreaBotLib
Fork of CreaBotLib by
CreaBot.cpp
- Committer:
- sepp_nepp
- Date:
- 2019-01-01
- Revision:
- 7:3a793ddc3490
- Parent:
- 6:4d8938b686a6
- Child:
- 9:efe9f76d6f76
File content as of revision 7:3a793ddc3490:
#include "CreaBot.h" // ***************************************************************** // BotCommand Structure Helper // ***************************************************************** // Struct Helper; set structure fields to values */ void BotCommand::set(BotCmdVerb Acommand, float Aangle_deg, float Adist_cm) { command = Acommand; dist_cm = Adist_cm; angle_deg= Aangle_deg; }; // Struct Helper; set structure fields to values */ void BotCommand::set(BotCmdVerb Acommand, float Aparam) { command = Acommand; dist_cm = Aparam; angle_deg= Aparam; }; // ***************************************************************** // circle_geos Structure Helper // ***************************************************************** void circle_geos:( float Adiam_cm) /**< Helper; set diameter and perim to values */ { diam_cm = Adiam_cm; perim_cm = PI*diam_cm; degree_per_cm=360.0f/perim_cm; } // ***************************************************************** // CommandFIFO Class // ***************************************************************** // Class Creator: initializes an empties FIFO CommandFIFO::CommandFIFO() { readIdx = writeIdx = Count = 0; cmd_idle.set(IDLE, 0, 0); } // Reserve a new element at the head of the FIFO BotCommand *CommandFIFO::put() { if( !isFull() ) { int old_writeIdx = writeIdx; writeIdx++; if (writeIdx==DEPTH_FIFO) writeIdx=0; Count++; return &cmd[old_writeIdx]; } else return NULL; }; // put() // Get and remove the oldest element at the tail of the FIFO BotCommand *CommandFIFO::get() { if ( !isEmpty() ) { int old_readIdx = readIdx; readIdx++; if (readIdx==DEPTH_FIFO) readIdx=0; Count--; return &cmd[old_readIdx]; } else return NULL; }; // get() // ***************************************************************** // Creabot Class // ***************************************************************** Creabot::Creabot(Motor *left, Motor *right, float diameter_wheel_cm, float bot_diam_cm): motor_left(left), motor_right(right), { // Initialize wheel and bot geometires wheel.setDiam(wheel_diam_cm); bot.setDiam(bot_diam_cm); // some other parameters: ratio_wheel_bot=bot_diam_cm/wheel_diam_cm; bot_speed_cm_sec = DEFAULT_SPEED_CM_SEC; // Attach the Crabot functions as callbacks to the motors motor_left->callbackSet(this, &Creabot::cbLeftMotStopped); motor_right->callbackSet(this, &Creabot::cbRightMotStopped); // Initialize own callback as empty extCallBack = NULL; // Initialize the own status fields MotState = LRMOTS_STOP; executingFifo= false; } void Creabot::fifo(BotCmdVerb moveType, float angle_or_cm) { BotCommand *cmd = fifoBot.put(); if(cmd != NULL) { cmd->set(moveType, angle_or_cm, 0); } executeFifo(); } void Creabot::fifo(BotCmdVerb moveType, float angle_deg, float dist_cm) { BotCommand *cmd = fifoBot.put(); if(cmd!=NULL) { cmd->set(moveType, angle_deg, dist_cm); } executeFifo(); } void Creabot::flushFifo() { fifoBot.empty(); if(executingFifo) botTicker.detach(); executingFifo=false; } int Creabot::moveInFifo() { return fifoBot.getCount(); } void Creabot::spirale(float b, float turns) { float r=0.0f; float angle_deg = 0.0f; while(angle_deg < float( 360.0f * turns) ) { this->moveAndWait(RIGHT, 10, r); r=r+b; } } // This is the own callback function of the ticker, that works throught the FIFO stack void Creabot::executeFifo() { if (fifoBot.isEmpty()) flushFifo(); else { if(endMove) { BotCommand *cmd = fifoBot.get(); executeCommand(cmd); if (!executingFifo) botTicker.attach_us( callback( this, &Creabot::executeFifo), 3150); executingFifo=true; } } } //************************************************************************** // Using the BotCmdVerb to encode different commands, done immediately //************************************************************************** void Creabot::moveAndWait(BotCmdVerb moveType, float Aparam) { move(moveType,Aparam); waitEndMove(); } void Creabot::moveAndWait(BotCmdVerb moveType, float Aangle_deg, float Adist_cm) { move(moveType,Aangle_deg,Adist_cm); waitEndMove(); } void Creabot::move(BotCmdVerb moveType, float Aparam) { move(moveType, Aparam, Aparam) } void Creabot::move(BotCmdVerb moveType, float Aangle_deg, float Adist_cm) { BotCommand Anew_cmd; Anew_cmd.set(moveType, Aangle_deg, Adist_cm); executeCommand(&Anew_cmd); } // Direct Command Execution, also called by FIFO-Handler. void Creabot::executeCommand(BotCommand *cmd) { switch (cmd->command) { case FORWARD: moveForward(cmd->dist_cm); break; case BACKWARD: moveBackward(cmd->dist_cm); break; case ROTATE: rotate(cmd->angle_deg); break; case LEFT: moveLeft(cmd->angle_deg, cmd->dist_cm); break; case RIGHT: moveRight(cmd->angle_deg, cmd->dist_cm); break; case IDLE: default: break; }; }; // executeCommand void Creabot::stopAll() { flushFifo(); stopMotors(); } // ***************************************************************** // Creabot Mid level control functions: // all directly access the motor, no FIFO */ // ***************************************************************** // set bot_speed_cm_sec parameter for next high level commands void Creabot::setBotSpeed(float Abot_speed_cm_sec) { if (Abot_speed_cm_sec < MAX_SPEED_CM_P_SEC) && (Abot_speed_cm_sec>MIN_SPEED_CM_SEC) bot_speed_cm_sec = Abot_speed_cm_sec; // Low level setting of motor speed is done inside SetMotsSpeed: } // Mid level control function: move bot forward for a given distance void Creabot::moveForward(float dist_cm) { if (dist_cm<0) moveBackward(-dist_cm); else { float angle_deg = dist_cm*wheel.degree_per_cm; setMotorsSpeed(bot_speed_cm_sec); moveMotorLeft(COUNTERCLOCKWISE, angle_deg); moveMotorRight(CLOCKWISE, angle_deg); } } // Mid level control function: move bot backwards for a given distance void Creabot::moveBackward(float dist_cm) { if(dist_cm<0) moveForward(-dist_cm); else { float angle_deg = dist_cm*wheel.degree_per_cm; setMotorsSpeed(bot_speed_cm_sec); moveMotorLeft(CLOCKWISE, angle_deg); moveMotorRight(COUNTERCLOCKWISE, angle_deg); } } /* Mid level control function: turn bot forward right, around a radius twice the bot size */ void Creabot::moveRight(float angle_deg) { moveRight(angle_deg,bot.diam_cm); } /* Mid level control function: turn bot forward right, around a radius that is center_cm away from the right wheel*/ void Creabot::moveRight(float angle_deg, float center_cm) { if(center_cm<0) center_cm=0; /* TO remove? */ float perimeter_outer = 2.0f*angle_deg*(center_cm+bot.diam_cm)*PI/360.0f; float perimeter_inner = 2.0f*angle_deg*(center_cm)*PI/360.0f; float angleLeft = perimeter_outer*wheel.degree_per_cm; float angleRight = perimeter_inner*wheel.degree_per_cm; float ratio = angleRight/angleLeft; float speedRight = bot_speed_cm_sec * ratio; setMotSpeed(motor_left,bot_speed_cm_sec); setMotSpeed(motor_right,speedRight); moveMotorLeft(COUNTERCLOCKWISE, angleLeft); moveMotorRight(CLOCKWISE, angleRight); } /* Mid level control function: turn bot forward left, around a radius twice the bot size */ void Creabot::moveLeft(float angle_deg) { moveLeft(angle_deg,0); } /* Mid level control function: turn bot forward left, around a radius that is center_cm away from the left wheel*/ void Creabot::moveLeft(float angle_deg, float center_cm) { if (center_cm<0) center_cm=0; /* TO remove? */ float perimeter_outer = 2.0f*angle_deg*(center_cm+bot.diam_cm)*PI/360.0f; float perimeter_inner = 2.0f*angle_deg*(center_cm)*PI/360.0f; float angleLeft = perimeter_inner*wheel.degree_per_cm; float angleRight = perimeter_outer*wheel.degree_per_cm; float ratio = angleLeft/angleRight; float speedRLeft = bot_speed_cm_sec * ratio; setMotSpeed(motor_left,speedRLeft); setMotSpeed(motor_right,bot_speed_cm_sec); moveMotorLeft(COUNTERCLOCKWISE, angleLeft); moveMotorRight(CLOCKWISE, angleRight); } /* Mid level control function: turn bot on its place for a given angle. positive angles turn right, negative angles turn left*/ void Creabot::rotate(float angleBot) { float angleWheel = angleBot*ratio_wheel_bot; setSpeed(bot_speed_cm_sec); if(angleBot<0) { moveMotorLeft(CLOCKWISE, -angleWheel); moveMotorRight(CLOCKWISE, -angleWheel); } else { moveMotorLeft(COUNTERCLOCKWISE, angleWheel); moveMotorRight(COUNTERCLOCKWISE, angleWheel); } } /* spends all time with waits, returns only once MotorState = LRMOTS_STOP */ void Creabot::waitEndMotors() { while(MotState!=LRMOTS_STOP) wait(0.1); } /* spends all time with waits, returns only once MotorState = LRMOTS_STOP, but maximum max_wait_ms milli seconds */ void Creabot::waitEndMotors(uint32_t max_wait_ms) { uint32_t waited=0; while( (MotState!=LRMOTS_STOP) && (waited < max_wait_ms) ) { wait(0.1); waited += 100; } } // waitEndMotors //****************************************************************************** // low level motor functions, only filters for angle_deg>0, then passes // to Motor Class; and remembers that a motor moves //****************************************************************************** /* Low level access functions: sets both motor speeds immediately */ void Creabot::setMotorsSpeed(float mot_speed_cm_sec) { setMotSpeed(motor_left,mot_speed_cm_sec); setMotSpeed(motor_right,mot_speed_cm_sec); } void Creabot::setMotorSpeed(Motor *motor, float speed_cm_sec) { if (speed_cm_sec < MIN_SPEED_CM_SEC) // catch too small or negative speeds motor->setStepTime_us( 1000000 ); // arbitrary value else { motor->setStepTime_us( wheel.perim_cm * 1000000 / speed_cm_sec / motor->getStepsFullTurn() ) ; } } void Creabot::moveMotorLeft(motorDir dir, float angle_deg) { if(angle_deg>0) { motor_left->RunDegrees(dir, angle_deg); if (MotState==RMOT_RUNS) MotState=LRMOTS_RUN; else MotState=LMOT_RUNS; } } void Creabot::moveMotorRight(motorDir dir, float angle_deg) { if(angle_deg>0) { motor_right->RunDegrees(dir, angle_deg); if (MotState==LMOT_RUNS) MotState=LRMOTS_RUN; else MotState=RMOT_RUNS; } } void Creabot::stopMotors() { motor_left->MotorOFF(); motor_right->MotorOFF(); AllMotorsStopped() } //****************************************************************************** // low level motor functions, handles callbacks from motors // ***************************************************************************** void Creabot::setCallBack(void (*Acallback)(int status)) { extCallBack = Acallback; } void Creabot::cbLeftMotStopped() { if (MotState==LRMOTS_RUN) MotState = RMOT_RUNS; else AllMotorsStopped(); } void Creabot::cbRightMotStopped() { if (MotState==LRMOTS_RUN) MotState = LMOT_RUNS; else AllMotorsStopped(); } void Creabot::AllMotorsStopped() { if (MotState!=LRMOTS_STOP) { // Only do all this here if motor state is not already in LRMOTS_STOP! MotState = LRMOTS_STOP; if(extCallBack!=NULL) extCallBack( MotState ); } }