So I am trying to write some code that allows me to select what autonomous runs for the autonomous portion of the match using an interface on the screen. It’s basically 4 rectangles that I can use to select a corner of the field for auton. I put an if statement in the pre_auton function to set two variables to the x and y coordinates of the last location pressed on the screen. It’s in pre_auton to allow me to select the program after we plug into the tower but before auton starts. Then, in the auton function, I have 4 if statements asking what range the coordinates are in to determine what “button” was pushed. However, every time I start the program using the timed run part of the controller to give me 3 seconds of pre_auton, no matter where I push on the screen, it always runs the first function. I’m just wondering if anyone has tried this before and know if this is possible. Screenshots:
You want logical and, which is && symbols.
In this pre autonomous state are the buttons on the controller responsive? Your thread talks specifically about the brains response but is the controller also fully responsive?
No, all controller input is completely disabled during pre autonomous.
You should make it run on the controller instead, because you can’t touch your robot when the field controller has started (in some occassions). I can post my code from last year that did this, but with a selection menu.
I’ve tried this before, it still gives the same results, but ill change it anyway
I was thinking I have a teammate plug the controller in and start the code. This puts the robot in pre_auton state so the screen should be responsive on the brain. I’m also [retty sure the controller is completely disabled during pre_auton so the buttons wouldn’t be responsive, am I wrong?
I’m not sure if the controller is disabled during pre_auton, but you don’t need it during then specifically. Even if it is, a lot of auton selectors on the robot continue to work, so one of the states before auton takes controller input. My code made a thread (task) in initialize(), then made sure it had finished in auton, and if it didn’t, a default was run.
In this scenerio, it’s the same result because both sides of the equation are booleans, which will work with bitwise AND logical ‘and’ operators. However, it’s goood practice to use logical and to avoid unwanted bugs and oversights.
“&” can also be used as the “address of” operator, used in both C and C++.
Since robotics are teachable moments, I try to teach the clearest way to do things, as you suggest.
Fun fact that’s applicable here, you can just use the word “and” in this context as valid C++ code. See here for other alternatives: Alternative operator representations - cppreference.com
Would you mind sharing some code for that if you still have it? That sounds logical, but I have no idea how to go about that.
Absolutely!
// An array of the autons
// Stores a pointer to a function that returns void and takes a pointer to a chassis as a parameter
std::array<void (*)(pros::ADIDigitalOut&), 2> autons = {DefensiveAuton, OffensiveAuton};
// Indexes of the autons
enum autonsIndex { Defensive = 0, Offensive, autonLength };
// Auton names
std::unordered_map<int, std::string> autonNames = {
{autonsIndex::Defensive, "Defensive"},
{autonsIndex::Offensive, "Offensive"}
};
/*
...
*/
// Controller refresh rate is 50ms max. I use 100ms
void autonSelection()
{
// Prints the auton selection screen
master.clear();
pros::delay(100);
master.print(0, 0, "Selecting Auton.");
pros::delay(100);
master.print(1, 0, "Left/Right Arrows/A");
pros::delay(100);
master.print(2, 0, "Auton: %s", autonNames[selectedAuton].c_str());
pros::delay(100);
// While 'a' hasn't been pressed
while (!master.get_digital_new_press(pros::E_CONTROLLER_DIGITAL_A))
{
// Cycle left
if (master.get_digital_new_press(pros::E_CONTROLLER_DIGITAL_LEFT))
{
// Subtract one from the current auton, and if it's less than 0, cycle back to the end
selectedAuton = autonsIndex((2 + (selectedAuton - 1)) % 2);
// Print selected auton
master.clear_line(2);
pros::delay(100);
master.print(2, 0, "Auton: %s", autonNames[selectedAuton].c_str());
pros::delay(100);
}
// Cycle right
else if (master.get_digital_new_press(pros::E_CONTROLLER_DIGITAL_RIGHT))
{
// Add one to the current auton, and if it's greater than the length, cycle back to the beginning
selectedAuton = autonsIndex((selectedAuton + 1) % 2);
// Prints selected auton
master.clear_line(2);
pros::delay(100);
master.print(2, 0, "Auton: %s", autonNames[selectedAuton].c_str());
pros::delay(100);
}
// Stops the program from using up all the resources
pros::delay(2);
}
// 'a' has been pressed
// Print selected auton
master.clear();
pros::delay(100);
master.print(0, 0, "Auton: %s", autonNames[selectedAuton].c_str());
pros::delay(100);
// Prompts the user to select the driver (optional), and prints the current one
master.print(1, 0, "Select Driver");
pros::delay(100);
master.print(2, 0, "Driver: %s", presetNames[selectedPreset].c_str());
pros::delay(500);
}
/*
...
*/
void my_task_fn(void* ignore)
{
if (!pros::competition::is_autonomous())
{
autonSelected();
}
}
// all other competition modes are blocked by this function
void initialize()
{
inertial.reset();
pros::lcd::initialize();
pros::ADIDigitalOut pneumatics('A');
chassis->setMaxVelocity(240);
pros::delay(100);
master.clear();
pros::delay(200);
master.clear();
pros::delay(100);
#if COMPETITON
pros::Task my_task (my_task_fn, NULL, TASK_PRIORITY_DEFAULT, TASK_STACK_DEPTH_DEFAULT, "Auton Selector");
#endif // COMPETITION
}
/*
...
*/
void autonomous()
{
pros::ADIDigitalOut pneumatics('A');
while (inertial.is_calibrating())
{
pros::delay(2);
}
(autons[selectedAuton])(pneumatics); // Runs the selected auton
}
You can find the full github here: GitHub - Joeger-Bahar/vexRobotics
You need an
Else {
} after the last else is statement, and you need to put the thing in preauton in a while statement (while (1))
You don’t need a terminating else block in C++. You “need” a default for a switch statement.
while
instead of if
might be the problem.
I tried changing the if in the pre_auton to a while (1), but now it doesn’t run any of the autos when auto does start. I’m not super well versed in C++ but my theory is that the brain doesn’t break the while loop when starting auto for some reason.
I actually just tried adding an else statement to print “nothing selected” if none of the autos were picked. Nothing ended up printing on the screen so this reinforces my previous theory
this also looks way beyond my level of comprehension as far as c++ goes lol
The math with the modulos is just to make sure the selection can loop around.
As for the first few lines, they are a bit complicated. They basically just store functions as if they’re variables, and allow you to run them like so
autons[0](chassis) // Call the first function in the array
It looks complicated, but you can kind of just copy/paste and it will work.
Here’s a simple explanation for a pretty basic auton selector.
https://www.rollingrobotsonline.com/v5-gui-auton-selector