FRC 6328 Mechanical Advantage 2022 Build Thread

Glad to hear that it’s working well for you! I don’t any specific recommendations for Raspbian, but here’s what we do for auto start if it’s at all useful. Our setup uses Xfce, which has a convenient graphical interface for setting startup application/scripts through the settings pane. We also configure LightDM to automatically log in at the correct user. The Xfce login script looks something like this (I don’t have the actual script on hand ATM). We run the main script in a terminal window just for ease of debugging.

exo-open --launch TerminalEmulator "source AdvantageTrack/venv/bin/activate; python AdvantageTrack/"
firefox -url "" &

we’ve been trying to Run AdvantageTrack the past month or so. After some initial success, we seem to be hitting some snags

  1. the application seems to not be signing some folks in or out anymore, and is very slow (to be fair we have about 120 people on our Config-People page).
  2. We sometimes get a “RATE_LIMIT_EXCEEDED” warning, which you’d think is related to why I can’t sign people in and out, but is not.

I don’t think it’s from my general config settings, but maybe it is:

We’re currently running off of a raspberry pi, and I have the timeout so long because the network doesn’t have a good connection for kids in the machine shop. I’m thinking I’m going to basically remove the auto-sign in capability (increase the ping delay, and delete data from the data - devices tab) and also try to run it off of a laptop instead of a raspberry pi to see if that helps, but if there are any other suggestions I’d like to hear them.

I tried to request a higher quota limit, but had issues doing that and I don’t think that should be necessary anyway.

1 Like

I’ll throw out a few things if they’re useful for reference; we run AdvantageTrack off of an Intel NUC with some variant of a core i3, and it’s connected over WiFi. We have 125 people registered (67 active) and 110 devices. Based on that, I don’t see any immediate issues with your setup. Just a couple of questions:

You say that some folks can’t sign in or out. Does that apply to everyone or just some people? If it’s everyone, that suggests there’s a problem with the Google Sheets connection. For example, corrupted data in the sheet could have a that effect. I’d start by comparing your copy to the template sheet in case anything was changed accidentally (headers, extra blank rows, etc). You might also try linking a blank copy of the template, adding a few people, and seeing if you have the same problems.

What makes you say that the “RATE_LIMIT_EXCEEDED” error is unrelated to the other problems? What have you observed the triggers to be? If the system tries to sign someone out automatically and fails, it will repeat it periodically on every ping cycle. I know we’ve hit the rate limit before when 10+ people get stuck in a similar loop. Is there any evidence of that in the console log?

You’re correct that you shouldn’t need to use a higher rate limit. If it’s useful, these lines define the times (in seconds past the minute) that various periodic reads from Google occur. You could try decreasing the frequency, though if it’s stuck in a loop as I described then this may not change much.


The main reason I say it’s not related is because when we are getting the Rate limit Exceeded error it’s clear that the google sheets connection is down. There are times that we don’t get that error for extended periods of times and we still have trouble logging people in and out. I guess in reality that does not mean it’s not related.

Is the best way to manually log people out and “disable” the auto-sign in to just delete some of the data-devices rows and data - records rows?

EDIT: something else that is also then likely related is that we don’t have the wifi enabled all the time. Knowing now it can get in a loop trying to sign people out and exceed a rate that way, I bet the wifi going out is probably a potential root cause of that. For reference, our meetings are from 5-8 on weds and 1-6 on Saturday, but the wifi is on from 4 PM weds - 5 am thurs, and then Saturday morning through Sunday night. So I would still think that it signs everyone out during that time, but could see those things being related

1 Like

That should work, especially if you just want to disable it for some people. You can also change this line in the script to turn off the network monitoring entirely:


If you can’t beat em, join em

During this offseason we have been busy with a bunch of training programs, as well as developing our new swerve test bench, affectionately named “Crab Bot.” We opted to use SDS MK4i L2 Modules with in-corner mounting and Neo Motors. The CAD for this test bench can be found here. It will be battle tested at The New England Robotics Derby this weekend. We plan to continue with these modules going into next season, game permitting.

We also have a reveal video for this robot which can be found below:

Many thanks to the following groups:

SDS - For making some awesome and robust modules
FRC 3467 - For the climber in a box
FRC 4909 - For allowing us to bring it to an event before next season
All the swerve teams that beat us on Einstein

If you have any questions about the robot, please ask here, or shoot me a PM. There’s a software post being cooked up.

Looking forward to moving sideways for the foreseeable future.


Software Update #11: Learning to Crabwalk

No crab is complete without its code. Or something like that. We’ve been working on swerve code since early August as part of our offseason training for software, which means that a good chunk of this code was created by some of our newest students. Thank you to everyone on 6328 who dedicated their time to this project!

The Basics

All of the code is in our SwerveDevelopment repository on GitHub (the drive subsystem is here). The code structure closely resembles our 2022 competition code, including full integration with AdvantageKit. This means that the hardware interface for each subsystem is separated from the control logic, allowing us to accurately replay matches using the WPILib simulator or seamless switch to a physics simulation (more on that below).

The swerve support uses WPILib’s built-in kinematics for most functions with feedforward/feedback controllers running on the RIO. We chose to bypass the onboard controllers on the SparkMaxs for a variety of reasons — this simplifies the code running the controllers (no need to artificially wrap turn setpoints), it makes it easier to run with simulated modules, and we can use our new derived velocity controller for the drive motors (see the section below for details on that). We haven’t observed any performance issues with running the controllers on the RIO.

Odometry is one area where we deviate slightly from WPILib’s built-in kinematics. The supported approach for 2022 has been to update odometry based on the velocities of the modules (running the kinematics in the reverse direction of when driving the robot). Instead, we’re using the position delta of each wheel, which reduces the amount of drift over extended periods. Our odometry code is here — we just use the kinematics object but feed it a position delta instead of a velocity, then modify our pose using a Twist2d. I believe WPILib is planning to make position delta odometry the default for next year.

Enough babbling! Here’s a video of the code in action, comparing a video to the odometry and module states. The red arrows show the measured states and the blue arrows show the setpoints.

Generating a feedforward model and tuning the controllers is especially important for swerve, and we have a couple of tools we’ve developed to help with that:

  • We rely heavily on our TunableNumber class for values like FF and PID gains. These values act like constants when running on the field, but can be manipulated using NetworkTables when the robot is running in tuning mode.
  • Last year, we wrote a FeedForwardCharacterization command that generates values for kS and kV using a the same technique as SysId’s quasistatic tests. Integrating this function into our code allows us to recharacterize quickly without needing to configure SysId and deploy new code. It also means…
  • We can run the characterization routine on the drive motors by just controlling the turn motors to zero degrees. No need to use blocks or rely on brake mode for the turning motors. Our drive subsystem has a characterization mode to support this use case.

Trajectory Following

Our preference has always been to define trajectories in code using transformations (rather than relying on a GUI tool). Last year, we created a FieldConstants class that defined lots of useful reference points on the field:

All of our trajectory waypoints were defined relative to these reference points (example). Defining these waypoints in code also allowed us to extensively reuse waypoints rather than redefine full trajectories for increasingly complex autos. You can see that in action with our five cargo auto, which uses waypoints from our two, three, and four cargo autos (code here).

We wanted to continue defining trajectories in code for swerve, but WPILib’s tools don’t provide a complete solution for controlling the holonomic rotation along a path. We created our own set of trajectory classes for swerve to address this issue, which can be found here. Let’s look at an example trajectory definition:

CustomTrajectoryGenerator.generate(config, List.of(
    new Waypoint(new Translation2d(0.0, 0.0), null, Rotation2d.fromDegrees(90.0)),
    new Waypoint(new Translation2d(2.0, 3.0), Rotation2d.fromDegrees(90.0), Rotation2d.fromDegrees(-90.0)),
    new Waypoint(new Translation2d(2.0, 6.0), null, null)

Each waypoint has three components defined in the constructor — a translation (required), a drive/velocity rotation (optional), and a holonomic rotation (optional). Since both rotations are optional at every waypoint, the generator will automatically combine quintic and cubic splines for the drive path, then use an S curve for the holonomic rotation. We also have shortcuts for generating waypoints based on poses. For example, moving from one pose to another on swerve (following a straight line) looks like this:

CustomTrajectoryGenerator.generate(config, List.of(

Our CustomHolonomicDriveController can follow these generated trajectories, including correctly handling the holonomic rotation feedforward. Here are some key examples from our swerve code:

  • Setting up the config and generating the trajectory (here)
  • Running the drive controller (here)
  • An auto routine using our trajectory following command (here)

You can see the trajectory follower in action at the end of this video:


Last year we relied very heavily on simulation to test drive code, auto routines, driver assist features, and more. We knew we wanted to support this on swerve, but creating a full swerve simulation becomes complicated very quickly. Instead, we opted for the simpler approach of independently simulating each drive and turn motor using the FlywheelSim class. With the hardware interaction separated from the drive subsystem, enabling the simulator is as simple as swapping our ModuleIOSparkMAX implementation for ModuleIOSim.

Another problem we needed to solve was simulating the gyro sensor. The angular velocity of the robot can be calculated using the measured module states (the outputs of the module sims) and applied to the pose, but this approach is suboptimal on the real robot. In that case, we want to rely on the gyro because it’s more accurate over long periods. We set up the odometry system to automatically switch between these two approaches depending on whether a gyro is connected (code here). The sim simply doesn’t provide a gyro hardware implementation, meaning the “disconnected” case is used. A nice side effect is that we have a fallback if the gyro is ever disconnected on the real robot.

This system works very well to check that the drive and turn controllers are behaving correctly. It can even approximate some more “complex” behaviors like realistic acceleration (making this work mostly involved adjusting the flywheel sim parameters until the results looked reasonable). Ultimately, we feel that this approach achieves everything we require of the simulator despite not being physically accurate.

Here’s a video of a five cargo auto running in the simulator:

Derived Velocity

While we have generally found great success with the SparkMax/NEO ecosystem, the fixed velocity filtering on the internal encoders has been a distinct low point. For those unaware, the SparkMax filters the velocity measurements from the internal encoders, resulting in a ~100ms delay in readings. This makes it more difficult to tune aggressive feedback controllers. While we’ve been able to work around this with well calibrated feed forward models, eliminating the latency would make it much easier to tune the velocity controllers for mechanisms like flywheels and drivetrains. We created a class that replaces the built-in PID controller on the SparkMax and eliminates this measurement latency:

You can find the code here: SparkMaxDerivedVelocityController

This works by running the controller on the RIO in a notifier thread while calculating the velocity based on the SparkMax’s position measurements (which are not filtered). Running that calculation requires accurately timestamping the measurements from the SparkMax (data which is not provided by REVLib), so we manually read the CAN frame for position from the SparkMax. Using a notifier allows us to run the controller faster than the loop rate of the main robot code, though for most applications a 20ms period appears to be sufficient. You can also manually adjust the level of filtering on the data, since completely unfiltered velocity data can be extremely noisy.

Here’s an example of velocity data from our swerve drive with the SparkMax’s measurements in yellow and our derived ones in blue:

We also tested this system on the flywheel for our 2022 robot. We shot two balls in succession after raising the kP value until just before it oscillated at steady state. Here’s what the internal (filtered) controller on the SparkMax did:

After the first ball, it overshoots the setpoint of 3000 RPM by several hundred RPM (blue is our derived value). The second ball is then fired with the flywheel running too fast, which could affect its trajectory. The controller overshot the setpoint because the data showing that flywheel had reached the setpoint was delayed, and so it continued to apply voltage after it should have stopped. In contrast, here’s the same test with the controller running on the RIO using our derived value:

The flywheel speed recovers perfectly after the first shot and is stable at 3000 RPM, because the controller is able to respond more quickly. You can find the implementation of this controller for our flywheel here, and (as shown before) we’re also applying it to the drive velocity controllers on our swerve bot.

Feel free to reach out with any questions, and keep an eye out for more software updates soon.




Nice work! A couple thoughts for people who want to follow suit on some of these innovations:

This was actually just merged into WPILib earlier today.

PathPlanner seems to have in-code generation in the new beta. I haven’t tried it yet, but it seems like you have a more fleshed-out API.

Did you run into any thread-safety or other pitfalls with this system? Would they be eradicated if the code was run in the regular robotPeriodic loop?


Seems like the relevant bits are the generatePath method and the PathPoint class. It’s definitely a nice option, though it seems to lack some features like optional rotations (very nice when we don’t want to optimize everything by hand) and advanced constraints (our API uses WPILib’s trajectory config/constraints, which are quite flexible).

The class is written to be thread-safe using synchronized blocks, and we haven’t encountered any issues there. The main thing to keep an eye on is CAN utilization if it’s configured to use a very short period (the period for status frame 2 is updated to match the controller period, though it only contains the position value). The default rate for that status frame is 20ms anyway, and we haven’t observed any issues running it on four motors for swerve.

1 Like

How did you get your FlywheelSim constants, particulary for the turn motor? Did you just characterize the values using WPILib’s SysId or did you use a different method?


The gearbox and gearing values (the first two constructor options) are known based on the hardware, so they don’t require tuning. The moment of inertia (the last argument) is trickier because we’re trying to roughly simulate the dynamics of an entire drivetrain — for example, using the theoretical moment of inertia for just the drive wheel would result in wildly unrealistic behavior. Our approach was to tune the moment of inertia values manually until the controllers could converge in a “reasonable” length of time during sudden acceleration (a fraction of a second for the turn motor and roughly a second for the drive motor). You might be able to calculate those values based on the physics of the drivetrain, but we didn’t bother because this simplified simulator is only meant to be a rough estimate in the first place.


As a founding member of the Open Alliance, 6328 strives to be transparent about our decisions. At this time, given the discussions in the community regarding IFI and VEX, we are of the opinion that the IFI Executive Leadership and the IFI workplace environment is not consistent with the values and beliefs of our team. As such, for future designs and purchases we will choose to direct our business towards companies we believe align better with our values and beliefs.

We may continue to use Vex products we already have in stock, as Vex has already profited from their sale whether we use them or not.

We will not judge or make competition decisions based on other teams’ use (or non-use) of Vex products. We recognize that each team’s situation is different and many factors are involved in choosing what components are used.

As always, feel free to ask any questions and we’d be happy to answer them.


Could you clarify your turning motor control system? With the sparkmaxes you talk about recoding the pidcontroller, so does this mean you are not doing calculations on the roborio? What is your feedback device?


For turning, we’re using the Thrifty Bot absolute encoders connected directly to the RIO. The control loops are running on the RIO, and we haven’t found any performance issues doing so.

To clarify, our derived velocity controller works around the latency in the SparkMax’s velocity measurements for the drive motors. It works by calculating the velocity and running the control loop on the RIO. We don’t use the derived velocity controllers for the turn motors because a) we’re controlling position, not velocity and b) we’re using external encoders anyway.


jonah, Impressive system…Another question. Once i download the code from github.
Execute from VSCODE or WPILIB software ?
What extensions are necessary to make the simulator workable. Sorry for the basic questions.
Thanks Fordraiders

1 Like

All of the robot code works with a standard WPILib installation (instructions here). It creates a separate VSCode copy with everything installed for WPILib, which you can use to launch the simulator. AdvantageScope is our viewer application that can connect to simulated robot code, and it’s a separate app download (here).


just out curiosity - what were your driver assist features?

1 Like

Our driver assistance features were pretty modest last year, but the key ones were auto aim based on odometry (so it worked from any direction) and automatically setting the flywheel speed (again based on odometry). We also created a feature to guide the driver on a smooth path to the nearest fender, which we determined to be helpful on the opposite side of the field — this was an older iteration of the robot with only two shooting positions. More details and a video here:

We opted not to use the fender align in competition because our odometry data wasn’t reliable enough between target detections (with the camera pointed in a fixed direction, we often had long periods with no vision updates). Our hope for next season is that AprilTag tracking can increase our odometry reliability such that these sorts of advanced driver assistance features are more viable. We have some early ideas and prototypes, but ultimately those features are extremely game dependent. As we make progress in this area, we’ll definitely be posting about it in our 2023 build thread.


Some Final Notes

2022 has been an incredibly successful year for us and we are very grateful both for the experience and to have had the opportunity to document it here. To all those who have given feedback or just shared things we did, Thank You. We try to read everything people have to say and make changes to what we share to better fit what y’all want to see. If you have feedback about how we did or how we can improve, feel free to shoot me a PM and it’ll get to the right people. All input is very much appreciated.

Here is a collection of our recaps from this past year, since many of them weren’t posted in the thread:

Greater Boston Recap
Season Recap
Season Bloopers
Battlecry Recap
Duck Bot Reveal
Summer Heat Recap
Mayhem in Merrimack Recap
Swerve Bot Reveal

I also want to give huge Thank You to the following people/groups who made this season possible. (This isn’t everyone who positively impacted us; that list would be as long as the rest of this thread combined. This list is not sorted.)

Shelby Anderson (@ShelbyA)
Karthik Kanagasabapathy (@Karthik)
Michael Corsetto (@Michael_Corsetto)
Justin Tervay (@jtrv)
Saikiran Ramanan (@saikiranra)
Michael Fantom
Team 1100
Team 2168
Team 2713
Team 3467
FIRST Updates Now (@Tyler_Olds)
Dunkin Donuts
All of our fellow Open Alliance members
      Special shoutout to 3847, 95, 1339, and 4481
All of our alliance partners
      Special shoutout to our worlds alliance partners in 5940, 2471, and 3534
All of our sponsors
      Special shoutout to Patriot Beverages, who provides our build space
All our team parents
      Special shoutout to the 6328 Mom Squad
The Bazel Authors

Looking forward to 2023, I’m sick of launching spheres.



We’re lucky that you guys came to Chezy in 2021 and got to connect with the students and coaches on 1678. Ya’ll built a great robot in 2022 and your run to Einstein was truly epic. Looking forward to following your progress in 2023 and hope to see you again at Champs!