We’ve been slacking, and we apologize. We’re a rapidly changing team that is currently maxing out our bandwidth on the robot.
We settled on swerve rather quickly, on day 2 of build. We looked at the field and the only reason that we shouldn’t do swerve that we could find was the cable protector, which we don’t believe will be detrimental to it. Additionally with how cramped the line-up process is in the community, on top of the cramping in the human player station area, we settled on swerve, with the MK4i modules we already had on hand.
We evaluated the two module configs for the MK4i - standard and high-clearance. Due to the way we’re mounting the elevator above the chassis, we aren’t able to lift the modules up and out of the chassis, as the elevator prevents it. Because of this, we opted for the high-clearance config, which allows us to drop the modules out the bottom of the chassis without interference.
We wanted to go as small as possible without jeopardizing our center of gravity - 24" or 25" felt a bit too small due to a likely higher CG this year than last, and 26" square felt “just right.” This is also the maximum size you can be if you want to fit 3 robots on the bridge, but with swerve you can simply strafe your bumpers off the edge for the couple extra inches you’ll need to make sure robots aren’t accidentally pushing against each other while trying to balance.
Pictured are a simple top guard (mostly to prevent grease from flying all over), a Spectrum Corner™, and some crush blocks to help us not crush the tube while we’re fastening the modules into place. These are all PLA+ parts. We’re running the L3 on NEOs.
The higher config does raise the belly pan, and thus the CG, though - we are already concerned about CG due to everything above the drivetrain, so we want to keep the CG as low as possible. Due to this and our sheet metal sponsor’s availability, we created the belly pot.
The belly pot rivets to the bottom of our drive rails, and lowers everything on it (battery, PDH, sparks, etc) by an additional 1.75 inches. This is currently a single piece of aluminum, but it’s not difficult to transform this into a 5-piece set of 4x aluminum brackets and 1x stainless steel belly pan if we need an even lower CG (and have the weight for it). Always have a backup plan.
We’ve laid out the electronics in such a way to minimize cable runs as best we can. We are using the VRM to power both our radio and our network switch, rather than using the REV Radio Power Module plus a Polulu regulator. The VRM is just easier for our use case. Hopefully the radio has more ports in the future. Pictured sparks are for our swerve modules plus our elevator.
We’ve decided on a continuous (3/16” Dyneema) rigged elevator powered by 2 NEOs at ~5:1. The elevator is mounted at a 55 degree angle. The mounting for this is a rather difficult packaging problem, which is why we are using the Spectrum Corners to allow us to rivet plates to the outside of the drive rails.
We’re using some additional 2x1 to brace the upper parts of the elevator. As of now we plan on routing the wires connecting to the carriage through these 2x1’s. It’s possible we’ll mount a vision camera up here as well, but that’s still to-be-finalized, and may wind up near the belly pan. The rigging here goes both inside and outside the tubes, and is very similar to 1323 2019. We also opted for using 1x1 tubing as opposed to 2x1 for the top and bottom of our carriage. This will allow for our tensioning system (which will be mounted on the bottom of our carriage) to better align with our driving pulleys and prevent the Dyneema from going at too steep of an angle and potentially slipping.
Mounted to the elevator carriage is our four-bar system, which is responsible for allowing the end effector to get where it needs to be. We’ve intentionally left the four-bar-to-intake-mounting a bit abstract as we are still experimenting with intake geometry.
The sparks here are for powering both the four-bar and the end-effector. The four-bar is powered (currently) by a single NEO on a 250:1 reduction - a 100:1 planetary reduction, which powers a 16:40 RT25 belt reduction. This belt is mounted to both the four bar arms and a MAX Spline shaft, in order to power both sides on one motor. We’ve left open the possibility of adding a second motor to power the other side of the four bar, which is something we did last year and wound up saving us due to some tolerance & controls issues.
We are prioritizing modular design with the carriage-extension. Since the 4-bar/end-effector is the only part of our robot consistently extending outside of our frame-perimeter, we believe they are likely to get damaged during matches. Modularity allows us to isolate issues, replacing individual parts rather than the entire system. Last year, we ran into this issue a lot (especially with our climber) — short turn-arounds spent removing, fixing, and replacing a whole part of our robot. We hope modular design will help to prevent this.
We currently have two intakes that we are actively CADing and will manufacture. We don’t have enough signal to definitively say one is better than the other, and we have the bandwidth to design & build both, so we are going to design & build both.
On the left side, you’ll see a NEO 550 on a 45:1 reduction, with an output shaft that has both a pulley and a gear.
The pulley on the MAX Planetary output runs directly to the upper red roller. The gear runs to a separate axle, which is coaxial with another pulley, which connects to the lower red roller. This is in order to have both rollers powered by a single motor, but with inverted directions. The belt runs are all 1:1.
On the right side, you’ll see another NEO 550 on another 45:1 reduction that powers the output shaft with the 4" flex wheels on it. This is a 1:1 belt run.
The red plates on the outside are belt guards to prevent the belts from ever walking off or getting hit by another robot (which plagued us last year).
The concept of Marvin is that those mid-level flex wheels are spring loaded inwards, and each half of the intake is each powered by a motor. It’s on the table to move this to a single motor powering it, but for now we’re using two. These 4" flex wheels are powered by a NEO 550 at a 2:1 reduction. We are still actively working on motor mounting and related geometry here.
We’ve taken a huge amount of inspiration from 6328 over the last year, and have fully converted to the AdvantageKit hype train. The majority of our work has been on learning how to most effectively utilize simulation. We are simulating each of our mechanisms right now:
Since our elevator is at an angle and does not behave exactly the same as a normal vertical elevator, we had to subclass
ElevatorSim in order to adjust the gravitational constant, resulting in
Our swerve modules are simulated by modeling each module as two flywheels - one for azimuth, one for driving. It works, but the MOIs are mostly just guessed and will probably be wrong on the real robot and will need re-tuning.
We’re not taking too many risks this year, and are mostly catching up to the latest on recommended approaches for things like pose estimation with April Tags.
One thing we are taking risks with is our autonomous path generation methodology. Since this year’s field is not rotationally symmetric, we need to do some more explicit transforms in order to account for red vs blue alliance paths. Our requirements were:
- Only create/maintain paths on one side of the field (e.g. blue)
- Use a GUI-based path creation tool (PathPlanner)
- Minimize the amount of “red vs blue” compensation that needs to occur during April Tag usage.
The third point is a quality-of-life requirement and is not based on any performance or math related foundations. Since we are still learning a lot about coordinate spaces in robotics, we feel it would be easiest if we had an absolute origin - in this case being the bottom-right corner of the blue alliance driver station wall. We felt it’d be easiest to understand pose-based log data if we had the same origin in every match. This may not be the case for every team, and that’s okay.
PathPlanner provides a solution for requirement #1 and #2, but the built-in transformation of trajectories from blue to red also adjusts the origin, which we do not want (but we’re sure will be a totally valid solution for most teams).
We want to manually reflect the trajectories (and states) ourselves at robotInit, in order to transform them from blue to red. However, PathPlanner’s transformation algorithm uses private fields that we can’t access, so we can’t completely transform it on our own. There are two solutions:
- PR PathPlanner to make private fields not private.
- Use reflection.
We felt adventurous, so we chose #2. We’d like to thank @came20 for helping us with this.
Effectively, we are taking each state in the trajectory and just mirroring it across the mid line to a new pose. This also requires some rotation changes and some curvature changes - some of which are private fields that we need to tell the JVM to make accessible. We then join the states to a trajectory using a constructor that is also private.
This will only crash if the API signatures change, which won’t happen during an event, as we won’t be updating PathPlanner during events. This is not recommended to most teams. That said, it fits our requirements for this year’s codebase.
Mechanism2d is great and recommended. However, we were worried about code complexity with having each subsystem update its own Mechanism2d, which may or may not be dependent on other subsystems’ Mechanism2d (mostly just at initialization time). Since we are opting for
public static subsystems rather than dependency injection this year, we wrote a quick “subsystem” that reads from all the other subsystems and updates the whole Mechanism2d drawing. This class is a work in progress and will change drastically over the course of the season.
(PID tuning to be perfected later)
Overall, we are cautiously optimistic at this time. We are happy to see great teams like 3847 coming to similar conclusions as us and would like to thank them for sharing so much.