4265 2021 Robot and Shifting Swerve Reveal

Team 4265 The Secret City Wildbots is proud to present our new two-speed swerve design and 2021 robot “Mando". Check out our reveal video:

At the beginning of the season we decided to make a new robot that is optimized for both the Infinite Recharge at Home challenges (hyperdrive, galactic search, and autonav) and as a technology development platform for future seasons. Mando is 24” x 24” x 25” and weighs 70.5 pounds.

2021 Robot Renter GIF

The defining aspect of our robot is its drivetrain – a two-speed swerve drive. We began our venture into swerve drives in the 2019 offseason, and machined modified mk.2 modules to fit our custom 5” pneumatic wheels. After having promising results at the 2020 Arkansas regional, which we were lucky enough to attend, and with a lot of time on our hands, we decided to continue to innovate on our swerve modules, implementing a shifting mechanism after three design iterations. The current design has free speeds of 8.38 ft/s in low gear, and 22.85 ft/s in high gear and a max empirical ground speed of 20.9 ft/s. The inspiration from 2910’s mk.2 modules is still clear; however, only the main pulley remains completely unmodified from the original mk.2 design in an attempt to reduce manufacturing time. Similarly, the modules use the same custom wheels and wheel mounts as our 2020 swerve, and are still compatible with mk.2 wheels and wheel mounts. The total module dimensions are 6.25” x 6.25” x 11.2”.

Shifting Swerve GIF

Sensor and Code integration:
Our swerve drive automatically handles failures and calibrations. If an azimuth module fails, we switch the motor to coast mode, disable the drive motor for the affected module, and remove the module from the robot pose calculations. To prevent the swerve modules from opposing each other, we slow down any module that is going against the others. We also can easily correct misaligned swerve modules by zeroing and recalibrating them from the dashboard (we are still working on integrating new absolute encoders to handle brown-out situations). Additionally, we assist the driver by locking the robot’s orientation at high speeds, which prevents the robot from drifting and helps when they go under the control panel. We also automatically control whether the swerve drive is in robot-oriented or field-oriented mode based on driver inputs and emergency overrides. Finally, we use customizable driver profiles so each driver can have personalized settings.

Each module shifts independently. We use 2 photointerrupters on each module to determine the real shifter state the robot is in and compare this state to our requested shifter state. Using this information, we can determine whether the robot is in high or low gear so that we can use the correct conversion factors. We can also compare the requested and actual shifter states to know when we are transitioning between gears, stutter the shifter if it gets stuck while transitioning, and detect any shifter failures. To estimate our pose, we fuse the sensor readings from the Falcon encoders, IMU, and Limelight. The pose is also used to latch the azimuth angles during deceleration to prevent the robot tipping from at high speeds.

We learned in the 2020 season some of the difficulties associated with fitting a full-width intake on a swerve drive, especially with limited drive tube space. This year we explored a four-bar design, allowing the intake to retract over the front modules and prevent balls from coming out the front of the robot. We have three powered 2” rollers and a smaller passive 0.625” roller above the top roller to block balls from being ejected out of the robot by the intake. The intake is powered by a Falcon 500 with a 5:1 Versa-Planetary gearbox with the bottom roller having an additional 1.5:1 pulley ratio to help pick up balls from the floor before being run over by the robot.

Robot reveal made by:
Adam, Alex, Amelie, Henri, Julianna, Tyler


Wow! One of the best 2021 robots I’ve seen so far. The trajectory tracking that you’re using look very interesting. Is there a GitHub repository where we can look at or something?

1 Like

We’re still working on cleaning up our code, but here are our current releases: Releases · secret-city-wildbots/2021-Skillz-Robot · GitHub

Here is our Autonomous Path Planner too: Releases · secret-city-wildbots/AutonomousPathPlanner · GitHub


Those shifting modules are really cool! Where did you buy the 5” tires and tubes from?


I don’t know if these are the exact wheels we ordered, but they are 125mm skate wheels like these:

1 Like


Still really cool though, that robot goes fast.


Our swerve drive automatically handles failures and calibrations. If an azimuth module fails, we switch the motor to coast mode, disable the drive motor for the affected module, and remove the module from the robot pose calculations.|

This is so cool! Can you describe a bit about how you’re doing this automatic fault detection and recovery?

1 Like

Any pictures or additional info on the custom 5” wheels?

1 Like

Of course. The wheel is machined in two parts, one being this part, which the wheel can be slid into.

Then the second part, a plate, is bolted to the primary hub to keep the wheel fully captured.

*This is an older version, instead of bolting all the way through the wheels, we now tap the bolt holes and have bolts on both sides of the bevel gear and the plate. We also now machine a slot for the valve stem to sit in so it doesn’t hit the wheel mounts.


This is super exciting. Lots of details to explore.

I’m really curious about this.

When you say the azimuth module “fails” what failure modes are you specifically considering. Three that come to mind are 1) steering motor fails such as becoming unplugged but the module position is still known from the absolute encoder, 2) steering geartrain fails such that motor inputs don’t spin the module, but the module position is still known from the absolute encoder 3) absolute encoder fails and the module position is unknown.

In all 3 cases (from our experience) if you continue driving, you will be dragging the “dead” wheel sideways across the carpet if you try to drive in a direction that the wheel is not pointed. Switching to coast mode is good if the robot is trying to move in a direction that is aligned or nearly aligned with the dead wheel. But coast mode alone is not going to allow the wheel to caster into alignment, so most of the general motions of the robot will still be dragging the wheel most of the time.

However, in cases 1 and 2 where the module position is still known, you can, in theory, change the swerve code to only allow motions (rotation and translations) that can be accommodated with the direction that the wheel is already pointed. You can pivot around the dead wheel to rotate and then drive in both the forward and backward directions that the dead wheel is pointed in as well as any curved paths that are allowed given the pointing angle of the wheel. We have thought several times about trying to do that, but have never mustered up the spare time to dedicate to that problem.

I’m curious if this is what you have done or if you had something else in mind for the azimuth failures.

1 Like

A little bit more about our module failure detection:

For general module failures: We detect an azimuth fault if the error from the goal is over a threshold for a certain amount of time (if the sensor is unplugged or a gearbox failure). When this occurs, we disable the power to the module, force to coast so the module won’t be opposing the other working modules, and remove this module’s odometry from our pose calculations. This allows us to continue driving with only 3 modules for the remainder of the match. We are also using the thermocouples on the Falcons to detect if one of the motors is overheating. As of right now, we do not have an absolute encoder, but we are working on implementing this to allow us to handle brown-out situations and to detect a separate azimuth sensor failure by comparing the two encoder readings. We detect these errors individually for each module and have indicators on our driver station so we know which module caused the error.

For shifter failures: We compare the real shifter state (determined with the 2 photointerrupters on each module) with the requested shifter state (what the robot wants to be in). If these states don’t match for a certain time threshold, we stutter the shifter to try to get the piston to engage, and if that doesn’t fix the problem, we detect a shifter failure. If we have a shifter failure on a module, we force the modules to low gear.


I love the robot and the control system! I am curious about your pure pursuit, though – do you use a small-radius pure pursuit to follow the generated path, and then a separate controller for turning?

Thank you so much!

Im really curious on how the shifting mechanism works. (how it runs and everything), is it one before the contact bearing?

Do y’all plan on putting out the cad?

The shifting mechanism is a simple lever linkage with a pivot in the center:
Low Gear:

High Gear:

We are using these plastic clevis joints for the pivots. The linkage bar is manufactured and the photo interrupter stack and flag are 3d printed.

As far as putting out CAD we are not sure if we will be making another iteration on the design during the offseason implementing some of the things we have learned from actually assembling and running the modules for the first time on the robot. Either way CAD will certainly be up before the 2022 season begins.


Did you have any issues with the joints needing to swing out through the rotation of the lever? Do you just handle that by leaving enough play in the system?


On a philosophical level I wonder if what we are doing is really still “pure” enough to be considered “pure pursuit” haha, but that aside I’ll try to give an overview. Essentially it is a feed-forward path follower with a feed-back pure pursuit controller running on top of it:

  1. First, we generate a smooth path using a custom path planner. This computes smooth velocity profiles and does some basic acceleration limiting but we haven’t explored curvature related things yet.
  2. Based on the robot’s pose, we identify the closest smooth point on the path within our search window (which we prevent from ever extending backwards, effectively preventing the robot from traveling backwards along the path).
  3. Based on this closest point we grab the following information:
    a. Distance along the path from the start.
    b. Distance along the path from the end.
    c. The feed-forward velocity magnitude.
    d. The feed-forward velocity angle (for us this is essentially the pointing direction for our swerve modules).
    e. The robot heading goal (for us this is an independent degree of freedom).
  4. We then identify our look-ahead point, this is where the robot should be at any given time and is used to calculate the error used by the feed-back controller. The look-ahead point is defined as either the smooth point that is the look-ahead time away from our current position, or the “chase” point, whichever is closer to us and assuming neither are behind us. Where the chase point is where the robot should currently be located along the path based completely on the feed-forward values generated by the path planner. This (a) compensates for us drifting off of the path due to imperfections in the feed-forward controller and (b) keeps us moving along the path when we stop to touch points like in the bounce path.
  5. Once we have this look-ahead point we grab the following information:
    a. Distance error from the current pose to the look-ahead point.
    b. Pointing angle from the current pose to the look-ahead point (for us this is essentially the pointing direction for our swerve modules).
  6. Next, we have to do some conversions. The feed-forward velocity is in inches/s from the path planner and must be converted to our standardized non-dimensional drive command [0,1] based on the maximum ground velocity we can achieve. The distance error is in inches, and is “converted” into a non-dimensional drive command [0,1] by the PID controller. The independent heading error is “converted” from degrees to a non-dimensional rotation command [-1,1] by another PID controller.
  7. The feed-forward and feed-back drive commands are broken into their vector components using the feed-forward velocity angle and the feed-back pointing angle, respectively. They are then summed and the result is field-centric X and Y drive commands.
  8. These drive and rotation commands get passed to all of our TeleOp swerve commands. Downstream we are running in voltage compensation mode on the Falcons during auto and applying another linearizing feed-forward controller to convert the non-dimensional motor commands [-1,1] to non-dimensional motor power commands [-1,1] which scale linearly with motor RPM.

Let me know if you have any other questions!


The pivot bar is slotted on the side of the piston but is just a simple hole on the side of the shifter rod. This is because the shifter rod has a lot of wiggle inside of the shifter shaft, so when we slotted it the shifting became inconsistent as the joint would just slide back and forth in the slot due to in not being constrained concentrically to the shifter shaft. The hole instead of the slot at least makes the action consistent although technically we are pulling the shifter rod slightly out of concentricity. Hopefully that makes sense.


@ClayTownR has seen this before XD

1 Like

It’s a bit late now – but thank you so much for your reply! Nice to hear about the complexity of what you all are using.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.