Skip to content

Commit 03ca026

Browse files
authored
Merge pull request #119 from BCLab-UNM/bug-rover_lockedup_state
Fix for stuck in place rovers
2 parents 6fd1af2 + 8c77ba0 commit 03ca026

File tree

3 files changed

+185
-67
lines changed

3 files changed

+185
-67
lines changed

src/behaviours/src/DriveController.cpp

Lines changed: 128 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,122 +16,202 @@ DriveController::DriveController() {
1616

1717
DriveController::~DriveController() {}
1818

19-
void DriveController::Reset() {
19+
void DriveController::Reset()
20+
{
2021
waypoints.clear();
21-
if (stateMachineState == STATE_MACHINE_ROTATE || stateMachineState == STATE_MACHINE_SKID_STEER) {
22+
23+
if (stateMachineState == STATE_MACHINE_ROTATE || stateMachineState == STATE_MACHINE_SKID_STEER)
24+
{
2225
stateMachineState = STATE_MACHINE_WAYPOINTS;
2326
}
2427
}
2528

26-
Result DriveController::DoWork() {
29+
Result DriveController::DoWork()
30+
{
2731

28-
if(result.type == behavior) {
29-
if(result.b == noChange) {
32+
if(result.type == behavior)
33+
{
34+
if(result.b == noChange)
35+
{
3036
//if drive controller gets a no change command it is allowed to continue its previouse action
3137
//normally this will be to follow waypoints but it is not specified as such.
32-
} else if(result.b == wait) {
38+
}
39+
40+
else if(result.b == wait)
41+
{
3342
//do nothing till told otherwise
3443
left = 0.0;
3544
right = 0.0;
3645
stateMachineState = STATE_MACHINE_WAITING;
37-
3846
}
39-
} else if(result.type == precisionDriving) {
47+
48+
}
49+
50+
else if(result.type == precisionDriving)
51+
{
4052

4153
//interpret input result as a precision driving command
4254
stateMachineState = STATE_MACHINE_PRECISION_DRIVING;
4355

44-
} else if(result.type == waypoint) {
56+
}
57+
58+
else if(result.type == waypoint)
59+
{
4560
//interpret input result as new waypoints to add into the queue
4661
ProcessData();
4762

4863
}
4964

50-
switch(stateMachineState) {
51-
65+
switch(stateMachineState)
66+
{
5267

5368
//Handlers and the final state of STATE_MACHINE are the only parts allowed to call INTERUPT
5469
//This should be d one as little as possible. I Suggest to Use timeouts to set control bools false.
5570
//Then only call INTERUPT if bool switches to true.
56-
case STATE_MACHINE_PRECISION_DRIVING: {
71+
case STATE_MACHINE_PRECISION_DRIVING:
72+
{
5773

5874
ProcessData();
5975
break;
6076
}
6177

78+
79+
case STATE_MACHINE_WAYPOINTS:
80+
{
81+
6282
//Handles route planning and navigation as well as makeing sure all waypoints are valid.
63-
case STATE_MACHINE_WAYPOINTS: {
6483

6584
bool tooClose = true;
66-
while (!waypoints.empty() && tooClose) {
67-
if (hypot(waypoints.back().x-currentLocation.x, waypoints.back().y-currentLocation.y) < waypointTolerance) {
85+
while (!waypoints.empty() && tooClose)
86+
{
87+
if (hypot(waypoints.back().x-currentLocation.x, waypoints.back().y-currentLocation.y) < waypointTolerance)
88+
{
6889
waypoints.pop_back();
6990
}
70-
else {
91+
else
92+
{
7193
tooClose = false;
7294
}
7395
}
74-
if (waypoints.empty()) {
96+
if (waypoints.empty())
97+
{
7598
stateMachineState = STATE_MACHINE_WAITING;
7699
result.type = behavior;
77100
interupt = true;
78101
return result;
79102
}
80-
else {
103+
else
104+
{
81105
stateMachineState = STATE_MACHINE_ROTATE;
82106
//fall through on purpose
83107
}
108+
}
84109

110+
case STATE_MACHINE_ROTATE:
111+
{
85112

86-
}
87113
// Calculate angle between currentLocation.theta and waypoints.front().theta
88114
// Rotate left or right depending on sign of angle
89115
// Stay in this state until angle is minimized
90-
case STATE_MACHINE_ROTATE: {
91116

92117
waypoints.back().theta = atan2(waypoints.back().y - currentLocation.y, waypoints.back().x - currentLocation.x);
118+
93119
// Calculate the diffrence between current and desired heading in radians.
94120
float errorYaw = angles::shortest_angular_distance(currentLocation.theta, waypoints.back().theta);
95121

122+
cout << "ROTATING, ERROR: " << errorYaw << endl;
123+
96124
result.pd.setPointVel = 0.0;
97125
result.pd.setPointYaw = waypoints.back().theta;
126+
127+
//Calculate absolute value of angle
128+
129+
float abs_error = fabs(angles::shortest_angular_distance(currentLocation.theta, waypoints.back().theta));
130+
98131
// If angle > rotateOnlyAngleTolerance radians rotate but dont drive forward.
99-
if (fabs(angles::shortest_angular_distance(currentLocation.theta, waypoints.back().theta)) > rotateOnlyAngleTolerance) {
132+
if (abs_error > rotateOnlyAngleTolerance)
133+
{
100134
// rotate but dont drive.
101-
if (result.PIDMode == FAST_PID) {
102-
fastPID(0.0,errorYaw, result.pd.setPointVel, result.pd.setPointYaw);
135+
if (result.PIDMode == FAST_PID)
136+
{
137+
fastPID(0.0, errorYaw, result.pd.setPointVel, result.pd.setPointYaw);
138+
139+
std::cout << "LEFT: " << this->left << ", RIGHT: " << this->right << std::endl;
140+
141+
const int MIN_TURN_VALUE = 80;
142+
143+
//If wheels get a value less than 80, will cause robot to sit in place
144+
if(fabs(left) < MIN_TURN_VALUE && fabs(right) < MIN_TURN_VALUE)
145+
{
146+
147+
std::cout << "ERROR my speed was too slow, increasing" << std::endl;
148+
149+
//increase left and right values to minimum value, checking signs for negative or positive value
150+
if(this->left < 0)
151+
{
152+
this->left = MIN_TURN_VALUE * -1;
153+
}
154+
else
155+
{
156+
this->left = MIN_TURN_VALUE;
157+
}
158+
159+
if(this->right < 0)
160+
{
161+
this->right = MIN_TURN_VALUE * -1;
162+
}
163+
else
164+
{
165+
this->right = MIN_TURN_VALUE;
166+
}
167+
168+
std::cout << "LEFT: " << this->left << ", RIGHT: " << this->right << std::endl;
169+
}
103170
}
171+
172+
104173
break;
105-
} else {
106-
// move to differential drive step
174+
}
175+
else
176+
{
177+
178+
//move to differential drive step
107179
stateMachineState = STATE_MACHINE_SKID_STEER;
180+
108181
//fall through on purpose.
109182
}
110183
}
111-
// Calculate angle between currentLocation.x/y and waypoints.back().x/y
112-
// Drive forward
113-
// Stay in this state until angle is at least PI/2
114-
case STATE_MACHINE_SKID_STEER: {
184+
185+
case STATE_MACHINE_SKID_STEER:
186+
{
187+
// Calculate angle between currentLocation.x/y and waypoints.back().x/y
188+
// Drive forward
189+
// Stay in this state until angle is at least PI/2
190+
115191
// calculate the distance between current and desired heading in radians
116192
float errorYaw = angles::shortest_angular_distance(currentLocation.theta, waypoints.back().theta);
117193

118194
result.pd.setPointYaw = waypoints.back().theta;
119195

120196
// goal not yet reached drive while maintaining proper heading.
121197
if (fabs(angles::shortest_angular_distance(currentLocation.theta, atan2(waypoints.back().y - currentLocation.y, waypoints.back().x - currentLocation.x))) < M_PI_2
122-
&& hypot(waypoints.back().x - currentLocation.x, waypoints.back().y - currentLocation.y) > waypointTolerance) {
198+
&& hypot(waypoints.back().x - currentLocation.x, waypoints.back().y - currentLocation.y) > waypointTolerance)
199+
{
123200
// drive and turn simultaniously
124201
result.pd.setPointVel = searchVelocity;
125-
if (result.PIDMode == FAST_PID){
202+
if (result.PIDMode == FAST_PID)
203+
{
126204
fastPID(searchVelocity - linearVelocity,errorYaw, result.pd.setPointVel, result.pd.setPointYaw);
127205
}
128206
}
129207
// goal is reached but desired heading is still wrong turn only
130208
else if (fabs(angles::shortest_angular_distance(currentLocation.theta, waypoints.back().theta)) > finalRotationTolerance
131-
&& hypot(waypoints.back().x - currentLocation.x, waypoints.back().y - currentLocation.y) > waypointTolerance) {
209+
&& hypot(waypoints.back().x - currentLocation.x, waypoints.back().y - currentLocation.y) > waypointTolerance)
210+
{
132211
// rotate but dont drive
133212
result.pd.setPointVel = 0.0;
134-
if (result.PIDMode == FAST_PID){
213+
if (result.PIDMode == FAST_PID)
214+
{
135215
fastPID(0.0,errorYaw, result.pd.setPointVel, result.pd.setPointYaw);
136216
}
137217
}
@@ -147,34 +227,38 @@ Result DriveController::DoWork() {
147227
break;
148228
}
149229

150-
default: {
230+
default:
231+
{
151232
break;
152233
}
153234

154235

155236
}
156237

238+
//package data for left and right values into result struct for use in ROSAdapter
157239
result.pd.right = right;
158240
result.pd.left = left;
159241

242+
//return modified struct
160243
return result;
161244

162245
}
163246

164-
bool DriveController::ShouldInterrupt() {
247+
bool DriveController::ShouldInterrupt()
248+
{
165249

166-
if (interupt) {
250+
if (interupt)
251+
{
167252
interupt = false;
168253
return true;
169254
}
170-
else {
255+
else
256+
{
171257
return false;
172258
}
173259
}
174260

175-
bool DriveController::HasWork() {
176-
177-
}
261+
bool DriveController::HasWork() { }
178262

179263

180264

@@ -193,7 +277,8 @@ void DriveController::ProcessData()
193277
stateMachineState = STATE_MACHINE_WAYPOINTS;
194278
}
195279
}
196-
else if (result.type == precisionDriving) {
280+
else if (result.type == precisionDriving)
281+
{
197282

198283
if (result.PIDMode == FAST_PID){
199284
float vel = result.pd.cmdVel -linearVelocity;
@@ -215,7 +300,8 @@ void DriveController::ProcessData()
215300
}
216301

217302

218-
void DriveController::fastPID(float errorVel, float errorYaw , float setPointVel, float setPointYaw) {
303+
void DriveController::fastPID(float errorVel, float errorYaw , float setPointVel, float setPointYaw)
304+
{
219305

220306
float velOut = fastVelPID.PIDOut(errorVel, setPointVel);
221307
float yawOut = fastYawPID.PIDOut(errorYaw, setPointYaw);

src/behaviours/src/PID.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
#include "PID.h"
22

3-
PID::PID() {
3+
PID::PID() { }
44

5-
}
6-
7-
PID::PID(PIDConfig config){
5+
PID::PID(PIDConfig config)
6+
{
87
this->config = config;
98
integralErrorHistArray.resize(config.integralErrorHistoryLength, 0.0);
109
}
1110

12-
float PID::PIDOut(float calculatedError, float setPoint) {
11+
float PID::PIDOut(float calculatedError, float setPoint)
12+
{
1313

14-
if (Error.size() >= config.errorHistLength) {
14+
if (Error.size() >= config.errorHistLength)
15+
{
1516
Error.pop_back();
1617
}
1718
Error.insert(Error.begin(), calculatedError); //insert new error into vector for history purposes.
@@ -20,13 +21,15 @@ float PID::PIDOut(float calculatedError, float setPoint) {
2021
float I = 0; //Integral yaw output
2122
float D = 0; //Derivative yaw output
2223

23-
if (setPoint != prevSetPoint && config.resetOnSetpoint) {
24+
if (setPoint != prevSetPoint && config.resetOnSetpoint)
25+
{
2426
Error.clear();
2527
integralErrorHistArray.clear();
2628
prevSetPoint = setPoint;
2729
step = 0;
2830
integralErrorHistArray.resize(config.integralErrorHistoryLength, 0.0);
2931
}
32+
3033
//feed forward
3134
float FF = config.feedForwardMultiplier * setPoint;
3235

@@ -132,5 +135,7 @@ float PID::PIDOut(float calculatedError, float setPoint) {
132135
PIDOut = config.satLower;
133136
}
134137

138+
cout << "PID OUTPUT: " << PIDOut << endl;
139+
135140
return PIDOut;
136141
}

0 commit comments

Comments
 (0)