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 https://github.com/vannaka/Motion_Profile_Generator.git
  • 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 {
    main.java {
        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
Downloading https://services.gradle.org/distributions/gradle-4.7-bin.zip
.......................................................................

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 https://docs.gradle.org/4.7/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)

> Task :compileJava
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ProfileGenerator.java:4: warning: OutputFormat is internal proprietary API and may be removed in a future release
import com.sun.org.apache.xml.internal.serialize.OutputFormat;
                                                ^
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ProfileGenerator.java:5: warning: XMLSerializer is internal proprietary API and may be removed in a future release
import com.sun.org.apache.xml.internal.serialize.XMLSerializer;
                                                ^
/Users/nyjeanne/git/Motion_Profile_Generator/src/com/mammen/main/ProfileGenerator.java:435: 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/ProfileGenerator.java:435: 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/ProfileGenerator.java:439: 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/ProfileGenerator.java:439: 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/MainUIController.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
6 warnings

BUILD SUCCESSFUL in 24s
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!

using eclipse launch configurations to deploy FRC robot code faster in eclipse

I use Eclipse launch configurations at work and coding at home all the time. It never occurred to me to mention them to the team until last week. A student asked “is there a way to use a keyboard shortcut to deploy.”

Before

For those not familiar with FRC (FIRST Robotics Challenge), the deployment procedure is:

  1. Select the project in your workspace.
  2. Click “Run”
  3. Mouse over “Run As”
  4. Click “WPILib Java Deploy”

This kicks off the Ant build to do the deploy. Certainly not a terrible process. But when you do this dozens of times and in a rush, it can feel tedious. I think that’s why I never suggested it. At the lab, I ensure the students always drive at the keyboard. So I never have to click four things to deploy and it doesn’t feel tedious. Whereas when I’m coding myself, I feel it and optimize my time/clicking.

Setting up a launch configuration

The first thing I did was show how to set up and favorite a launch configuration.

The initial setup:

  1. Run a build the “long way”
  2. “Run” > “External Tools” > “External Tools Configuration…”
  3. Click build.xml or build.xml (1) or whatever you see in the list. Confirm it is for this year’s robot. (You may find it easier to select all the build.* configurations, delete them and then run one new build.)
  4. Change the name to one that you like. For example, “2018 Robot”
  5. Click the “Common” tab
  6. Click “Display in Favorites Menu”
  7. Click “Apply”

Then to run it, you just click the triangle next to the launcher and it is stickied first in the list. (Be sure to click the triangle next to the green arrow with the red box. There’s also one without the red box which is used for running Java command line programs.)

This gets us down to two mouse clicks. But it is still not a keyboard shortcut; the initial request.

Keyboard shortcut

I had to look this up, but you can provide a keyboard shortcut. Sort of. I couldn’t figure out how to create a keyboard mapping to a specific run configuration. But that doesn’t matter here. We want to map to the last run configuration.

  1. Open the Eclipse preferences. (The Eclipse menu on a Mac and the Window menu otherwise)
  2. “General” > “Editor” > “Keys”
  3. Type “Run last” in the filter to find the matching entry
  4. Setup a binding. I chose command F + command R. (The beginning of spelling out FRC), but you can choose anything.
  5. note that the contest/when is “in windows”.  This means the shortcut is avilable when you have any file open. Just when you want when looking at or making robot code better.