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

Eclipse with Github

Programming alone is sometimes difficult, but one programmer can only do so much. It’s better to work as a team. Groups of programmers can share the load, but having multiple people working on the same code adds additional challenges.  You’ll need extra communication to keep everyone productive, and additional tools to keep from losing work.

Professional environments use Revision Control Systems to store the code, communicate the changes, and keep people from overwriting each other’s work.  FRC programming teams should also use Revision Control.

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 and configuring git

You are not required to install git, since there is a version packaged within Eclipse.  However, you may choose to install it anyway.  Instructions are at:  https://git-scm.com/ .

You should configure git to know who you are.  This information will be added to the repository very time you commit.  Open the Eclipse Preferences dialog and select Team > Git > Configuration.  Add user settings for “user.email” and “user.name”:

eclipse_git_config

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 Eclipse:

  1. From the main menu select File > Import…
  2. In the Import dialog, select Git > Projects from Git.
  3. Select Clone URI
  4. The Source Git Repository page should already be populated from your clipboard.
  5. For Branch Selection, select at least the “master” branch
  6. For Location Destination, make sure you’ve selected a plausible location, such as in your Documents directory.
  7. Specify the project type.  In this case, choose to import existing Eclipse projects.  Hit the Finish button

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 in Eclipse 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 Eclipse, right-click on the project name and select Team > Share Project…
    1. Check the box for “Use or create repository or create new one.
    2. Click on the Location of your project
    3. Click the “Create Repository” button
    4. Click the “Finish” button.  Your project will now be initialized as a local git repository.
  5. Now you need to commit all your files.  Right-click on the project and select Team > Commit… This will expose the Git Staging view.
    1. Drag all files from “Unstaged Changes” to “Staged Changes”
    2. Type in a Commit Message describing this commit.  Normally you should put in something informative, but in this case just say “Initial commit”.
    3. Click Commit and Push…
    4. The Destination Git Repository dialog will be filled in based on your clipboard.
    5. Click the Next button twice to get to the “Push Confirmation” dialog.  Push the Finish button.
  6. 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.

Committing changes to the code

From now on, when you add files, delete files, or modify files, git and Eclipse will keep track of how your code differs from the most recent commit.  The Git Staging view keeps track of what has changed.  When you are ready to make a commitment, drag the files you want committed into the “Staged Changes” area.  Usually you’ll commit all changes, but you might choose to just stage a subset.

eclipse_git_commit0

Type in a commit message.  Try to write informative messages, since you and others will be reading this later.  Good messages say things like “Updated autonomous commands for new encoder” or “Code changes after first regional”.   Bad messages contain jokes or gibberish or say things like “changed stuff”.

After entering a useful message, hit the “Commit” button.  This will commit your changes locally, but will not yet push those changes upstream to Github.

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.  That is to say, commit the code but don’t push it up yet.  Follow the directions in the previous section to do the commit.

To pull down changes, right-click on the project and select Team > Pull.   The best case scenario (which is usually what happens) is that upstream changes will be seamlessly added to your code and everything will work perfectly.

One thing that might go wrong is that the changes pulled in will invalidate or undo something you are doing.  You should always look over the incoming changes.  Check the Problems view in Eclipse to see if new errors have been added.  Recompile and run any relevant tests.

The worst case scenario is that someone else will have changed files that you are working on, and you will need to “merge” changes.  The Git Staging view will show which files are in conflict.

eclipse_git_merge1

Right click on one of the conflicted files and and select the Merge Tool, which will show the differences between your commit and the incoming commits.  In the picture below, local changes are on the left and incoming are on the right.  Edit the left pane to be the compromise between these changes.

eclipse_git_merge2.png

After you’ve modified a conflicted file and saved the changes, go back to the Git Staging view and drag the into the “Staged Changes” area.   After merging all the conflicts, hit the “Commit” button.

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.

If you are the only programmer working on a repository, you can push changes from the Git Staging view and its “Commit and Push…” button.

eclipse_git_commit

If  there are multiple programmers, you should just “Commit”.   Later, you can push all changes by right-clicking the project and selecting Team > Push to Upstream.

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.

With multiple programmers, you should perform the following steps manually:

  1. 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

Installing Eclipse

Eclipse is a sophisticated professional development environment for Java, C++, and other languages.   Eclipse was the officially supported development environment for FRC for the 2015 through 2018 seasons.  In 2019, WPILib has shifted their focus to developing in Visual Studio Code, but you’ll find that Eclipse is still an excellent platform for FRC development.

FRC robot programs will be built using GradleRIO, which can execute from inside any development environment.

Step 0:  Install prerequisites

You must install Java.  Even if you will be developing in C++, you’ll need Java installed to run Eclipse and GradleRIO.  You should define your JAVA_HOME environment variable to point to your JDK installation.  Often setting JAVA_HOME is considered optional, but I have seen many strange situations resolved after this variable has been properly set.

You should obtain and run the WPILib one-step installer (available at the beginning of the 2019 season).  Even if you’ll be developing with Eclipse,  you’re likely to need the tools and project templates included in this package.

It is recommended (though not strictly required) that you also install git, instructions for which are at: https://git-scm.com/ .

Step 1: Download and install Eclipse

Eclipse is available for Windows, Macintosh, and Linux. Download the installer from https://www.eclipse.org/downloads .  As of this writing, the latest version of Eclipse is called Photon.  If possible, run the installer as Administrator.  The installer will offer you several versions of the program.  Pick either “Eclipse IDE for Java Developers” or “Eclipse IDE for C/C++ developers”.

eclipse_install_installer

Eclipse is a big program, and you should consider looking at the online documentation. Here are a few concepts to get you started:

  1. There are a lot of things going on in the main Eclipse window.  Editors appear in the middle of the window.  This is where you modify code. The tabbed panels surrounding the editors are called Views. Views give you information about your whole project and allow you perform important actions, such as build and deploy code.  There are more views available than are currently displayed, and you can add them from the Window > Show View menu.
    For now, important views to know about include:

    1. The Package Explorer view on the left side shows all available projects.  From here you can open projects and then drill down to find files which can then be edited.
    2. The Outline view on the right side shows a table of contents of any file you are editing.
    3. The Problems view on the bottom shows things that are wrong with your code.  If there is a compile error in the code, you will see it here.
  2. The Preferences dialog allows you to change some Eclipse configurations.  On Macintoshes this can be opened from the Eclipse menu.  On all other computers it is under the Windows menu.
    Also, right-clicking on any project within the Package Explorer view will let you open the Properties dialog for that project.  The project Properties dialog lets you reconfigure the project.
  3. You can extend the functionality of Eclipse by adding plugins.  Plugins are managed from the Help menu, starting with the menu items for “Install New Software…” and “Eclipse Marketplace…”

eclipse_install_eclipse

Once Eclipse starts up, you should verify that it will be using your preferred Java installation. Open the Preferences dialog and then click on “Java” and then “Installed JREs”.  Make sure that your preferred JDK installation is present and is checked.

eclipse_install_jre.png

Step 2: Install the Gradle plugin

Now we’ll want to install a plugin to Eclipse that makes it easier to build and deploy your robot programs.  Click on the Help menu and select “Eclipse Marketplace…”  In the dialog’s find box, type “Buildship Gradle”.  Click the Install button for the Gradle plugin.  Eclipse will need to restart to complete installation.

eclipse_install_plugin

After the restart, open the Eclipse Preferences dialog and click on the “Gradle” item.  Make sure that “Gradle wrapper” is selected.  Apply and close.

Click on the Window menu and select “Show View…” and “Other…”.  Find the “Gradle” item and select “Gradle Tasks”.   The Gradle Tasks view is where you will build and deploy your robot programs.

Step 3: Build a simple project

Creating  new robot programs in Eclipse is a lesson I’ll defer to another tutorial.  For now, you can download an existing project and verify that Eclipse can build robot programs.

  1. Go to https://github.com/firebears-frc/testrobot0/releases/ and download testrobot0.zip . Uncompress this ZIP file onto your laptop, probably in your Documents folder.
  2. From the File menu, select Import…
  3. In the Import dialog select General and then Existing Projects.  Select your new testrobot0 directory as the root.  Hit the Finish button.  This will create a new testrobot0 project in your Package Explorer.
  4. You should also see testrobot0 in your Gradle Tasks view.  Open this item and then open “build”.  Double-click on the “assemble” task.  This should successfully compile the program.
  5. Under embeddedtools, double-click on the “deploy” task to deploy the program to your robot.  This will fail if you aren’t connected to a roboRIO.  But, no harm will have been done.

Further Reading:

Tutorial

Creating Java Programs with Eclipse

Creating GradleRIO FRC robot programs in Eclipse is quite easy.

Step 0: The prerequisites

At this point you should already have installed Java and set up Eclipse with the Buildship Gradle plugin.

You must be connected to the internet the first time you build the project.  After the first build, you can build in offline mode.

Also, you should obtain and run the WPILib one-step installer (available at the beginning of the 2019 season).  Even if you’ll be developing with Eclipse,  you’re likely to need the tools and project templates included in this package.

Step 1: Create a new Robot Project

There are currently several ways to create a basic WPILib robot project:

  • Create a new robot project with VS Code using the WPILib extension.
  • Create a project with RobotBuilder.  You will need a recent version of RobotBuilder that generates GradleRIO projects.  The 2019 software release will contain all new tools, including RobotBuilder.  Or, you can build the latest version from GitHub.
    RobotBuilder creates a full command-based project, so it may be more complicated than what is described in Step 3 below here.
  • Uncompress a copy of the  Quickstart.zip file and make a copy of the “java” directory.  Rename the directory to whatever you like.

Now, whichever method you use, add an empty directory called “vendordeps”.   Your project should now look like this (plus or minus the BSD license file):

eclipse_program_files.png

There’s one tiny change you must make to the build.gradle file before importing into Eclipse.  Open build.gradle in a text editor and set you team number at about line 17:

eclipse_program_gradle

Then, inside Eclipse, open the File menu and select File > Import > Gradle > Existing Gradle Project.  Select your project root directory and hit the “Finish” button.  It may take a while the first time you load a Gradle project, because Eclipse must download the dependencies off the internet.

Third party dependencies

If you intend to use any third-party software, you will need to add some JSON files to the vendordeps directory.  The best way to get these files is to get the official installers.  Examples of third party packages include:

First Build

Open the Gradle Tasks view.  You should see your new project listed. From the tasks view, open your project’s icon and select the “build” folder and then double-click on the “build” task.  This should successfully build your new FRC Java project.

Check the Problems view.  There should be no errors in your project.

 

Step 2: Make the project your own

Your minimal project is too generic, and you should now tweak it for you and your team.

In the Package Explorer, open the src/main/java folder.  Drill into the packages to reveal the Robot.java file.

If you started with the Quickstart.zip, the base package will be “frc.robot”. You can change it to almost anything, but a good choice would be to your team name or number.  Right-click on the package name and select Refactor > Rename…    Specify your new package name and hit OK.  Next, double-click on the build.gradle file, which will pop open an editor.  This file controls the build process.   If there is a ROBOT_CLASS variable, make sure it uses your new package name.  Hit Control-S to save.

Go back to the Gradle Tasks menu and execute build > build.  Everything should build successfully.  If your robot is connected, you can also deploy code by selecting the embeddedtools > deploy task.

 

Step 3: Program to control one motor

If you started your program in RobotBuilder, you may already have mostly complete program.  If you started with the Quickstart example, your program is mostly just in one Robot.java file.  We can augment the Quickstart example to control a motor.

Back in the Package Explorer, double-click on that Robot.java file.  This is your main Java program for controlling the robot.

All of the code in Robot.java is useful, but for simple programs it is optional.  To keep this tutorial really simple, we’re going to delete everything except robotInit() and teleopPeriodic().   Also we’re going to tweak the “import” statements a bit:

eclipse_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.

At this point, check the Problems view and verify that there are no compiler errors.  From the Gradle Tasks view you can now build or deploy the program.

 

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.

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: