Tutorial

Debugging: Java Remote debugging

So far you’ve probably been debugging Java code by adding print statements;  you add code that gives you a peek into the robot’s internal state.  Monitoring the robot with ShuffleBoard is similar;  you add output statements to your code.

Imagine a better system that doesn’t require added code, where you could stop time, crack the roboRIO open and see what was going on inside.   You could examine the variables and then watch the lines of code execute, one at at time.  This technique, called Remote Debugging, is available to you from most modern Java development environments.

Remote debugging lets us answer questions like “Did my code even get executed?” or  “Did the initialization code really get executed before the periodic code?” or “What were the variable values?”.   Since the the debugger can let you see the actual execution, you can also verify that conditionals and loops really execute the way you expect.  You can even use the debugger to alter variable values, so novel scenarios can be tested.

We call this technique “remote” debugging because it involves a network connection between your programming laptop and the roboRIO.  Your robot program is executing on the RIO, but it will be controlled and monitored by the development environment on your laptop.  You’ll be watching the action as if it’s happening on your screen, but the action is actually occurring remotely on your robot.

Starting the debugger is almost the same action as deploying code with GradleRIO.  Execute the “debug” command instead of “deploy”:

debug_remote_menu

This command will build and deploy code in debug mode which will configure the RIO to communicate back to your debugger.  Visual Studio Code will also switch into debug mode (as indicated by the Debug icon in the activity bar on the left edge of the window).

Breakpoints

The first important concept in remote debugging is the setting of “breakpoints” in your program.  A breakpoint is a location in your program that you want to watch.   When your robot’s thread of execution reaches that point, the program will freeze and your debugger will come alive.

Inline breakpoints

To create a breakpoint, click to the left of the line numbers in your program.  Below, we’ve created a breakpoint on line 51 of the teleopPeriodic method, indicated by a little red dot:

debug_remote_normal_breakpoint.png

Start the Driver Station software and enable teleop mode.  The normal execution of a robot program is that the RIO will execute teleopInit once and then start executing teleopPeriodic.   When the RIO reaches the breakpoint on line 51, it will pause execution as below:

debug_remote_debug_mode

There is a lot of information going on in this window:

  • In the upper left sidebar you see all the local variables of the teleopPeriodic method, There’s also the “this” variable that you can expand to see all the Robot’s instance variables.
  • Below the Variables section is the Watch section, which lets you add arbitrary expressions to be evaluated.
  • In the lower left of the sidebar is the Call Stack, which tells you what method called your current method, and what method called that method, etc.  The call stack actually lists all the Java threads currently running on the RIO, but you may have to stretch out the window to see them all.
  • Below the Call Stack, there is a list of Breakpoints.  In the above illustration, you would need to collapse the call stack to see the breakpoints.  You can edit or enable/disable breakpoints here.
  • Above the editor window is the debug toolbar:

debug_remote_toolbar.png

The “Continue” tool will cause program execution to resume, until it reaches the next breakpoint.  The “Step Over” tool executes the next line of code.  “Step in” will drill into a method. “Step out”  pops out of the current method to the method in the call stack that called it.  At every step, you can watch the variables change.  You’ll be able to see the code go through “if” statements and loops.

Also, take a look at the “Debug” menu at the top of the window.  Particularly useful in the Debug menu are options to temporarily disable all breakpoints and then later enable all breakpoints.  Disabling breakpoints lets you perform normal robot operations for a while.  Then you can enable breakpoints to examine specific scenarios.

Conditional breakpoints

Note that in our above example, we encounter the breakpoint every single time we execute teleopPeriodic.  We could have put the breakpoint inside the “if” statement, in which case the breakpoint would stop only when the “slowMode” variable was true.

It is often useful to set “conditional” breakpoints that only fire when certain conditions arise.  The conditional breakpoint is indicated by a little red dot with an equals sign in it.  Create one by right-clicking to the left of the line number and specify “Add Conditional Breakpoint”.

For instance, below we have a  breakpoint on line 55 that only fires when both leftSpeed and rightSpeed are greater than 0.5.

debug_remote_conditional_breakpoint

Exception breakpoints

You can also specify that the debugger stops operation when an exception is thrown.  Look in the Breakpoints section at the bottom of the Debug sidebar and enable “Caught Exceptions”.  Exception breakpoints can be especially useful when you’re trying to diagnose unexpected exceptions.

Note that VS Code will break on all exceptions.  Other IDEs allow you to break on specific exception types.

Logpoints

A logpoint is like a breakpoint, but it merely prints a message out to the console instead of stopping.  This is like debugging with print statements, except that you can enter them in the debugger without having to recompile.  Create one by right-clicking to the left of the line number and specify “Add logpoint”.  Logpoints are indicated by a little red diamond.

You can cause logpoints to print out variable values by putting the variables in curly braces.  Below is a logpoint that will print out three variables:

debug_remote_logpoint.png

Examining program state

The Variables section of the debug sidebar will answer many of your questions about what’s going on inside your program.  Spend time exploring the local and instance variables to see what’s in the objects.  Familiarize yourself with the state of health programs so you can better spot error conditions.

The Variables section also allows you to change the values of variables.  Just double-click on any number, boolean, or String value and you can give it a new value.  This feature can let you test specific scenarios, such as “What will happen if my gyro returns a negative value?”.

If you are monitoring specific variables or variable expressions, park them in the Watch section.  They will be reevaluated whenever the program stops.  You can add expressions directly in the Watch section, or you can right-click on them in the code editor and select “Debug: Add to Watch”.

Debugging robot programs with Eclipse

The program on your robot is running within a Java Virtual Machine (JVM).  Remote debugging is possible because JVMs contain features to support it.  The mechanism for debugging is called the Java Platform Debugger Architecture (JPDA).    Visual Studio Code has an extension that connects to JPDA, but so does nearly every other Java development environment.  The debugging functions will be similar on other IDEs, but the user interface may be different.

Eclipse has an excellent built-in Java debugger.  The user interface is different from VS Code, but (in my opinion) it makes better use of you screen space.

debug_remote_eclipse_3.png

Eclipse’s Gradle plugin allows you to execute the GradleRIO deploy task.  Enabling remote debugging is a slight variation on the deploy task.

  1. Go to the Gradle Tasks view and find embeddedtools > deploy.  Right-click on the deploy task and select “Open Gradle Run Configuration”.
    debug_remote_eclipse_1a.png
  2. The Run Configuration dialog will pop up for the “deploy” task.
    debug_remote_eclipse_1b
  3. Click on the Arguments tab and add the debugMode project property.  Then hit the OK button to save.
    debug_remote_eclipse_1c
  4. Next, you’ll need to set up a Remote debugging configuration.  From the Run menu, select “Debug Configurations…”
    In the Debug Configuration dialog, add a new entry under “Remote Java Application”.
    debug_remote_eclipse_2
    Specify a host address that will connect to your roboRIO (either 10.te.am.2 or 172.22.11.2) and set the port number to 8349.

To do remote debugging in Eclipse, you will first deploy the code in debugMode using your new run configuration.  Then, you will attach to the remote process with your new debug configuration.

Debugging robot programs with IntelliJ

IntelliJ also an excellent Java debugger.  It is built-in, no extension needed.  The function and user interface is similar to Eclipse.

debug_remote_intellij_3

To set up remote debugging in Intellij:

  1. From the Run menu, select “Edit Configurations…”
  2. Create a Gradle configuration with a task of “deploy” and arguments turning on the debugMode
    debug_remote_intellij_1
  3. In the same Run/Debug Configurations dialog, create a new Remote configuration for port 8349 and for a host address that connects to your roboRIO.
    debug_remote_intellij_2

To do remote debugging in Intellij, you first deploy the code using your new deploy configuration.  Then, attach to the RIO using the new Remote configuration.

When not to use the Debugger

There are times when the debugger isn’t the right tool.   Robots operate in real-time, so freezing time disconnects them somewhat from real-world processing.    For instance, if you are debugging while motors are moving, stopping the action will the change the physics of your situation.  If you stop a command that has a timeout, the timeout may expire while you’re staring at the code, which change the robot’s behavior.  If you’re investigating at problem related to real-time interactions, you may choose to set logpoints or to use printing, logging, or ShuffleBoard instead.

Overall though, I hope this exercise has sold you on the use of the debugger.  It will be a tremendously useful tool for problem solving.  All serious programmers should learn to use the remote debugger.

Further Reading:

Tutorial

Debugging: print statements and logging

Debugging is the process of figuring out why software isn’t doing what it should, and then fixing it so it behaves better.

Computer programmers always spend more time debugging code than they do writing it in first place. It is important to build up your skills in debugging code, whether the problem is in your own software or in code written by others.

Strangely, there isn’t a lot of literature available on this subject, and practically no formal education on debugging software. There should be more study and more formal methodologies. At least, all programmers should know the general techniques used by others and should learn the tools that are available.

Formalizing the questions

Sometimes debugging is easy. You see the problem immediately, or after a minute’s thought. However, if the problem has taken more than a couple minute’s consideration, you should start to specify the questions you need answers to. Often it helps to actually write these questions.  Really.  Write down the questions as if you you’re posing them to some third party.

Typical questions are:

  • Exactly how do I reproduce this problem? What is the negative scenario (where the problem occurs) and what is a positive scenario (where there is no problem)
  • Where was the program executing when things went wrong? How far into the program did we get? In what routine did the problem occur, and what was the path to get to that routine?  Did the Command I’m working on even execute?
  • What is the state of the data at the time of the problem? What does the data look like in positive scenarios? Why isn’t my Command ever finished?  What are the input and output values on my PID controller?

Debugging with print statements

The oldest and most common tool for debugging is to put temporary “print” statements into the code. You can print out variable values so you know the state of the data. Sometimes you just print little messages telling you where the program was executing, so you get a better idea of where the problem occurred.

A print statement in Java looks like this:

System.out.println("motor speed is " + motor.get());

When this statement executes, the text will print out on VS Code’s RioLog window and also on the Driver Station’s console window.  The printed text will also be available in the Driver Station’s Log File Viewer.  For basic debugging, the console may prove more useful than the Log File Viewer.

Print statements help answer questions like “Did a specific routine even execute” or “How did the motor speed vary during autonomous”.

Exceptions and Stack traces

When something goes seriously wrong in a Java program, the program may communicate this to other parts of the program by “throwing an exception”.  When an exception occurs, the program breaks out of the routine it is running and passes the exception to the routine that called it.  The exception is then propagated up the calling stack until one of the routines can handle it.  Handling the exception is called “catching” the exception.

When an exception is thrown, the program often prints out a “stack trace” to the console, which will show where the error occurred.  There is an example stack trace:

ERROR 1 Unhandled exception: java.lang.NullPointerException org.firebears.betaTestRobot2.subsystems.Board.setMotor2(Board.java:82) 
Error at org.firebears.betaTestRobot2.subsystems.Board.setMotor2(Board.java:82): 
Unhandled exception: java.lang.NullPointerException 
  at org.firebears.betaTestRobot2.subsystems.Board.setMotor2(Board.java:82) 
  at org.firebears.betaTestRobot2.commands.AutonomousCommand.execute(AutonomousCommand.java:29) 
  at edu.wpi.first.wpilibj.command.Command.run(Command.java:292) 
  at edu.wpi.first.wpilibj.command.Scheduler.run(Scheduler.java:224) 
  at org.firebears.betaTestRobot2.Robot.autonomousPeriodic(Robot.java:118) 
  at edu.wpi.first.wpilibj.IterativeRobotBase.loopFunc(IterativeRobotBase.java:225) 
  at edu.wpi.first.wpilibj.TimedRobot.startCompetition(TimedRobot.java:81) 
  at edu.wpi.first.wpilibj.RobotBase.startRobot(RobotBase.java:261) 
  at org.firebears.betaTestRobot2.Main.main(Main.java:20) 
Warning 1 Robots should not quit, but yours did! edu.wpi.first.wpilibj.RobotBase.startRobot(RobotBase.java:272) 
Warning at edu.wpi.first.wpilibj.RobotBase.startRobot(RobotBase.java:272): Robots should not quit, but yours did! 
ERROR 1 The startCompetition() method (or methods called by it) should have handled the exception above.

The above stack trace shows that an unexpected null value was encountered when the AutonomousCommand tried to set a motor value.

A stack trace is kind of a good news / bad news situation.  On one hand, you have a serious problem that shuts down processing.  On the other hand, you know generally what went wrong and exactly where it happened.

Learn to read stack traces and use them in your debugging.  Understand what the exception types are and how to interpret the calling stack.

Logging

The print statements described above are temporary changes to the program.  You should delete them after they have served their purpose.

Logging is a more formal process of printing out program state and execution.  If you identify things you want to monitor, you can leave the logging statements in your code, and then selectively turn on the ones you want to print.  Logs let you answer questions like “How often did our pneumatics fire?” or “What command was running just before we experienced a brownout?” or “Which autonomous program executed and what happened during that command?”

You can log items of different levels of importance.  Java supports seven levels of log severity, in this order:

  • SEVERE – serious failures
  • WARNING – potential problems
  • INFO – informational messages
  • CONFIG – configuration change messages
  • FINE – detailed debugging and tracing messages
  • FINER – more detailed debugging messages
  • FINEST – highly detailed debugging messages

Before you can do any logging, you must first create a Logger variable in each Java class:

private final Logger logger = Logger.getLogger(this.getClass().getName());

To actually create logs, call methods on the logger variable:

logger.fine("vision target acquired: angle=" + a + " : dist=" + d);

logger.config("PID controller values: " + p + "," + i+ "," + d);

logger.info("starting AutonomousCommand3 : gameData=" + gameData);

logger.warning("Air pressure is only " + pressure + " psi");

If you catch and handle an exception, you may want to log the problem, even if you’ve taken care of it.  The proper form is to add the exception to the log statement.  The following code will log a warning message, accompanied by the stack trace:

} catch (IOException e) {
    logger.log(Level.WARNING, "Failed to open connection", e);
}

Make good decisions about what to log. Don’t get carried way. Too many logs might create performance problems. Too many logs make it harder to find what you’re interested in.

Logged data will show up on the driver station Console and also within the Log Viewer.  For long term monitoring, the Log Viewer becomes extremely useful.   The Log Viewer can be used to reconstruct what happened during match.  Having some well chosen log statements may help you reconstruct what commands executed at what times, and what were the critical values of air pressure, elevator height, or motor speed.

Configuring your Loggers

Logging can be reconfigured to print out different things for different scenarios. For instance, you may decide that only messages of level INFO or higher get printed.  Later you can easily switch the level down to FINE, which will cause all the CONFIG and FINE messages to also print.  You can also specify different levels for different Java packages.  For instance, you may want the default log level to be CONFIG, but the autonomous commands log at the FINE level.  These levels are easy to set and easy to change later.

To configure your logging, create a file called “logging.properties” in your “deploy” directory:

debug_log_config.png

Here’s the content of our sample file:

frc.robot.handlers=java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level=ALL

frc.robot.level=CONFIG
frc.robot.commands.auto=FINE
frc.robot.subsystems.DriveTrain=FINEST

The first two lines just cause all messages in your project to be printed out to the console.  Line 4 sets the default logging level to CONFIG or higher for all loggers under the frc.robot package.  Line 5 causes all logging in the frc.robot.commands.auto package to log at the FINE level.  Line 6 sets the logging level of the DriveTrain subsystem to be FINEST.

To tell Java where your logging config file is, you must add one line to your build.gradle file.   You must add one jvmArg to the deploy / artifacts / frcJavaArtifact section:

frcJavaArtifact('frcJava') {
    targets << "roborio"
    jvmArgs = [ '-Djava.util.logging.config.file=/home/lvuser/deploy/logging.properties' ]
    // Debug can be overridden by command line, for use with VSCode
    debug = getDebugOrDefault(false)
}

Configuration specific behavior

Occasionally, you may need to do a little special processing that depends on the logging configuration.  Most of the time this is a bad idea, because logging should not change the behavior of your code.   On the rare occasions when this is necessary, you can detect the logging level as follows:

if (logger.isLoggable(Level.FINE)) {
    doubled=lidar.getDistance();
    logger.fine("Lidar distance = "+ d);
}

Further Reading:

Tutorial

VS Code with GitHub

So you’re developing code for your robot, but where should you store the master copy of that code?  Keeping everything on a single laptop is a terrible plan;  you at least need backups, maybe multiple backups.  Also, you want to keep the history of the development. You might want to compare the code used in two different competitions. And, if the code worked yesterday but fails today, you want to know what has changed.  In professional software environments, the code is usually stored in a Revision Control System.  FRC teams should also follow this practice.

Software Revision Control systems are databases for storing computer software.  They track the history of all changes to the software and allow groups of programmers to share large programs.  They allow anyone on your team to retrieve the current program, or see the versions of the program from the past. 

Probably the most popular revision control system right now is git, a distributed version control system created by Linus Torvalds, the same guy who created Linux. You can use git from the command line, or from within development environments such as Eclipse, IntelliJ, and Visual Studio Code.  GitHub is a web-based hosting service for git, and the GitHub corporation is a FIRST sponsor.  All programming mentors and students can get free GitHub accounts, and FIRST teams can get upgraded Team Accounts.

To say that git is “distributed” means that every programmer will have a copy of the code, along with the history of the changes.  There is also one remote repository of the code out on the internet. Programmers will occasionally pull changes from the remote repository to their local copy and occasionally push their own changes up to the remote repository.  In this way, everyone eventually has the same code and the same history.

Combinations of the code files are called “commits“, and the word “commit” here is both a noun and a verb.  Committing your changes creates a commit that you can retrieve later.

OK, I know that that was a lot of information.  Honestly, git is a really deep subject, and companies that use it develop really complicated methodologies for its use.  I do not recommend that FRC teams try to use everything in the git toolkit, or try to emulate commercial practices.  Especially at first.  Instead, let’s lay out the minimal functions.

Installing git

If you don’t already have git software installed on you laptop, the basic instructions are at:  https://git-scm.com/ .

After installing, open up a terminal window and execute the following:

git config --global user.email "myEmailAddress@whereever.com"
git config --global user.name "My real name"

Note that starting in 2021 GitHub started requiring that users authenticate using Personal Access Tokens. Hopefully, if you install git using the basic instructions above, this should be automatically taken care of, since the default install should include Git-Credential-Manager-Core.

Cloning an existing repository

Suppose that there is a repository on GitHub that you’d like to download to your laptop.  Making a local copy is called making a clone.

Consider the code repository at:  https://github.com/firebears-frc/testrobot0.  Go ahead and visit that page in a browser.  Press the green button labeled “Clone or Download” and then press the little clipboard button.  This will copy the repository’s formal URL into your clipboard.

vsc_git_clone

Now go to Visual Studio Code.

  1. Open the Command Palette by hitting the F1 key (or Control-shift-P on Windows or Command-shift-P on Macintosh).
  2. Type “git clone” and hit the return key.
  3. VS Code will ask for the repository URL.  Paste the URL in and hit return.  You may also need to give your GitHub username and password.
  4. VS Code will ask for the parent directory in which to save the code.  Typically this might be your machine’s Documents directory.
  5. VS Code will ask you if you want to open the repository.  Yes, you do.

At this point you now have a clone of the repository on your machine.  You won’t be able to push changes up to the remote repository unless the owner has granted you permission, but you can read, edit, and deploy this code to the robot.

Creating a new repository

Suppose you have a robot project on your local machine that has never been under git control, but you’d like to upload it into GitHub.

Open the project folder into VS Code and then open a browser to https://github.com.

  1. In the browser, log into your GitHub account.  Click on a green button that says either “New” or “New Repository”.
    vsc_git_new_repo.png
  2. Github will ask for a repository name.  Give it the same name as project directory on your laptop.  You can also specify a description. Probably you should make it a public repository.
    However, do not add a README file or a .gitignore file or a license file.  Your GitHub remote repository must be totally empty at this point.
  3. After creating the repository, your browser will go to a page which displays your new repository URL.  Copy this value into your clipboard.
  4. In VS Code, open the Command Palette and type “git”.  Select “Git: Initialize Repository”.  A file dialog will pop up.  Click on the “Initialize Repository” button.  Your project will now be under local git control, although no files have yet been committed.  The “Source Control” icon in the Activity Bar will now have a blue circle with the number of uncommitted files.
  5. Now you need to commit all your files.
    1. Click on the “Source Control” icon in the Activity Bar.
    2. Click on the plus icon next to Changes.  This will cause all files to be “staged” for a subsequent commit action.
    3. Type in a message describing this commit.  Normally you should put in something informative, but in this case just say “Initial commit”.
    4. Click check-mark icon.  All files are now locally committed.vsc_git_commit
  6. Now we need to add a connection from your local repository to the remote repository.  You must now open a terminal window by typing control-back-quote.  (If you can’t find this key, you can pop down the “View” menu and select “Terminal”).  Type the following lines, with your repository URL pasted into the appropriate spot:
    git remote add origin repository-url
    git push -u origin master

Now go back to your browser and visit the page for your new repository.  You should now see all the files listed on the web page.

Comitting changes to the code

In the Activity Bar there is an icon that opens the Source Control sidebar.  This is where we can manage our git status.

vsc_git_sidebar1

From now on, when you add files, delete files, or modify files, git and VS Code will keep track of how your code differs from the most recent commit.  The Source Control sidebar show you which files have changed.

Let’s make some small changes.  Click to the Explorer tab. Create a README.md file and type some text to describe your current file.  Next, make a minor change to Robot.java, such as modifying a comment.  Click back to the Source Control sidebar and you will see a list of the two files you’ve changed.

vsc_git_sidebar2

Double-clicking on any filename will pop up a window outlining your changes.  Hovering your cursor over any filename will reveal action buttons to discard the changes or to stage the file to be committed.

If you are happy with the changes then you can commit them into git. You do not need to commit all the changed files.  Selecting which ones to commit is called “staging” the changes.  In this case, click the “+” button next to both files to stage them both.

vsc_git_sidebar3

Now type in a message and click the check-mark button. Your changes are now committed to the local repository.

One note about commits: only commit code that you know to be good.  It is bad form to commit code that won’t compile or has some significant problem.  We share code with other programmers by sharing commits.  You don’t want to be the person who breaks other people’s code.

Pulling changes back from the repository

Suppose someone else has made changes to the code and pushed them up to the remote repository.  You’d like to fetch those changes and merge them into our code.  This is called doing a pull from the remote.

You can pull at any time, but it is usually best to commit your code locally before pulling.

Within the Source Control sidebar of VS Code, click on the three little dots to get the More Actions menu.

vsc_git_pull

Select “Pull” from the menu.  This should merge in all changes from the remote repository.

If the incoming changes are in different files from your own changes, then the new adds/updates/deletes will be applied to your collection of files.

If someone has modified a file that you are working on, but where those changes do not overlap your changes, then git will try to cleverly merge the incoming changes into your file.  This might be perfectly fine, or it might break your code.  These things happen.  Keep calm and fix the code.  It is your responsibility to fix and test your code before pushing it up to the repository.

However, if the incoming changes overlap with your changes, then git will declare a “merge conflict” which you must resolve before you can commit and push.  VS Code will show you each conflict and give you options on how to handle it.  If none of the offered options are correct, you may choose to just edit the file until it is right.  When all code has been fixed, you must stage and commit all changed files.

Pushing your changes up to the repository

If you are ready to release your changes to the rest of the group, you can push your commits up to the remote repository.

Open the More Actions menu and select “Push”.  Done.

Synching with the remote repository

There’s an important discipline that everyone must develop with respect to the remote repository, which is that you should always pull in remote changes before pushing up your own.  If there are incoming changes, then you must recheck the merged code to verify that it is OK.

There is a “Sync” option in the More Actions menu that will do the pull and push in one step.  This can be a nice feature if no one else is working on your code.  If multiple people are working, then Sync does increase the risk that the repository will contain combinations of files that do not work together.  With multiple programmers, you should avoid Sync and perform the following steps manually:

  1. Stage and commit your changes locally.
  2. Pull remote changes, and deal with any merge conflicts.
  3. Verify that the merged code compiles correctly and that the code works correctly.  If there are any problems, fix them and then go back to step 1.
  4. Push all commits to the remote repository.

Further Reading:

Tutorial

Creating Java Robot Programs with VS Code

Now that you’ve got Visual Studio Code installed and configured for WPILib, you can start creating robot programs.  The WPILib extension contains a wizard to get you going quickly.

You can start coding before the robot exists, but if you have a physical robot available, so much the better.  For this example, let’s assume we have the roboRIO set up on a test board, with a joystick, one motor and one motor controller.

Step 1: Create a new Robot Project

Start up VS Code.  If the WPILib extension is properly loaded, then every window’s title bar will have a red hexagon around the letter “W”.  This is a button that will open up the Command Palette to show all the WPILib commands.

wpilib_logo

Click on the “W” button, and select “Create a new Project”.

vsc_program_palette

This will pop open the WPILib Project Creator window.

vsc_program_creator

There are three buttons just under the welcome message.

  • The first button lets you choose either Template or Example.  Templates are bare-minimum projects that can be the basis for your robot program. Examples are projects for specific purposes.  Examples can also be the basis for your work, but they are especially useful to demonstrate different robot functions.
  • The second button lets you choose either Java or C++ programs.
  • The third button picks a specific Template or Example.

For this example, we’ll specify a Java template for “Iterative Robot”.   Fill in a parent folder, project name, and your team number.  Generate the project and open it in the current window.

Once generated, VS Code will open the File Explorer sidebar, so you can see all the new files created.  Go ahead and look at everything. In particular note that all the Java source code is under the “src” directory.  Also, take a look at the “build.gradle” file which controls how the project is compiled and deployed.

This project is a complete robot program.  You could deploy it to your robot, although it doesn’t do anything yet.  Click on the “W” button and select “Build Robot Code”.  All code will be compiled locally, and you should see the message “BUILD SUCCESSFUL”.

Step 2: Program to control one motor

From the File Explorer, open up the “Robot.java” file.  This is the program executed by your robot.  Read through the whole file.

vsc_program_0

The robot will execute Robot.java as follows:

  • When the robot starts executing the program, it will initialize all class variables, and will then call robotInit().  Then, no matter what mode it is in, it will call robotPeriodic() repeatedly.  The standard for FRC robots is to attempt 50 calls a second.
  • When the robot transitions into autonomous mode, it will call autonomousInit() once and then call autonomousPeriodic() repeatedly.
  • When the robot transitions into teleoperated mode, it will call teleopoInit() once and then call teleopPeriodic() repeatedly.
  • There are also methods for testInit(), testPeriodic(),  disabledInit(), and disabledPeriodic().   These are not often used.

To keep this tutorial really simple, we’re going to delete everything except robotInit() and teleopPeriodic().  Your bare-minimum robot program is below.  Once you’ve modified it, hit the “W” button and try to “Build Robot Code”;  you should get a successful build.

vsc_program_1

For this example, assume we have a joystick connected to drivers’ station and a motor controller connect to the roboRIO.  We’ll create two variables around line 7 to represent them:

Joystick stick;
SpeedController motor;

Now we’ll instantiate the objects inside the robotInit() method:

public void robotInit() {
    stick = new Joystick(0);
    motor = new WPI_TalonSRX(2);
}

For my example, I’m using a Talon SRX connected to CAN ID 2.  If you’re using any other motor controller, just change the line to reflect your hardware.

Next, change your teleop mode so it reads the joystick, and sets the speed of the motor:

public void teleopPeriodic() {
    double speed=stick.getY();
    motor.set(speed);
}

The getY() function tells us how for forward or backwards the joystick has been pushed.  The speed value will be a number between -1.0 and 1.0.

Hit the “W” button and build robot code again.  You should get BUILD SUCCESSFUL.

Step 3: Build and deploy

Now, connect all the hardware.  Your laptop should connect to the roboRIO, either through USB, Ethernet, or through the radio.  The joystick should be attached to the laptop.

Hit the “W” button and choose “Deploy Robot Code”.  VS Code will compile the project again and deploy it out to the roboRIO.  You should see BUILD SUCCESSFUL in the terminal window.  The RioLog window will open inside VS Code.

vsc_program_deploy

The most common failure at this point is “Target roborio could not be found at any location”, which means that you’ve failed to make a network connection to the robot.  Debug all the physical connections or maybe try a different way of connecting to the robot.  Sometimes you will need to disconnect from all other networks, so VS Code isn’t trying to find your robot out on the open internet.

Step 4: Drive your robot

Start up the FRC Driver Station software.  You should see green bars next to “Communications”, “Robot Code”, and “Joysticks”.  Also, you should see your correct team number.  If the team number is wrong, click the Gear icon on the left side to get to the setup panel.

vsc_program_driver

Click the “Enable” button to initialize teleoperated mode.  You should now be able to drive the motor with the joystick.

Note that the RioLog window in VS Code is still connected and will show you console output from the roboRIO.

Consider for a moment what’s going on with the code.  The robotInit() method was called once, and then teleopPeriodic() is being called 50 times a second.  Each call of teleopPeriodic() reads the joystick and passes that value into the motor.

Further Reading:

 

Tutorial

Installing VS Code

Note that the following document was written while we were still in the 2019 alpha test of WPILib.  When the 2019 software is officially released, it will include a one-step installer that sets up almost everything into a single frc2019 directory, including a customized version of Visual Studio Code. So, some of the following may be unnecessary, but there is still some good information about VS Code.  Also, you could use the following to roll your own environment, or experiment with developmental versions of WPILib.

When the new software is officially released, it is recommended that you use the one-step installer.

Starting in 2019, the officially supported development environment for FRC software development will be Visual Studio Code. That’s not to say that you cannot use Eclipse, IntelliJ, or vim if you want. In fact, if your team is happy with another environment, then you can safely stick with it. However, the excellent support from the WPILib team will be behind Visual Studio Code.

The first thing to know is that Visual Studio Code is not the same as Visual Studio. Visual Studio is a heavyweight Integrated Development Environment, primary for working with Microsoft applications. Visual Studio Code (let’s call it VSCode) is a much lighter text editor with an extension mechanism. The WPILib team will be providing a new extension for FRC development.

FRC robot programs will be built using GradleRIO, which can also be executed from Eclipse, IntelliJ or from the command line.

Step 0: Install prerequisites

You must install Java.  Even if you will be developing in C++, you’ll need Java installed to run GradleRIO.  You must define your JAVA_HOME environment variable, since VSCode uses it to find your Java install.  After installing, you should be able to execute “java -version” at a command prompt and get back the current version of the java runtime.  Execute “javac -version” to get back the version of the java compiler.

You must install git, instructions for which are at: https://git-scm.com/ Even if you aren’t using git, VSCode expects it.  After installing, try executing “git –version” at a command prompt.  If it prints back the git version number, you’ve installed it correctly.

If you will be doing C++ development, you must install the compiler toolchains at: http://first.wpi.edu/FRC/roborio/toolchains/

Step 1 : Download and install VSCode

VSCode is available for Windows, Macintosh, and Linux. Download the installer from https://code.visualstudio.com/download . If possible, run the installer as Administrator.

Once installed, VSCode will start up at the Welcome screen

vsc_install_vsc

VSCode is pretty feature rich, and you should definitely start reading the documentation and memorizing the keyboard shortcuts.  Here are a few concepts to get started:

  1. The icons on the left edge make up the “Activity Bar”.  Clicking on the icons will open up the “Sidebar” which offers more functions.
    The icon on top opens the “Explorer” sidebar which shows all the files that you can edit.
    The squarish icon on bottom opens the “Extension” sidebar, which lets you manage software extensions for VSCode.
    Hitting control-B (or command-B on a Mac) will toggle away the sidebar, so you can make full use of screen space.
  2. Holding the control key down and hitting the back-quote character will open a terminal panel on the lower part of the screen.  (The back-quote character is usually in the upper left corner of your keyboard, just under the Esc key).   You’ll probably need to get comfortable with terminals and command lines when developing with VSCode.
    Hitting control-back-quote again will toggle the terminal away.
  3. The F1 key will open the “Command Palette” at the top of the screen.  Also, you can hit control-shift-P on Windows or Linux.  Macintosh users can hit Command-Shift-P.  The Command Palette lets you invoke special commands inside VSCode.  It’s pretty good about offering you suggestions for what you want to do.  Many of these functions are available from menus or from keyboard shortcuts, but you’ll find yourself using the Command Palette a lot.
    The FRC extension for WPILib adds new commands to the Command Palette for building robot code and reconfiguring your robot development environment.

Step 2 : Install language extensions

Click the square “Extension” icon on the Activity Bar.

If you will be doing Java development, type “Java Extension Pack” into the sidebar window.  Select the entry for “Java Extension Pack” and click the green Install button.  After the install is done, click the blue Reload button to restart VSCode.

vsc_install_java

If you will be doing C++ development, search for the “C/C++” extension.  Install and Reload.

vsc_install_three_dot

Note the three dots on the upper right corner of the sidebar.  VS Code calls this the “More Actions” button, and clicking on it will open a menu.  Select “Show Installed Extensions” from the menu.  If everything was successful, you should see your extensions listed in the sidebar.

Step 3 : Install the WPILib extension

At the time of this writing, you can get the alpha release of the WPILib extension from https://github.com/wpilibsuite/vscode-wpilib/releases .  Download the VSIX file.

Click the “Extension” icon on the Activity Bar to open up the Extension sidebar.  Click on the More Actions button on the upper right corner of the sidebar and select “Install from VSIX…”  Specify your new VSIX file.  Install and then hit the blue Reload button.

If you show installed extensions, you should now see the WPILib extension added.  The Command Palette will now offer WPILib commands.  There will also be a little “W” button in a red hexagon on the title bar of all windows. It pops open the Command Palette and lists all WPILib commands.

vsc_install_wpilib

Further Reading: