first impressions of VS Code (visual studio code)

FIRST Robotics is using VS (Visual Studio) Code as the default IDE next year so I’ve developed a sudden interest in learning it :).

My overall impressions

It is much faster to get started with VS (Visual Studio) Code than Eclipse. And for the simplified use cases for FIRST robotics this makes sense.

Initial install

I installed it about two months ago. That was easy. I went to the website and downloaded. I didn’t have time to do anything then so my only experience was when I double clicked a .java file when preparing for my QCon Java 11 presentation. It’s a nice editor so cool that it opened out of the box. Not so cool that it changed my defaults for opening files without telling me.

Also nice that VS Code prompts with a suggestion to install the Java extension pack when I opened the Java file.


Since I didn’t do anything, the first order of business was to upgrade to the latest version. VS Code makes this easy. One  a Mac, you go to code > check for updates. It downloads quietly in the background. Then you go back to Code and choose restart to download.

Like Eclipse, the release notes automatically open. However, since I’m completely new to the tool, everything is new to me so I didn’t read it.


The FIRST website suggests some plugins. To start with, I installed:

  • Java extension pack – includes the plugin for Maven
  • C++
  • WPILib – this is a custom download (vs being part of marketplace at this time).

I like that it uses a Marketplace like Eclipse. I also like that you just click “reload” to have the downloaded plugins take effect (rather than having to restart the whole IDE). I also like that the extensions menu has an install from VSIX option. Really easy to install a plugin that you downloaded from the internet.

I’ll install more plugins after getting the lay of the land.


The VS Code getting started is good. I like that it includes the keyboard shortcuts for opening the command palette.

  • shift+command+P = mac
  • shift+ctrl+P = windows

It was harder to find the windows keyboard shortcuts than expected. The website help “knows” I’m on a Mac so tells me about the Mac ones. But I’m going to be helping students on multiple operating systems. (It was clear in the FIRST robotics docs, but I would have liked this to be clear on the Microsoft website as well)

Creating a first project

I used the WPI wizard to create a new project. It was easy to use and fast. The file structure is standard for a Gradle project so it felt familiar. I opened the file and tried to make a change. Then VS Code started “downloading the internet.” This is also normal for Gradle. I was just expecting it to happen on file creation or first build rather than when I pressed ctrl+space for autocomplete.

I like that you can use the command palette to run commands without having to use the mouse or memorize a lot of keyboard shortcuts.

Playing a little

Many of the keyboard shortcuts are standard so autocomplete and closing tabs works as expected. If a file has warnings it (and the package name) are in green. Similarly, errors are in red. I imagine this is customizable if someone is red/green colorblind. I’m surprised the defaults are ones where this is a problem.

How to open multiple projects

I immediately wanted to compare two projects in the same workspace. This is easy. You go to file > add folder to workspace. This creates a “multi root” project.


building motion profile generator with gradle and/or eclipse

Last year, I blogged about how to build Smart Dashboard with Gradle for FRC. Today, a student asked me how to build Motion Profile Generator using gradle. It’s similar, but seemed like a good time to update the post for this specific project.

You can use pure command line when reading/following this. Alternatively, you can use Eclipse as little or as much as you like. I include the Eclipse “gotchas.” (Spoiler: It’s faster to just use the command line)

Pulling from git

You can pull the code from git in any way you’d like. Common ways are:

  • From the command line (or git bash): git clone
  • From Eclipse, go to the git perspective, and paste in the URL.
  • Download the project from github as a zip file. (Please don’t choose this option. It is better to use git properly. The only reason I’ve ever done the zip option is if I need to look at a code on a computer where I can’t install anything.)

Running Gradle at the command line

The discussion was centered around building Motion Profile Generator. If you aren’t involved with a FIRST Robotics Competition team, this is used to help with autonomous programming. As with many Gradle projects, the project comes with Gradle right in the project. So all you have to is:

  1. cd to directory you cloned Motion Profile Generator in
  2. chmod 700 gradlew
  3. ./gradlew build

Make sure you have internet before running this the first time. If you want to build directly from Eclipse, see my Eclipse Gradle post and skip to the BuildShip section.

Where is the output when building SmartDashboard?

Running gradle creates a build directory. You can look at it on the file system. Or if you are using Eclipse,

  1. Configure the filters so show the Gradle build folder
  2. Add/remove the JRE library as described here to get rid of the Eclipse errors about access restrictions.
  3. Hit refresh before looking for it.

I don’t care how gradle works, I just want to run the program!

No  worries. Just:

  1. cd build/libs
  2. java -jar Motion_Profile_Generator-v3.0.0.jar

Ok now I’m curious, what gets generated?

This build directory  contains a number of things:

  • distributions – a zipped up and tarred up version of Motion Profile Generator which includes the jar file, all need dependencies and the script to kick it off.
  • classes – the compiled .class files
  • libs – a jar file with the compiled code in this project
  • resources – the JavaFX file (user interface files)
  • scripts – to launch Motion Profile Generator
  • tmp – would you really expect to find something important in a directory named tmp?

What does the Gradle build file do?
Gradle is a build tool. The build.gradle file in Motion Profile Generator contains Groovy code that declares what the build should do. Both Gradle and Maven follow “convention over configuration” which means that a lot is implied! I went over most (but not all) of this out loud in the classroom.

A plugin is like a helper tool that Gradle is going to use in order to build. For example, ‘java’ is going to compile among other things.  Most of these plugins are in common use. Gradle needs to download files in order to run. This includes some default plugins. These files are hosted in a repository for binary files. A really common one is Maven Central. This is used by both Maven and Gradle builds to obtain binaries. This build file is really simple. It says that Gradle needs to know how to build a standalone java application.

plugins {
    id 'application'
    id 'java'

This tells Java to put some information in the manifest. In particular, which class should run automatically when you try to run the jar. It also includes a version number for reference.

mainClassName = "com.mammen.main.Main"
version = "v3.0.0"

Remember the convention over configuration thing I mentioned earlier? Convention says the source code is in the nested directories src/main/java. This project decided to put the source code directly in the src directory. Therefore the project needs to inform Gradle of this non-standard location.

sourceSets { {
        srcDirs = ['src']; include '**/*.java'

    main.resources {
        srcDirs = ['src']; exclude '**/*.java'

Normally, Gradle projects include references to dependencies on the internet. This project decided to supply them directly in a lib directory. Again, a non-standard thing to inform Gradle about. (I think this decision is because Pathfinder has extra files)

dependencies {
    compile fileTree(dir: 'lib', include: '*.jar')

Next the script specifies that we should create a jar file and an uber jar file including the special files..

jar {
    from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    // Set up manifest to point the main class to the right class.
    manifest {
        attributes 'Main-Class': mainClassName
        attributes 'Version': version
	from ("lib/native_libs") {
		into ("")

The end! The very last thing is to declare which version of Gradle this entire script should be run with.

task wrapper(type: Wrapper) {
    gradleVersion = '3.3'

Output from building in gradle

I’m including the output from a “good” run in case you have problems and want to compare. This is for the first time you run it. After that the download steps won’t be in the output and it will run much faster.

JeanneBrskysMBP:Motion_Profile_Generator nyjeanne$ ./gradlew build

Welcome to Gradle 4.7!

Here are the highlights of this release:
 - Incremental annotation processing
 - JDK 10 support
 - Grouped non-interactive console logs
 - Failed tests are re-run first for quicker feedback

For more details see

Starting a Gradle Daemon (subsequent builds will be faster)

> Task :compileJava
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ warning: OutputFormat is internal proprietary API and may be removed in a future release
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ warning: XMLSerializer is internal proprietary API and may be removed in a future release
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ warning: OutputFormat is internal proprietary API and may be removed in a future release
            OutputFormat format = new OutputFormat(dom);
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ warning: OutputFormat is internal proprietary API and may be removed in a future release
            OutputFormat format = new OutputFormat(dom);
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ warning: XMLSerializer is internal proprietary API and may be removed in a future release
            XMLSerializer xmlSerializer = new XMLSerializer(
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ warning: XMLSerializer is internal proprietary API and may be removed in a future release
            XMLSerializer xmlSerializer = new XMLSerializer(
Note: /Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/ui/javafx/ uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
6 warnings

6 actionable tasks: 6 executed

why i’m so proud of frc team 694 and their two cube auton this year

Two years ago, I offered a prize if the robot could score a certain number of computer vision (CV) shots. The prize was custom printed M&Ms. This year, I offered a challenge again. I’m not doing a challenge every year. The challenge needs to meet certain criteria:

  1. Significant jump in tech capabilities
  2. Significant jump in teamwork
  3. Attainable, but stretch goal
  4. I feel like it

Here’s our robot:

There were a number of factors enabling success:

  1. The team was able to set up shop in the cafeteria for about 10 days. (Chinese New Year weekend and Presidents Day week.) This allowed for building a full size half practice field including sufficient height to test. It also allowed the practice field to remain set up so time wasn’t wasted setting up every day. We would not have had such a successful autonomous routine with this.
  2. This year was the first year, FRC Team 694 StuyPulse successfully built two robots – Wildcard and Mildcard. Not only that, but the robots were pretty much identical. Having an “extra” robot allowed us to test advanced autonomous modes even after the robot was “done.” This program has a “change freeze” on working on the physical robot, but not on software.
  3. Many skilled, smart and motivated students. Even the freshmen took on significant challenges in the space of programming and engineering. This allowed us to drive straight, go the right distance, tune, etc faster than usual. In fact, a couple freshman are leading a motion profiling project!
  4. Self starters. One of the freshmen (freshwomen?) started a project to record every practice run. This replaced debates on what happened in a run with actual facts. All competition matches were recorded as well for the same reason.
  5. Never giving up. I’m big on valuing this. The students worked on and succeeded at things that I thought were impossible.
  6. Communication was the best I’ve ever seen. Much more communication was on Slack (in a place mentors could see) than ever before. Different departments of the team communicated well throughout the season.

I’m particularly pleased that some of the contributions to our success this year came from some of the younger members of the team. This means that we get to advance even more next year. Go StuyPulse!

On to the prize. This was better than the CV year so I wanted to bring in something nicer. It needed to portable and have a low cost per unit (I needed a few hundred.) And ideally it would be wrapped. I decided on 30 mini chocolates each saying:

Congrats Team 694. Two identical working robots and two cub auton. What a year!

(two cube auton means scoring a game element, acquiring another and then scoring that one)

I also did a random draw for “nicer prizes”. (ex: my championships field pin and t-shirt). To enter the random draw, students had to say how they contributed. I got a nice range of replies including:

  • Helped with robot and field reset as well as carpet duty, so the autons could be tested more quickly
  • helped wire the bots and came to every meeting to retrieve batteries for auton testing
  • I filmed our tests so that we could rewatch them and learn what went well.
  • I helped wire the practice bot so that SE could continue working on auton development after bag and tag.
  • I helped set up the carpet 🙂
  • helped fundraise the team to have money for a second robot! 🙂
  • built bumpers to make sure the bot was legal and could play

I picked these to share because they will make sense to someone not on the team, don’t reference specific people or inside jokes. Fun fact. Half the total entries use the word “helped”. That’s a nice teamwork word!