amiro-os / devices / DiWheelDrive / userthread.cpp @ d607fcef
History | View | Annotate | Download (7.311 KB)
| 1 |
#include "userthread.hpp" |
|---|---|
| 2 |
|
| 3 |
#include "global.hpp" |
| 4 |
|
| 5 |
#include "linefollow2.hpp" |
| 6 |
|
| 7 |
using namespace amiro; |
| 8 |
|
| 9 |
extern Global global;
|
| 10 |
|
| 11 |
enum class states{ |
| 12 |
FOLLOW_LINE, |
| 13 |
OCCUPY, |
| 14 |
RELEASE, |
| 15 |
CHARGING |
| 16 |
}; |
| 17 |
|
| 18 |
enum msg_content{
|
| 19 |
STOP, |
| 20 |
START, |
| 21 |
EDGE_LEFT, |
| 22 |
EDGE_RIGHT, |
| 23 |
FUZZY, |
| 24 |
DOCKING |
| 25 |
}; |
| 26 |
|
| 27 |
// User thread state:
|
| 28 |
states utState = states::FOLLOW_LINE; |
| 29 |
|
| 30 |
// a buffer for the z-value of the accelerometer
|
| 31 |
int16_t accel_z; |
| 32 |
bool running = false; |
| 33 |
|
| 34 |
int vcnl4020AmbientLight[4] = {0}; |
| 35 |
int vcnl4020Proximity[4] = {0}; |
| 36 |
|
| 37 |
|
| 38 |
// Set the speed by the array
|
| 39 |
void setRpmSpeed(const int (&rpmSpeed)[2]) { |
| 40 |
global.motorcontrol.setTargetRPM(rpmSpeed[constants::DiWheelDrive::LEFT_WHEEL] * 1000000, rpmSpeed[constants::DiWheelDrive::RIGHT_WHEEL] * 1000000); |
| 41 |
} |
| 42 |
|
| 43 |
void lightOneLed(Color color, int idx){ |
| 44 |
global.robot.setLightColor(idx, Color(color)); |
| 45 |
} |
| 46 |
|
| 47 |
void lightAllLeds(Color color){
|
| 48 |
int led = 0; |
| 49 |
for(led=0; led<8; led++){ |
| 50 |
lightOneLed(color, led); |
| 51 |
} |
| 52 |
} |
| 53 |
|
| 54 |
/**
|
| 55 |
* Get the wanted strategy from the global object.
|
| 56 |
*/
|
| 57 |
LineFollowStrategy determineStrategy(){
|
| 58 |
switch(global.lfStrategy){
|
| 59 |
case 0: |
| 60 |
return LineFollowStrategy::EDGE_RIGHT;
|
| 61 |
break;
|
| 62 |
case 1: |
| 63 |
return LineFollowStrategy::EDGE_LEFT;
|
| 64 |
break;
|
| 65 |
case 2: |
| 66 |
return LineFollowStrategy::FUZZY;
|
| 67 |
break;
|
| 68 |
case 3: |
| 69 |
return LineFollowStrategy::DOCKING;
|
| 70 |
default:
|
| 71 |
break;
|
| 72 |
} |
| 73 |
return LineFollowStrategy::NONE;
|
| 74 |
} |
| 75 |
|
| 76 |
/**
|
| 77 |
* Blocks as long as the position changes.
|
| 78 |
*/
|
| 79 |
void checkForMotion(UserThread *ut){
|
| 80 |
int motion = 1; |
| 81 |
int led = 0; |
| 82 |
types::position oldPos = global.odometry.getPosition(); |
| 83 |
while(motion){
|
| 84 |
ut->sleep(500);
|
| 85 |
types::position tmp = global.odometry.getPosition(); |
| 86 |
motion = abs(oldPos.x - tmp.x)+ abs(oldPos.y - tmp.y)+abs(oldPos.z - tmp.z); |
| 87 |
oldPos = tmp; |
| 88 |
global.robot.setLightColor((led + 1) % 8, Color(Color::YELLOW)); |
| 89 |
global.robot.setLightColor(led % 8, Color(Color::BLACK));
|
| 90 |
led++; |
| 91 |
} |
| 92 |
} |
| 93 |
|
| 94 |
|
| 95 |
/**
|
| 96 |
* Turns MotorControl off and checks if position remains stable.
|
| 97 |
*/
|
| 98 |
int checkDockingSuccess(UserThread *ut){
|
| 99 |
// global.motorcontrol.setTargetRPM(0,0);
|
| 100 |
checkForMotion(ut); |
| 101 |
int led = 0; |
| 102 |
int success = 0; |
| 103 |
global.odometry.resetPosition(); |
| 104 |
types::position start = global.startPos = global.odometry.getPosition(); |
| 105 |
global.motorcontrol.toggleMotorEnable(); |
| 106 |
ut->sleep(1000);
|
| 107 |
types::position stop = global.endPos = global.odometry.getPosition(); |
| 108 |
global.motorcontrol.toggleMotorEnable(); |
| 109 |
// Amiro moved, docking was not successful
|
| 110 |
if ((start.x + stop.x) || (start.y + stop.y)){
|
| 111 |
for(led=0; led<8; led++){ |
| 112 |
global.robot.setLightColor(led, Color(Color::RED)); |
| 113 |
} |
| 114 |
success = 0;
|
| 115 |
}else{
|
| 116 |
for(led=0; led<8; led++){ |
| 117 |
global.robot.setLightColor(led, Color(Color::GREEN)); |
| 118 |
} |
| 119 |
success = 1;
|
| 120 |
} |
| 121 |
|
| 122 |
ut->sleep(500);
|
| 123 |
for(led=0; led<8; led++){ |
| 124 |
global.robot.setLightColor(led, Color(Color::BLACK)); |
| 125 |
} |
| 126 |
return success;
|
| 127 |
} |
| 128 |
|
| 129 |
void correctPosition(UserThread *ut, LineFollow &lf, int steps){ |
| 130 |
int checkWhite = 0; |
| 131 |
int rpmSpeed[2] ={0}; |
| 132 |
lf.setStrategy(LineFollowStrategy::EDGE_LEFT); |
| 133 |
for (int correction=0; correction<steps; correction++){ |
| 134 |
checkWhite = lf.followLine(rpmSpeed); |
| 135 |
setRpmSpeed(rpmSpeed); |
| 136 |
ut->sleep(CAN::UPDATE_PERIOD); |
| 137 |
} |
| 138 |
} |
| 139 |
|
| 140 |
|
| 141 |
UserThread::UserThread() : |
| 142 |
chibios_rt::BaseStaticThread<USER_THREAD_STACK_SIZE>() |
| 143 |
{
|
| 144 |
} |
| 145 |
|
| 146 |
UserThread::~UserThread() |
| 147 |
{
|
| 148 |
} |
| 149 |
|
| 150 |
msg_t |
| 151 |
UserThread::main() |
| 152 |
{
|
| 153 |
/*
|
| 154 |
* SETUP
|
| 155 |
*/
|
| 156 |
int rpmSpeed[2] = {0}; |
| 157 |
int stop[2] = {0}; |
| 158 |
int proxyWheelThresh = 18000; |
| 159 |
LineFollowStrategy lStrategy; |
| 160 |
for (uint8_t led = 0; led < 8; ++led) { |
| 161 |
global.robot.setLightColor(led, Color(Color::BLACK)); |
| 162 |
} |
| 163 |
running = false;
|
| 164 |
LineFollow lf(&global); |
| 165 |
/*
|
| 166 |
* LOOP
|
| 167 |
*/
|
| 168 |
while (!this->shouldTerminate()) |
| 169 |
{
|
| 170 |
/*
|
| 171 |
* read accelerometer z-value
|
| 172 |
*/
|
| 173 |
accel_z = global.lis331dlh.getAccelerationForce(LIS331DLH::AXIS_Z); |
| 174 |
|
| 175 |
/*
|
| 176 |
* evaluate the accelerometer
|
| 177 |
*/
|
| 178 |
|
| 179 |
//Features over can: (Line Following)
|
| 180 |
//SetKP
|
| 181 |
//SetKI
|
| 182 |
//SetKd ?
|
| 183 |
//SetSleepTime
|
| 184 |
//SeForwardSpeed? or SetMaxSpeed
|
| 185 |
//DriveOnLeftLine
|
| 186 |
//DriveOnRightLine
|
| 187 |
|
| 188 |
//if accel_z<-900
|
| 189 |
//send can event (one time)
|
| 190 |
// Line following is started if amiro roteted
|
| 191 |
if (accel_z < -900 /*-0.9g*/) { //new: (can.allowLineFollowOnTurn && accel_z < 900) || can.startLineFollow optional feature |
| 192 |
// set the front LEDs to blue for one second
|
| 193 |
lightAllLeds(Color::GREEN); |
| 194 |
this->sleep(1000); |
| 195 |
lightAllLeds(Color::BLACK); |
| 196 |
running = !running; |
| 197 |
// If message was received handle it here:
|
| 198 |
} else if(global.msgReceived){ |
| 199 |
|
| 200 |
global.msgReceived = false;
|
| 201 |
running = true;
|
| 202 |
switch(global.lfStrategy){
|
| 203 |
case msg_content::START:
|
| 204 |
break;
|
| 205 |
case msg_content::STOP:
|
| 206 |
running = false;
|
| 207 |
break;
|
| 208 |
case msg_content::EDGE_RIGHT:
|
| 209 |
lStrategy = LineFollowStrategy::EDGE_RIGHT; |
| 210 |
break;
|
| 211 |
case msg_content::EDGE_LEFT:
|
| 212 |
lStrategy = LineFollowStrategy::EDGE_LEFT; |
| 213 |
break;
|
| 214 |
case msg_content::FUZZY:
|
| 215 |
lStrategy = LineFollowStrategy::FUZZY; |
| 216 |
break;
|
| 217 |
case msg_content::DOCKING:
|
| 218 |
utState = states::OCCUPY; |
| 219 |
lStrategy = LineFollowStrategy::EDGE_RIGHT; |
| 220 |
break;
|
| 221 |
default:
|
| 222 |
break;
|
| 223 |
} |
| 224 |
|
| 225 |
} |
| 226 |
|
| 227 |
if(running){
|
| 228 |
switch(utState){
|
| 229 |
case states::FOLLOW_LINE:{
|
| 230 |
// LineFollowStrategy lStrategy = determineStrategy();
|
| 231 |
if(lStrategy == LineFollowStrategy::DOCKING){
|
| 232 |
utState = states::OCCUPY; |
| 233 |
break;
|
| 234 |
} |
| 235 |
lf.setStrategy(lStrategy); |
| 236 |
lf.followLine(rpmSpeed); |
| 237 |
setRpmSpeed(rpmSpeed); |
| 238 |
break;
|
| 239 |
} |
| 240 |
case states::OCCUPY:{
|
| 241 |
// Get Wheel proxy sensors
|
| 242 |
int WL = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
|
| 243 |
int WR = global.vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
|
| 244 |
// Check for black
|
| 245 |
if ((WL+WR) < proxyWheelThresh){ /*TODO: Only check for one sensor */ |
| 246 |
global.motorcontrol.setTargetRPM(0,0); |
| 247 |
|
| 248 |
// Stop when in docking state and take further actions
|
| 249 |
if(lf.getStrategy() == LineFollowStrategy::DOCKING){
|
| 250 |
if(checkDockingSuccess(this)){ |
| 251 |
utState = states::CHARGING; |
| 252 |
break;
|
| 253 |
}else{
|
| 254 |
correctPosition(this, lf, 250); |
| 255 |
lf.setStrategy(LineFollowStrategy::DOCKING); |
| 256 |
// break;
|
| 257 |
} |
| 258 |
}else{
|
| 259 |
checkForMotion(this);
|
| 260 |
// 180° Rotation
|
| 261 |
global.distcontrol.setTargetPosition(0, 3141592, 10000); |
| 262 |
// BaseThread::sleep(8000);
|
| 263 |
checkForMotion(this);
|
| 264 |
correctPosition(this, lf, 250); |
| 265 |
// break;
|
| 266 |
lf.setStrategy(LineFollowStrategy::DOCKING); |
| 267 |
|
| 268 |
} |
| 269 |
} |
| 270 |
|
| 271 |
// Set correct following
|
| 272 |
// lf.setStrategy(LineFollowStrategy::EDGE_RIGHT);
|
| 273 |
lf.followLine(rpmSpeed); |
| 274 |
setRpmSpeed(rpmSpeed); |
| 275 |
|
| 276 |
break;
|
| 277 |
} |
| 278 |
case states::RELEASE:{
|
| 279 |
break;
|
| 280 |
} |
| 281 |
case states::CHARGING:{
|
| 282 |
setRpmSpeed(stop); |
| 283 |
break;
|
| 284 |
} |
| 285 |
default:{
|
| 286 |
break;
|
| 287 |
} |
| 288 |
} |
| 289 |
|
| 290 |
}else{
|
| 291 |
// Stop
|
| 292 |
setRpmSpeed(stop); |
| 293 |
} |
| 294 |
|
| 295 |
this->sleep(CAN::UPDATE_PERIOD);
|
| 296 |
} |
| 297 |
|
| 298 |
return RDY_OK;
|
| 299 |
} |