From a1c2581267a6f6c81dbbdc257085d0e4de029604 Mon Sep 17 00:00:00 2001 From: galberding <galberding@techfak.uni-bielefeld.de> Date: Mon, 31 Aug 2020 14:50:18 +0200 Subject: [PATCH] Use sensorvalues for turning --- devices/DiWheelDrive/DiWheelDrive.cpp | 2 +- devices/DiWheelDrive/global.hpp | 8 +- devices/DiWheelDrive/linefollow.cpp | 31 +++--- devices/DiWheelDrive/linefollow.hpp | 22 +++-- devices/DiWheelDrive/main.cpp | 54 ++++++++++- devices/DiWheelDrive/userthread.cpp | 135 ++++++++++++++++++-------- devices/DiWheelDrive/userthread.hpp | 2 +- include/amiro/Constants.h | 1 + 8 files changed, 184 insertions(+), 71 deletions(-) diff --git a/devices/DiWheelDrive/DiWheelDrive.cpp b/devices/DiWheelDrive/DiWheelDrive.cpp index f5744c6b..3f257a80 100644 --- a/devices/DiWheelDrive/DiWheelDrive.cpp +++ b/devices/DiWheelDrive/DiWheelDrive.cpp @@ -115,7 +115,7 @@ msg_t DiWheelDrive::receiveMessage(CANRxFrame *frame) { case CAN::SET_LINE_FOLLOW_MSG: // chprintf((BaseSequentialStream*) &SD1, "Received Strategy!\n"); if (frame->DLC == 1) { - global.lfStrategy = frame->data8[0]; + global.msgContent = frame->data8[0]; global.msgReceived = true; // return RDY_OK; } diff --git a/devices/DiWheelDrive/global.hpp b/devices/DiWheelDrive/global.hpp index a7919b60..c0b07d9a 100644 --- a/devices/DiWheelDrive/global.hpp +++ b/devices/DiWheelDrive/global.hpp @@ -165,7 +165,7 @@ public: DiWheelDrive robot; UserThread userThread; - int rpmForward[2] = {30,30}; + int rpmForward[2] = {20,20}; int rpmSoftLeft[2] = {10,20}; int rpmHardLeft[2] = {5,20}; int rpmSoftRight[2] = {rpmSoftLeft[1],rpmSoftLeft[0]}; @@ -212,7 +212,7 @@ public: // 1 EDGE_LEFT // 2 FUZZY // 3 DOCKING - int lfStrategy = 3; + int msgContent = 3; // CAN communication line: // Will be set to true when message was received @@ -223,7 +223,9 @@ public: // uint8_t actualCharge = 0; // Debugging stuff -------------- - int forwardSpeed = 5; + + //TODO: Structure the variables + int forwardSpeed = 5; // declares the forwardspeed int enableRecord = 0; bool triggerCan = false; diff --git a/devices/DiWheelDrive/linefollow.cpp b/devices/DiWheelDrive/linefollow.cpp index 2d2a4ffb..d9c58de5 100644 --- a/devices/DiWheelDrive/linefollow.cpp +++ b/devices/DiWheelDrive/linefollow.cpp @@ -57,11 +57,11 @@ int LineFollow::getError(){ // Get actual sensor data of both front sensors int FL = global->vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset(); int FR = global->vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset(); - // int targetL = global->linePID.threshProxyL; - // int targetR = global->linePID.threshProxyR; + int targetL = global->linePID.BThresh; int targetR = global->linePID.WThresh; int error = 0; + // Calculate the error according to the current strategy switch (this->strategy) { case LineFollowStrategy::EDGE_RIGHT: @@ -82,14 +82,7 @@ int LineFollow::getError(){ default: break; } - // Debugging stuff ------ - // if (global->enableRecord){ - // global->senseRec[global->sensSamples].error = error; - // global->senseRec[global->sensSamples].FL = global->vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset(); - // global->senseRec[global->sensSamples].FR = global->vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset(); - // global->sensSamples++; - // } - // ---------------------- + // Register white values if (FL+FR > global->threshWhite){ whiteFlag = 1; @@ -122,10 +115,11 @@ int LineFollow::followLine(int (&rpmSpeed)[2]){ break; case LineFollowStrategy::REVERSE: + // Perform straight correctionSpeed = -getPidCorrectionSpeed(); - rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] = -1000000*global->forwardSpeed; + rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] = -SPEED_M_TO_U*global->forwardSpeed; - rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] = -1000000*global->forwardSpeed; + rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] = -SPEED_M_TO_U*global->forwardSpeed; break; @@ -133,9 +127,9 @@ int LineFollow::followLine(int (&rpmSpeed)[2]){ correctionSpeed = getPidCorrectionSpeed(); // chprintf((BaseSequentialStream*) &SD1, "Correction: %d, thresh: %d\n",correctionSpeed, global->threshWhite); - rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] = 1000000*global->forwardSpeed + correctionSpeed; + rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] = SPEED_M_TO_U*global->forwardSpeed + correctionSpeed; - rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] = 1000000*global->forwardSpeed - correctionSpeed; + rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] = SPEED_M_TO_U*global->forwardSpeed - correctionSpeed; break; } @@ -156,8 +150,10 @@ int LineFollow::followLine(int (&rpmSpeed)[2]){ int LineFollow::getPidCorrectionSpeed(){ int32_t error = getError(); int32_t sloap = oldError - error ; - // int correctionSpeed = (int) (global->K_p*error + Ki*accumHist - global->K_d*sloap); + + // Calculate the correction speed for the current step int32_t correctionSpeed = (int32_t) (K_p*error + K_i*accumHist + K_d*sloap); + //Update the old error value oldError = error; // Overflow Protection @@ -171,9 +167,14 @@ int LineFollow::getPidCorrectionSpeed(){ }else { accumHist += error; } + + // ---------------------------------------------------------------------------------------------------- + // Debugging: Track the biggest occurring error value + if (abs(error) > global->maxDist.error){ global->maxDist.error = error; } + // ---------------------------------------------------------------------------------------------------- return correctionSpeed; } diff --git a/devices/DiWheelDrive/linefollow.hpp b/devices/DiWheelDrive/linefollow.hpp index 01aa8c90..98a850f9 100644 --- a/devices/DiWheelDrive/linefollow.hpp +++ b/devices/DiWheelDrive/linefollow.hpp @@ -6,10 +6,12 @@ #include <amiroosconf.h> #define RAND_TRESH 16000 -#define MAX_CORRECTED_SPEED 1000000*100 +// Multiplication factor to convert m/s to um/s +#define SPEED_M_TO_U 1000000 +#define MAX_CORRECTED_SPEED SPEED_M_TO_U*100 namespace amiro { - + enum LineFollowStrategy{ EDGE_LEFT, // driving on the left edge of a black line TRANSITION_L_R, // Transition from left to right edge @@ -37,19 +39,19 @@ public: LineFollow(Global *global, LineFollowStrategy strategy); /** * Entry method which should be called to follow a line. - * + * * @param rpmSpeed speed that will be determained - * @return white flag, 1 if white is detected + * @return white flag, 1 if white is detected */ int followLine(int (&rpmSpeed)[2]); /** * Setter for LineFollowStrategy which triggers transition behavior. - * + * * To prevent random turns while changeing the strategy a transition state is set. * In case the strategy needs to be switched immediately use promptStrategyChange(). - * - * @param strategy + * + * @param strategy */ void setStrategy(LineFollowStrategy strategy); void promptStrategyChange(LineFollowStrategy strategy); @@ -87,17 +89,17 @@ private: /** * Error calculation while changing from one EDGE_* strategy to another. * This prevents the AMiRo from random turns while switching strategies. - * + * * @param FL value of left front sensor * @param FR value of right front sensor - * @param targetL left threshold + * @param targetL left threshold * @param targetR right threshold */ int transitionError(int FL, int FR, int targetL, int targetR); /** * Use the error according to the strategy to calculate the correction speed. - * Currently only the P part of the PID controller is used to calculate the + * Currently only the P part of the PID controller is used to calculate the * correction speed. */ int getPidCorrectionSpeed(); diff --git a/devices/DiWheelDrive/main.cpp b/devices/DiWheelDrive/main.cpp index 408a01b0..0889caa7 100644 --- a/devices/DiWheelDrive/main.cpp +++ b/devices/DiWheelDrive/main.cpp @@ -910,6 +910,7 @@ void shellRequestPrintCoordinate(BaseSequentialStream *chp, int argc, char *argv } + void shellRequestErrorInfo(BaseSequentialStream *chp, int argc, char *argv[]){ // Print out the error info collected. Clear buffer after calling chprintf(chp, "Error Info\n"); @@ -988,10 +989,57 @@ void shellRequestMapTest(BaseSequentialStream *chp, int argc, char *argv[]) { chprintf(chp, " +------> 1 | |\n"); chprintf(chp, " +---+-------------------+\n"); // BaseThread::sleep(MS2ST(250)); - global.lfStrategy = msg_content::MSG_TEST_MAP_STATE; + global.msgContent = msg_content::MSG_TEST_MAP_STATE; + global.msgReceived = true; + + } + +// Calibrate the Black bottom sensor value +void shellRequestCalibBlack(BaseSequentialStream *chp, int argc, char *argv[]) { + global.msgContent = msg_content::MSG_CALIBRATE_BLACK; + global.msgReceived = true; + } + +// Calibrate white value +void shellRequestCalibWhite(BaseSequentialStream *chp, int argc, char *argv[]) { + global.msgContent = msg_content::MSG_CALIBRATE_WHITE; + global.msgReceived = true; + } + + +// Calibrate white value +void shellRequestDock(BaseSequentialStream *chp, int argc, char *argv[]) { + // Set Amiro in docking mode + global.msgContent = msg_content::MSG_DOCK; global.msgReceived = true; + } + + +void sellRequestSpeedStage(BaseSequentialStream *chp, int argc, char *argv[]) { + int level; + if (argc == 1){ + chprintf(chp, "Speed Level %i \n", atoi(argv[0])); + level = atoi(argv[0]); + + } else { + chprintf(chp, "Usage: setSpeedLevel <1|2|3> \n"); } + switch(level){ + case 1: + global.forwardSpeed = -10; + break; + case 2: + global.forwardSpeed = 15; + break; + case 3: + global.forwardSpeed = 20; + break; + default: + chprintf(chp, "Usage: setSpeedLevel <1|2|3> \n"); + break; + } +} static const ShellCommand commands[] = { {"shutdown", shellRequestShutdown}, @@ -1028,6 +1076,10 @@ static const ShellCommand commands[] = { {"checkPowerPins", shellRequestCheckPower}, {"stateInfos", shellRequestErrorInfo}, {"test", shellRequestMapTest}, + {"bottomCalibrateBlack", shellRequestCalibBlack}, + {"bottomCalibrateWhite", shellRequestCalibWhite}, + {"setSpeedLevel", sellRequestSpeedStage}, + {"dock", shellRequestDock }, {NULL, NULL}}; static const ShellConfig shell_cfg1 = { diff --git a/devices/DiWheelDrive/userthread.cpp b/devices/DiWheelDrive/userthread.cpp index 68e8737c..28e830bf 100644 --- a/devices/DiWheelDrive/userthread.cpp +++ b/devices/DiWheelDrive/userthread.cpp @@ -209,7 +209,7 @@ int UserThread::checkDockingSuccess(){ // Amiro moved, docking was not successful // if ((start.x + stop_.x) || (start.y + stop_.y)){ - if (abs(start.x - stop_.x) > 200 /* || (start.y + stop_.y) */){ + if (abs(start.x - stop_.x) > 300 /* || (start.y + stop_.y) */){ lightAllLeds(Color::RED); // Enable Motor again if docking was not successful global.motorcontrol.setMotorEnable(true); @@ -220,7 +220,7 @@ int UserThread::checkDockingSuccess(){ } // this->sleep(500); - lightAllLeds(Color::BLACK); + // lightAllLeds(Color::BLACK); return success; } @@ -309,7 +309,7 @@ UserThread::main() } else if(global.msgReceived){ global.msgReceived = false; // running = true; - switch(global.lfStrategy){ + switch(global.msgContent){ case msg_content::MSG_START: newState = ut_states::UT_CALIBRATION_CHECK; break; @@ -372,6 +372,9 @@ UserThread::main() // Get sensor data uint16_t WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset(); uint16_t WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_RIGHT].getProximityScaledWoOffset(); + uint16_t FL = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset(); + uint16_t FR = global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset(); + for(int i=0; i<8;i++){ rProx[i] = global.robot.getProximityRingValue(i); } @@ -399,11 +402,15 @@ UserThread::main() This values will be used by the line follow object */ + proxCalib.buf = 0; + // Only calibrate the sensors if robot is on black surface if(proxCalib.calibrateBlack){ chprintf((BaseSequentialStream*)&global.sercanmux1, "Black Calibration, Place AMiRo on black Surface!\n"); global.robot.calibrate(); } + + // Get mean sensor value for pid regulation for(int i=0; i <= proxCalib.meanWindow; i++){ proxCalib.buf += global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_LEFT].getProximityScaledWoOffset() + global.vcnl4020[constants::DiWheelDrive::PROX_FRONT_RIGHT].getProximityScaledWoOffset(); @@ -411,6 +418,7 @@ UserThread::main() } proxCalib.buf = proxCalib.buf / (2*proxCalib.meanWindow); + // Store mean value if(proxCalib.calibrateBlack){ global.linePID.BThresh = proxCalib.buf; }else { @@ -516,38 +524,71 @@ UserThread::main() } // --------------------------------------- case ut_states::UT_DETECT_STATION: + // Set Amiro in detection state. It is expected that a docking station is + // positioned on the right edge. - if (global.forwardSpeed != DETECTION_SPEED){ - global.forwardSpeed = DETECTION_SPEED; - } - if(lf.getStrategy() != LineFollowStrategy::EDGE_RIGHT){ + // Lower the speed for more accuracy when reaching the station + if (global.forwardSpeed != DETECTION_SPEED){ + global.forwardSpeed = DETECTION_SPEED; + } + + // Switch to the right edge + if(lf.getStrategy() != LineFollowStrategy::EDGE_RIGHT){ lf.setStrategy(LineFollowStrategy::EDGE_RIGHT); } - lf.followLine(rpmSpeed); - setRpmSpeed(rpmSpeed); - // // Detect marker before docking station - // if ((WL+WR) < PROXY_WHEEL_THRESH){ - // Use proxy ring - if ((rProx[3]+rProx[4]) > RING_PROX_FRONT_THRESH){ - - setRpmSpeed(stop); - checkForMotion(); - // 180° Rotation - global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION); - // BaseThread::sleep(8000); - checkForMotion(); - newState = ut_states::UT_CORRECT_POSITIONING; + // Continue line following until station is not reached + lf.followLine(rpmSpeed); + setRpmSpeed(rpmSpeed); + // // Detect marker before docking station + // if ((WL+WR) < PROXY_WHEEL_THRESH){ + // Use proxy ring + + // Front sensors detect the station + // If thresh reached start with the docking procedure + if ((rProx[3]+rProx[4]) > RING_PROX_FRONT_THRESH){ + + setRpmSpeed(stop); + checkForMotion(); + // 180° Rotation + // global.distcontrol.setTargetPosition(0, ROTATION_180, ROTATION_DURATION); + // BaseThread::sleep(8000); + // checkForMotion(); + newState = ut_states::UT_STATION_POSITIONING_TURN; } break; // --------------------------------------- + + case ut_states::UT_STATION_POSITIONING_TURN:{ + // TODO: Manually rotate 180° + + rpmSpeed[0] = SPEED_CONVERSION_FACTOR * CHARGING_SPEED; + rpmSpeed[1] = -SPEED_CONVERSION_FACTOR * CHARGING_SPEED; + setRpmSpeed(rpmSpeed); + + if (FR <= (FL / 2)){ + setRpmSpeed(stop); + checkForMotion(); + newState = ut_states::UT_CORRECT_POSITIONING; + } + + break; + } + // --------------------------------------- case ut_states::UT_CORRECT_POSITIONING: + + // Ensure slow speed + // TODO: May be obsolete if (global.forwardSpeed != CHARGING_SPEED){ global.forwardSpeed = CHARGING_SPEED; } + // Ensure that the strategy is set to Left edge + // This is due to the 180° turn in the previous state if(lf.getStrategy() != LineFollowStrategy::EDGE_LEFT){ lf.promptStrategyChange(LineFollowStrategy::EDGE_LEFT); } + + // Follow line position the amiro straight in front of the charging station lf.followLine(rpmSpeed); setRpmSpeed(rpmSpeed); @@ -566,7 +607,7 @@ UserThread::main() } lf.followLine(rpmSpeed); setRpmSpeed(rpmSpeed); - // utCount.stateTime++; + utCount.stateTime++; // Docking is only successful if Deviation is in range and sensors are at their max values. if((rProx[0] >= PROX_MAX_VAL) @@ -696,12 +737,12 @@ UserThread::main() global.motorcontrol.setMotorEnable(true); global.robot.requestCharging(0); // TODO: Soft release when docking falsely - if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL)){ - newState = ut_states::UT_RELEASE_TO_CORRECT; - } else { - newState = ut_states::UT_RELEASE_TO_CORRECT; //ut_states::UT_CORRECT_POSITIONING; - } - + // if((rProx[0] >= PROX_MAX_VAL) && (rProx[7] >= PROX_MAX_VAL)){ + // newState = ut_states::UT_RELEASE_TO_CORRECT; + // } else { + // newState = ut_states::UT_RELEASE_TO_CORRECT; //ut_states::UT_CORRECT_POSITIONING; + // } + newState = ut_states::UT_RELEASE_TO_CORRECT; if (utCount.errorCount > DOCKING_ERROR_THRESH){ newState = ut_states::UT_DOCKING_ERROR; } @@ -711,18 +752,32 @@ UserThread::main() // --------------------------------------- case ut_states::UT_RELEASE_TO_CORRECT: - global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION); - checkForMotion(); - // move 1cm forward - global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION); - checkForMotion(); - // rotate back - global.distcontrol.setTargetPosition(0, -2*ROTATION_20, ROTATION_DURATION); - checkForMotion(); - - global.distcontrol.setTargetPosition(1500, 0, ROTATION_DURATION); - checkForMotion(); - newState = ut_states::UT_CORRECT_POSITIONING; + // global.distcontrol.setTargetPosition(0, ROTATION_20, ROTATION_DURATION); + // checkForMotion(); + // // move 1cm forward + // global.distcontrol.setTargetPosition(5000, 0, ROTATION_DURATION); + // checkForMotion(); + // // rotate back + // global.distcontrol.setTargetPosition(0, -2*ROTATION_20, ROTATION_DURATION); + // checkForMotion(); + + // global.distcontrol.setTargetPosition(1500, 0, ROTATION_DURATION); + + + utCount.stateCount++; + if(utCount.stateCount < 150){ + rpmSpeed[0] = -SPEED_CONVERSION_FACTOR * CHARGING_SPEED; + rpmSpeed[1] = SPEED_CONVERSION_FACTOR * CHARGING_SPEED; + setRpmSpeed(rpmSpeed); + }else if(utCount.stateCount < 180){ + rpmSpeed[0] = SPEED_CONVERSION_FACTOR * CHARGING_SPEED; + rpmSpeed[1] = SPEED_CONVERSION_FACTOR * CHARGING_SPEED; + setRpmSpeed(rpmSpeed); + }else{ + newState = ut_states::UT_STATION_POSITIONING_TURN ; + utCount.stateCount = 0; + } + // checkForMotion(); break; // --------------------------------------- case ut_states::UT_CHARGING: diff --git a/devices/DiWheelDrive/userthread.hpp b/devices/DiWheelDrive/userthread.hpp index 392ce843..a15e9f7e 100644 --- a/devices/DiWheelDrive/userthread.hpp +++ b/devices/DiWheelDrive/userthread.hpp @@ -52,7 +52,7 @@ #define CAN_TRANSMIT_STATE_THRESH 50 #define PROX_DEVIATION_MEAN_WINDOW 3 #define MAX_DEVIATION_CORRECTIONS 4 -#define MAX_DEVIATION_FACTOR 35 +#define MAX_DEVIATION_FACTOR 45 #define DEVIATION_CORRECTION_DURATION 900 #define DEVIATION_CORRECTION_SPEED 2000000 #define DEVIATION_CORRECTION_VALUE (DEVIATION_CORRECTION_SPEED / 2) diff --git a/include/amiro/Constants.h b/include/amiro/Constants.h index 6efd6536..84e4c477 100644 --- a/include/amiro/Constants.h +++ b/include/amiro/Constants.h @@ -86,6 +86,7 @@ enum ut_states : int8_t { UT_DEVIATION_CORRECTION = 16, UT_TEST_MAP_STATE = 17, UT_TEST_MAP_AUTO_STATE = 18, + UT_STATION_POSITIONING_TURN = 19, UT_DOCKING_ERROR = -1, UT_REVERSE_TIMEOUT_ERROR = -2, UT_CALIBRATION_ERROR = -3, -- GitLab