Autonomous Code Missing Variable

Hello,

I am pretty new to coding and have recently begun working on the autonomous section for our robot. Currently I think the best route would be to create a while statement that runs while a certain variable is true. I am unsure what to make said variable though, as I am unfamiliar with timer features in Java.

I have also heard an encoder would allow me to do a similar thing. I was wondering if anyone had helpful tips or ideas.

Thanks!

(We are using a mecanum drive and I have build a functioning teleop mode)

(Source Code)

package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.drive.MecanumDrive;
import edu.wpi.first.wpilibj.motorcontrol.PWMVictorSPX;


public class Robot extends TimedRobot {
  private static final String kDefaultAuto = "Default";
  private static final String kCustomAuto = "My Auto";
  private String m_autoSelected;
  private final SendableChooser<String> m_chooser = new SendableChooser<>();

  private static final int kFrontLeftChannel = 6;
  private static final int kFrontRightChannel = 7;
  private static final int kRearRightChannel = 8;
  private static final int kRearLeftChannel = 9;
  private static final int kJoystickChannel = 0;

  private MecanumDrive m_robotDrive;
  private Joystick m_stick;


  @Override
  public void robotInit() {
    m_chooser.setDefaultOption("Default Auto", kDefaultAuto);
    m_chooser.addOption("My Auto", kCustomAuto);
    SmartDashboard.putData("Auto choices", m_chooser);

    PWMVictorSPX frontLeft = new PWMVictorSPX(kFrontLeftChannel);
    PWMVictorSPX reafLeft = new PWMVictorSPX(kRearLeftChannel);
    PWMVictorSPX frontRight = new PWMVictorSPX(kFrontRightChannel);
    PWMVictorSPX rearRight = new PWMVictorSPX(kRearRightChannel);

    m_robotDrive = new MecanumDrive(frontLeft, reafLeft, frontRight, rearRight);

    m_stick = new Joystick(kJoystickChannel);

  }

  @Override
  public void robotPeriodic() {
  }
  @Override
  public void autonomousInit() {
    m_autoSelected = m_chooser.getSelected();

    System.out.println("Auto selected: " + m_autoSelected);

  }
  @Override
  public void autonomousPeriodic() {
    switch (m_autoSelected) {
      case kCustomAuto:
        while(    ){
          m_robotDrive.driveCartesian(.5, .5,.5, 0.0);
        }        
        break;
      case kDefaultAuto:
      default:
        // Put default auto code here
        break;
    }
  }

  @Override
  public void teleopInit() {
  }

  @Override
  public void teleopPeriodic() {

    double xAxis = m_stick.getRawAxis(0) ;
    double yAxis = m_stick.getRawAxis(1);
    double zAxis = m_stick.getRawAxis(4);

    m_robotDrive.driveCartesian(xAxis, yAxis, zAxis, 0.0);

  }

  /** This function is called once when the robot is disabled. */
  @Override
  public void disabledInit() {
  }

  /** This function is called periodically when disabled. */
  @Override
  public void disabledPeriodic() {
  }

  /** This function is called once when test mode is enabled. */
  @Override
  public void testInit() {
  }

  /** This function is called periodically during test mode. */
  @Override
  public void testPeriodic() {
  }
}
1 Like

I think you should start out by checking out the wpilib documentation and examples. Depending on where exactly you’re starting in this process, I think here would be a good place Creating your Benchtop Test Program (C++/Java) — FIRST Robotics Competition documentation. I think it will give you some more insight into your autonomous question.

But to vaguely answer your question, a while statement could be used under certain conditions, but there are also functions already available to you that get called periodically that will act as the while loop you want, with less possibility of locking up, and ultimately disabling, the robot.

An encoder is a piece of hardware, Sensors — FIRST Robotics Competition documentation, and it could be used as a check during your autonomous routine. It is hard to answer “what to make said variable” without a little more info for what you want to accomplish during your autonomous routine.

You’ve built a functioning teleop mode, so you’re obviously off to a good start, and maybe you’ve already perused the wpilib documentation. Are you doing a command-based robot? Do you have a link to a github repo so other posters can look at your code?

You shouldn’t ever really need a while loop in most FRC programming.

Logically, you want your auto code to run until something happens, which is slightly different.

How to do that depends on how you guys are running your robot, Command-Based, TimedRobot, etc.

I’m using the Timed Skeleton base and working in a single program file. (I’m a beginner and don’t quite understand how to use command structure yet)

When you say until something happens how would I go about that?

(I’ve also provided my code below if that helps)

package frc.robot;

import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.smartdashboard.SendableChooser;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.drive.MecanumDrive;
import edu.wpi.first.wpilibj.motorcontrol.PWMVictorSPX;


public class Robot extends TimedRobot {
  private static final String kDefaultAuto = "Default";
  private static final String kCustomAuto = "My Auto";
  private String m_autoSelected;
  private final SendableChooser<String> m_chooser = new SendableChooser<>();

  private static final int kFrontLeftChannel = 6;
  private static final int kFrontRightChannel = 7;
  private static final int kRearRightChannel = 8;
  private static final int kRearLeftChannel = 9;
  private static final int kJoystickChannel = 0;

  private MecanumDrive m_robotDrive;
  private Joystick m_stick;


  @Override
  public void robotInit() {
    m_chooser.setDefaultOption("Default Auto", kDefaultAuto);
    m_chooser.addOption("My Auto", kCustomAuto);
    SmartDashboard.putData("Auto choices", m_chooser);

    PWMVictorSPX frontLeft = new PWMVictorSPX(kFrontLeftChannel);
    PWMVictorSPX reafLeft = new PWMVictorSPX(kRearLeftChannel);
    PWMVictorSPX frontRight = new PWMVictorSPX(kFrontRightChannel);
    PWMVictorSPX rearRight = new PWMVictorSPX(kRearRightChannel);

    m_robotDrive = new MecanumDrive(frontLeft, reafLeft, frontRight, rearRight);

    m_stick = new Joystick(kJoystickChannel);

  }

  @Override
  public void robotPeriodic() {
  }
  @Override
  public void autonomousInit() {
    m_autoSelected = m_chooser.getSelected();

    System.out.println("Auto selected: " + m_autoSelected);

  }
  @Override
  public void autonomousPeriodic() {
    switch (m_autoSelected) {
      case kCustomAuto:
        while(    ){
          m_robotDrive.driveCartesian(.5, .5,.5, 0.0);
        }        
        break;
      case kDefaultAuto:
      default:
        // Put default auto code here
        break;
    }
  }

  @Override
  public void teleopInit() {
  }

  @Override
  public void teleopPeriodic() {

    double xAxis = m_stick.getRawAxis(0) ;
    double yAxis = m_stick.getRawAxis(1);
    double zAxis = m_stick.getRawAxis(4);

    m_robotDrive.driveCartesian(xAxis, yAxis, zAxis, 0.0);

  }

  /** This function is called once when the robot is disabled. */
  @Override
  public void disabledInit() {
  }

  /** This function is called periodically when disabled. */
  @Override
  public void disabledPeriodic() {
  }

  /** This function is called once when test mode is enabled. */
  @Override
  public void testInit() {
  }

  /** This function is called periodically during test mode. */
  @Override
  public void testPeriodic() {
  }
}

It’s important to understand how the framework works. Specifically, the TimedRobot class already runs everything in a large loop, with the *Periodic methods being run on each iteration of the loop depending on robot mode (Autonomous, Teleoperated, Disabled, etc). Knowing this, you shouldn’t need a loop because you’re already in a loop. Instead, you can use simple conditionals to check the current state of things. This practice is often referred to as a state machine.

Edit: shouldn’t, not should

I’ve been working with a mixture of the documentation youtube videos and Chief Delphi posts. Thanks for the sources I will check them out.

I am using a Timed Skeleton Base since I am unfamiliar with how to utilize the different files provided in Command Base.

I have updated my original Post to include the code I have currently wrote.

Thanks.

As was mentioned already, you just want to pay attention to the state of the robot through the various periodic loops.

You have an autonomous init function that will be called when you transition from disabled → autonomous mode.

One thing you can think to change is determine what autonomous code you want to run in autonomous init, and then do those things in autonomous periodic.

For example, if wanted my auto code to simply drive forward 5 seconds and stop:

Timer m_timer = new Timer();
....
public void autonomousInit(){
    timer.start();
}

public void autonomousPeriodic(){
    if(! m_timer.hasElapsed(5) ){  // False if below the number
        m_drivetrain.drive(.5); // Whatever code it takes to drive your robot
    }
}
.....

Thank you, from an initial glance it seems like I can definitely work with this.

I do however have a few questions.
(Sorry if they seem stupid, I’m new to most of this)

  • Do I need to import some sort of timer library or will the timer class work without it?

  • What does the exclamation mark inside the if statement parameters do?

  • If I wanted to run additional autonomous features (firing a ball by activating the shooter motors) that would also go within the same if statement right?

  • If my above question is true the motors would fire in the order I stated them, or would I need specific code to ensure drive motors and shooter motors didn’t fire at once?

You need to import edu.wpi.first.wpilibj.Timer. The Timer the code snippet is referencing is from wpilib, and not java.util.Timer.

It means “NOT”. It inverts the value logically. So if you have if(!true) { doSomething()}, it means if it is not true, doSomething(). In code example above it means if 5 seconds has NOT elapsed, set the drivetrain to .5.

That depends. If you put it in the same if statement, then it would be saying, if 5 seconds has not elapsed, then activate shooter motors. Is that what you want?

If you had shooter motors and driver motors set to a speed, it would set them in the order you wrote them in the code, but in reality you could consider them all going at the same time. Remember, once you set the speed on the motor it will continue until you set it to 0. So if you don’t want to drive and shoot at the same time you’ll have to work that into your if (and maybe else if and else) statement(s).

1 Like

A couple of quick notes:

A CommandBased robot is basically still a TimedRobot. It just has more stuff automatically added for you. This is a good thing.

And that’s the key: I assume you’re using Visual Studio Code? If so, the wpilib integration into the command bar will do a lot of the heavy lifting for you. I know it doesn’t seem like it right now, but using the commands will mean that you have to write LESS code, not more.

As others have pointed out, you can’t just do things in a loop. Each time the robot automatically calls the periodic functions, it’s asking you the question: “what should I be doing right now?” You can only tell it what to do for the next 0.02 seconds! Then it will ask again: “what about now?” That’s how the timed robot, and all other robots, work.

Now, you could create a bunch of timers, and a bunch of mode variables and boolean variables, but it will end up being far more complicated than the command framework. The wpilib VSCode menu has a shortcut to create a command for you, and it makes the CommandName.java file, fills it in with the right package wrapping, class wrapping, the main overrides, several comments, and is ready for you to just type in a few bits of code.

The main thing to understand about commands is that they have an “initialize” function (what happens when the command starts) and an “execute” function (what happens every 20ms to answer the “what should I be doing now?” question) and you supply an “isfinished” function that returns true or false to tell the robot that it’s now done with that command. So if you’re turning to an angle, isfinished can be as simple as “return gyro.getYaw() >= targetangle” or if you’re driving, isfinished can be as simple as “return encoder.position() >= targetpositoin”. They’re usually one line of code!

How do you tell it to do several things sequentially? Easy! You tell it: do this command, then that command, then the other command. If you have commands for drive, turn, shoot, etc., you can just keep adding more and more drive/turn/intake/drive/turn/shoot commands, and it will do them, automatically, one at a time, and won’t move on to the next command until the previous one has returned “true” in the “isfinished” function.

It seems difficult at first, but trust me, it’s far easier than attempting to hand-code your own command sequencing functions; you would end up having to basically re-invent the entire command system.

One other note: If you’re going to use mecanum, give your drivers a gift and use field-centric driving so they don’t get confused. Mecanum is really hard otherwise. It’s just a couple lines of code. If you have a navx or other gyro, get the gyro angle and feed it into the fourth term of the DriveCartesian function and it will automatically adjust the movement of the robot to be relative to the field instead of relative to the direction the robot is pointed (make sure you have a way to disable it if drivers need to switch to navigating by the camera instead of by looking at the field.)

2 Likes

Anything you want to do should have their initialization done in autonomousInit() and autonomousPeriodic().

If you wanted to drive for 5 seconds, but at 2 seconds turn on the shooter:

Timer m_timer = new Timer();
....
public void autonomousInit(){
    timer.start();
}

public void autonomousPeriodic(){
    if( m_timer.hasElapsed(2){
        m_shooter.shoot();
    }

    if(! m_timer.hasElapsed(5) ){  // False if below the number
        m_drivetrain.drive(.5); // Whatever code it takes to drive your robot
    }
}
.....

And so on…

Thanks for your responses,
They are incredibly helpful for a noobie like me. So far it seems like a timer system is going to be the easiest way to implement autonomous.

Thank you,

So in theory (while inefficient) I could create a serious of if statements based on the matches timing to line up with what I need the robot to do.

1 Like

Give it a go then post more code here if you get stuck.

The timer may be your best bet at this point in the season.

But going forward (in the offseason or next year), take a look at the command based robot that others have suggested. Its not too complicated, but some students who are newish such as yourself did find it to be a little be of a learning curve, so I don’t think its something you necessarily want to tackle at this point in the season. But after they got the hang of it, it makes a lot of sense and I think you’ll find it useful in saving time programming, and putting together more complicated routines.

1 Like

I think I understand how a command should work in theory. My problem arises when I attempt to call subsystems I have created into the robot.java to run them. If creating a subsystem creates a class do I have to initiate a new instance of that class in the Robot file that determines the order everything works?

For example, lets say I create a drive subsystem. I declare all of my variables within this new class and create a function that will make my robot drive.

How do I implement this class within my Robot file. I’m more directly just asking for the code to implement separate class files into my Robot file since this is what I cannot figure out from documentation.

Moreover, if I needed to call over a variable declared in a different subsystem would I need to reestablish it within Robot.Java?

Splitting things out into subsystems is the easiest way for me to conceptualize the robot.

That also lends very much to doing command-based things.

Since you’ve figured out this much, it may be worth your time to checkout command-based as a paradigm. It will make your code a lot less confusing overall (in my opinion).

Do you know of any documentation of command Based Code?

I think it would be helpful to see this code fully fledged out. I could reverse engineering how it works from there.

My biggest problem with Coding has always been knowing word for word what to type down. I can understand the concept behind it but if someone doesn’t show me the code I need to write (in this case calling subsystems within the “main” file that runs everything) I tend to struggle way more to “get it”.

I’ll do my best to research the topic because it seems like figuring out command based now is going to be very helpful as my team starts to implement shooter and climbing mechanisms.

Starts right here, and goes on from there.

There are tons of examples in wpilib github as well as the docs show source code along the way as well.

1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.