Arduino Autonmous car if statements (ultrasonic) - c++

I have run into a problem while creating the if statements for the autonomous car. The car skips most of the if statements and immeaditly goes to the else statement. The sensors give of the right values. Is it because i use "else if" statements or something else? The car is supposed to react to its surroundings, so i had to give it many if statements as possible. But instead it just does the last bit where it goes backwards waits goes backwards left and backwards right. So my question is do i have to add more if statements so it reacts better to its surroundings or is there more to it? Here is the code of the if statements:
if (sensors[0] >= 50 ) { //if the distance of the front sensor is greater than 50cm, than set Fwd true. Otherwise its false.
Fwd = true;
} else {
Fwd = false;
}
delay(50);
if ((Fwd == true) && (sensors[1] > 50) && (sensors[2] > 50)) {
fwd();
} else if ((Fwd == true) && (sensors[1] < 50)) {
fwdRight();
} else if ((Fwd == true) && (sensors[2] < 50)) {
fwdLeft();
} else if ((Fwd == false) && (sensors[1] < 50) && (sensors[2] < 50)) {
Stp();
} else if ((Fwd == false) && (sensors[1] < 50)) {
bwdRight();
} else if ((Fwd == false) && sensors[2] < 50) {
bwdRight();
} else {
Stp();
delay(1000);
bwd();
delay(500);
bwdLeft();
delay(500);
bwdRight();
}

Start by tidying up your code, and it may be obvious where things may be going wrong. For example, you are calling multiple checks to Fwd by doing:
if ((Fwd == true) && ... ) {
...
} else if ((Fwd == true) && ... ) {
...
} else if ((Fwd == true) && ... ) {
...
} else if ((Fwd == false) && ... ) {
...
} else if ((Fwd == false) && ... ) {
...
}
This uses up valuable resources in your program memory. It would be much more efficient to do a single check, and evaluate from there:
if (Fwd){
// Check sensor conditions here
} else {
// Check more sensor conditions here
}
In fact, you could probably omit the Fwd variable (unless you are using it elsewhere) altogether, saving you more memory space:
// Check whether to go forward or backwards.
// >= 50 - forward
// < 50 - backward
if (sensors[0] >= 50) {
// Check sensor conditions here
} else {
// Check more sensor conditions here
}
Overall, you could end up with something like:
// Check whether to go forward or backwards.
// >= 50 - forward
// < 50 - backward
if (sensors[0] >= 50) {
// Going forward, but which direction?
if (sensors[1] < 50) {
fwdRight();
} else if (sensors[2] < 50) {
fwdLeft();
} else {
// sensors[1] >= 50 AND sensors[2] >= 50
// Going straight forward
fwd();
}
} else {
// Check backward sensor conditions here
}
This answer might not directly answer your question, but it should help you diagnose better what is going on.

Related

Multiple if statements are having single else part

I have four if conditions and for all four conditions else is single.
I four conditions are true they have their own result to be executed but if they all fail they should enter in else part which common for all and can be executed only once.
For example, for save button all four fields should have values if not, respective field will throw an error and stop saving form further.
c.save = function () {
if(a == '' || a == undefined){
throw an error for a
}else
if(b == '' || b == undefined){
throw an error for b
}else
if(c == '' || c == undefined){
throw an error for c
}else
if(d == '' || d == undefined){
throw an error for d
}else
c.data.save = true;
}
You could use a bool to check if all if statements have failed.
bool someBoolean = true;
if(a == true) {
// code to execute
someBoolean = false;
}
else if(b == true) {
// code to execute
someBoolean = false;
}
else if(c == true) {
// code to execute
someBoolean = false;
}
else if(d == true) {
// code to execute
someBoolean = false;
}
// check if the bool is still true
if(someBoolean) {
// code to execute if all if statements failed
}
And then all you have to do is set the bool back to it's original state to use it again.

Converting if-else statement to if-else if-else statement

How do I convert this nested if-else statement into a non-nested if-else if-else statement? You may need to add some boolean operators to make this completely non-nested:
if (ball > 0) {
if (cup > 0) {
console.log(“I have a ball and cup.”);
} else {
console.log(“I have a ball.”);
}
} else {
if (cup > 0) {
console.log(“I have a cup”);
} else {
console.log(“I have nothing”);
}
}
If I understand what you are trying to do, then maybe this can help:
if (ball > 0 && cup > 0) {
console.log(“I have a ball and cup.”);
} else if (ball > 0) {
console.log(“I have a ball.”);
}
if (ball <= 0 && cup > 0) {
console.log(“I have a cup”);
} else if (ball <= 0) {
console.log(“I have nothing”);
}
Instead of nesting if-else statements, you can just check for multiple conditions in each if statement.

Tests randomly fails

I'm writing board game and I need following functionality: player rolls two dices, if he rolled doubles (same number on both dice), he gets to roll again, if he rolled doubles again, he goes to jail.
In my Game class it looks like that
void logic::Game::rollTheDice() {
m_throwsInCurrentTurn++;
int firstThrow = m_firstDice.roll();
int secondThrow = m_secondDice.roll();
m_totalRollResult += firstThrow + secondThrow;
if (firstThrow == secondThrow) m_doublesInCurrentTurn++;
}
std::string logic::Game::checkForDoubles() {
std::string message;
if (m_doublesInCurrentTurn == 0 && m_throwsInCurrentTurn == 1) {
m_canThrow = false;
m_canMove = true;
}
if (m_doublesInCurrentTurn == 1 && m_throwsInCurrentTurn == 1) {
message = "Doubles! Roll again.";
m_canThrow = true;
m_canMove = false;
}
if (m_doublesInCurrentTurn == 1 && m_throwsInCurrentTurn == 2) {
m_canThrow = false;
m_canMove = true;
}
if (m_doublesInCurrentTurn == 2 && m_throwsInCurrentTurn == 2) {
message = "Doubles again! You are going to jail.";
m_canThrow = false;
m_canMove = false;
getActivePlayer().lockInJail();
}
return message;
}
void logic::Game::setInMotion(unsigned number) {
m_players[m_activePlayer].startMoving();
m_players[m_activePlayer].incrementPosition(number);
}
m_canThrow basicly enables or disables ability to click "Roll the Dice" button, m_canMove decides if player token can start moving, m_players[m_activePlayer] is std::vector<Player>, startMoving() does that,
void logic::Player::startMoving() {
m_isMoving = true;
}
needed for token movement, so baiscly not relevant here.
Last function from Game class I need to show you is reset(), used mainly for testing purposes
void logic::Game::reset() {
m_throwsInCurrentTurn = 0;
m_doublesInCurrentTurn = 0;
m_totalRollResult = 0;
}
Now finnaly Unit Test that sometimes goes wrong. Sometimes, I mean completely random, like 1 out of 10-20 times.
//first throw is double, second throw is not
TEST_F(GameTestSuite, shouldFinishAfterSecondRollAndMove) {
auto game = m_sut.get();
do {
if (game.getThrowsInCurrentTurn() == 2) game.reset();
game.rollTheDice();
game.checkForDoubles();
if (game.getThrowsInCurrentTurn() == 1 && game.getDoublesInCurrentTurn() == 1) {
ASSERT_EQ(game.canThrow(), true);
ASSERT_EQ(game.canMove(), false);
}
} while (game.getThrowsInCurrentTurn() != 2 && game.getDoublesInCurrentTurn() != 1);
ASSERT_EQ(game.canThrow(), false);
ASSERT_EQ(game.canMove(), true);
game.setInMotion(game.getTotalRollResult());
ASSERT_EQ(game.getActivePlayer().isMoving(), true);
ASSERT_EQ(game.getActivePlayer().getPosition(), game.getTotalRollResult());
}
This line exactly, ASSERT_EQ(game.canThrow(), false); sometimes is equal true after do-while loop that should end once m_canThrow is set to false
Shouldn't:
} while (game.getThrowsInCurrentTurn() != 2 && game.getDoublesInCurrentTurn() != 1);
be
} while (game.getThrowsInCurrentTurn() != 2 && game.getDoublesInCurrentTurn() <= 1);
You want to allow up to two turns but 0 or 1 doubles.

Arduino method making

The code below is part of my "safe" program. I have to make 4 "guesses" (the password consists of 4 numbers). For each guess I use a few if statements but i was wondering if there is a way to make a method for each "guess". This way instead of these 4 sections of if-statements i would just have one Method.
if (turn == 1) {
if ((buttonState != lastButtonState) && buttonState == 1) {
guess1 = newValue;
turn = 2;
Printer();
}
lastButtonState = buttonState;
}
if (turn == 2) {
if ((buttonState != lastButtonState) && buttonState == 1) {
guess2 = newValue;
turn = 3;
Printer();
}
lastButtonState = buttonState;
}
if (turn == 3) {
if ((buttonState != lastButtonState) && buttonState == 1) {
guess3 = newValue;
turn = 4;
Printer();
}
lastButtonState = buttonState;
}
if (turn == 4) {
if ((buttonState != lastButtonState) && buttonState == 1) {
gok4 = nieuwewaarde;
beurt = 5;
Printer();
}
lastButtonState = buttonState;
}
Theoretically it should be possible to shrink it to something like this. Note you should use an array instead of a series of guess1, guess2, … variables.
int guess[4];
if ((buttonState != lastButtonState) && buttonState == 1) {
guess[turn-1] = newValue;
if (turn == 4)
{
gok4 = nieuwewaarde;
beurt = 5;
}
else
turn = turn+1;
Printer();
}
lastButtonState = buttonState;
You can adjust the +1/-1 if you count turn from 0. But with a broader view of what you would like to achieve, there might be other ways to write things.
Besides, Arduino code is not in C++, but AVR. The “user” code is Processing.

Out of range vector subscript C++

I have this method in one of my cpp files where I have navigated my failure to be. I have also added cout statements and checked that there is content in both foo and mainWord. I think my problem has to do with how I've added elements to foo or how I am trying to re-add them. The size mainWord is 88 and the size of foo is more than 1000. Here is where I add elements to foo:
while (myfile>>magic)//store the colours in an array
{
foo.push_back(magic);
}
and here is where I try and change them and add them back in.
void Penguin::addWord(std::vector<int> foo)
{
unsigned fooCounter=0;
int temp;
for (int i=0;i<88;i+2)
{
if(foo.at(fooCounter) == 11111111 && foo.at(fooCounter) != NULL)
{
if(mainWord[i]==1 && mainWord[i+1]==1)
{
foo.at(fooCounter) = 11111111;
}
else if(mainWord[i]== 1 && mainWord[i+1] == 0)
{
foo.at(fooCounter) = 11111110;
}
else if(mainWord[i]== 0 && mainWord[i+1] == 1)
{
foo.at(fooCounter) = 11111101;
}
else
{
foo.at(fooCounter) = 11111100;
}
}
else if (foo.at(fooCounter) == 11111111 && foo.at(fooCounter) != NULL)
{
if(mainWord[i]== 1 && mainWord[i+1] == 1)
{
foo.at(fooCounter) = 00000011;
}
else if(mainWord[i]== 1 && mainWord[i+1] == 0)
{
foo.at(fooCounter) = 00000010;
}
else if(mainWord[i]== 0 && mainWord[i+1] == 1)
{
foo.at(fooCounter) = 00000001;
}
else
{
foo.at(fooCounter) = 00000000;
}
}
fooCounter++;
}
}
I keep getting an error that says: "Debug Assertion Failed. Vector subscript out of range"
...Please help
You have an infinite loop because i is never updated in the for loop. You need to fix the typo:
for (int i=0;i<88;i+=2)
^
^