FRC 95 The Grasshoppers 2023 Build Thread

Whew, there is a lot going on. I’m going to post in digestible chunks with limited topics per post to avoid the wall of text eyes glassing over thing.

April tags! We did a thing with them, they seem to work nicely. Me simple mechanical man, trust programmers, @marshall says they good.

But seriously, april tags solve a lot of vision annoyances and I look forward to their implementation. We will be using them to localize the robot and control mechanism(s) and the chassis for scoring.

The team had a good discussion about changing our design philosophy a bit for this year, both because it makes sense to and because we will learn new things. This year we’re going to go for a light robot with a small foot print, maybe ditch pneumatics, and get real simple with things.

We had a concept review tonight for our chassis design goals and current draft. Turning the priorities list into design requirements within the context of our evolving design philosophy resulted in:

-swerve with rev modules, L3 for full yeet
-clear 34.25° breakover and approach angles of charger (worst-case to climb up an already-balanced charger, light robot may not tip heavy robots)
-bellypan to get mass as low as possible
-does NOT need to go over the 34deg breakover in any orientation (this design can go over in two directions only)
-24x24 to take up less than 1/3 of the charger with bumpers, and to help keep mass down

Still leaning into sheetmetal pretty hard. The formed side rails buy us about 9% more interior volume than a conventional 2x1 tube frame would. This will be helpful as we try to cram everything into the small 24x24 chassis.

More later, hope you’re all doing well.


The code linked above is for Wpilib 2022. New 2023 code is on our 2023 repo, which exists now.

All code is for mk4s with neos on drive and steering, and CANCoders on the azimuth. Everything should probably be adaptable by changing constants and possibly minimal adjustments to the SwerveModule class.

1 Like

Let’s talk about ‘doing the math.’

It’s kind of a trite and unhelpful thing to say: go do the math. What math? How hard should I do this math? Can I believe the results of this math at all?

For general design work we love using Recalc for mechanisms and ILITE drivetrain sim for basic drivetrain considerations. These calculators can get a lot of mechanism and gearing choices within the realm of sanity with very little effort.

Other times we need to write our own calculators for weirder things. Two things we made simple calculators for were tipping; tipping the charger and tipping the robot over with an extended arm.

We are building light, so we wanted to know if a light (100lb) robot would tip the charger if one or two full-weight robots were already balanced. This would represent a ‘we’ve got 20 points, but maybe we need 30 at the last second’. Turns out that our robot is unlikely to tip the charger in these situations (even a single balanced full-weight robot that’s offset near the limit of tipping the other way would prevent us from tipping the charger towards us), so we designed the chassis to handle the 34deg breakover.



We also made an arm-chassis-combo CG calculator that predicts max driving accelerationg with the arm in different configurations and weights. These numbers are based on a loony coodinate system we chose, so don’t overthink them too much.


Tells us something kinda obvious: heavier arms and lighter chassis get tippier. Now we compare to the ILITE sim results for our chose DT (yeah, I know, the masses aren’t all exactly the same, but we’re at a crayola level of precision here).

Now we can look at the green curve of the sim results to see how our driving is impacted by different acceleration limits by using different coefficients of friction in the sim. I picked 15ft as a sprint distance we might use with an extended arm for scoring (e.g. flip out arm as soon as you enter the community zone, then drive 15ft with an extended arm to score).

friction limit - sprint time for 15ft
1.2g - 1.4s (no robot tipping limit, traction limit of our wheels)
1g - 1.4s (small acceleration limit from a full-weight robot with an insanely light arm)
0.7g - 1.4s
0.6g - 1.5s
0.5g - 1.5s (moderate robot weight with moderate arm weight)
0.4g - 1.6s
0.3g - 1.8s
0.2g - 2.2s
0.1 - 3.2s (light robot with a very heavy arm)

These are all worst-case numbers and do not necessarily limit the robot in all directions of movement with swerve.

How do we put these results in context? Welp… experience.
Our best matches in 2017 were 9 gears, or about 8 full-field cycles with a ~10s climb. Call it 120s, 8 cycles… 15s/cycle broken down to ~ 8s driving, 1-2s pickup, 4-6s scoring. 2017 was a bonkers year.

So, how much do we care about the time-cost of acceleration limiting from an extended arm?

1.2-0.7g - not even a little bit. Any design that keeps our acceleration limit at or above 0.7g is effectively the same from a driving perspective

0.6-0.4g - not really much at all. A few tenths of a second are within traffic and light defense variability.

Down to 0.3g - adding less than 1s to a cycle, which is not TOO big a deal, worth considering if we gain some significant durability or flexibility in another area of robot performance. Think carefully if this will cost us a cycle.

0.2g or worse - nope, we’ll lose more than 1s, maybe 2-3s, per cycle which will reduce our total cycle capacity by at least 1 game piece, maybe 2. This is not acceptable.

Now we have some reasonable numbers to feed back into the CG tipping calculator to see what our design allowances might look like… Effectively a 10lb manipulator on a 100lb chassis is probably around where we want our design limits to be.

I do not plan on sharing these calculators, they aren’t polished and require a lot of explanation on how to use them. Derivation of such calculators is left as an exercise for the reader.

There, that’s a decent example of how we ‘do the math’ to help guide design decisions (and how to not obsess over making the lightest arm known to FRC).


Awesome content James! Also scares me a bit because we are also planning to be light and will beach ourselves on the corner of the charging station with our current design :rofl:

Let’s talk about design flexibility.

A common theme of successful teams is that their robot evolves over the course of build and competition season. Code improvements, new or revised mechanisms, and other upgrades help keep pace with improving competition.

Some teams can afford (and have the energy) to build whole new robot revisions through a season. We are not one of those teams (I know, I know, not with that attitude we’re not). So how do we support design flexibility? Design compromise.

The best-o-the-best generally do a wonderful job of integrating all of their systems together as a cohesive package. This results in a superior final product, but can restrict the amount of rework options for improvements later in the season. So, we compromise our overall design to enable easy-ish rework. This includes making different functions structurally independent and using generic hole pattern interfaces that aren’t always the most efficient choice.

It’s why our frame concept has way too many holes and extra flange features than it needs to be just a frame. This will give us many mounting options through the season without requiring significant disassembly.

We are going to take this philosophy a little further this year and make a generic arm structure as quickly as we can and worry about exactly what the end effector looks like later. We know a 1DoF arm with a (virtual) 4-bar linkage can reach some game pieces on the ground and score on the highest row, so we’re going to start there.

The magic box (to be determined effector) will be able to swing to the 3rd row and to the back of the robot for an as-yet-undetermined intake handoff. Maybe. If we get the far. The 1DoF arm is likely to have the lowest overall mass and fewest controls, but also has mass located near the top of the envelope and must swing its arm out before approaching the scoring area.

We will also aim to make the design somewhat scalable to turn it into a 2DoF arm (with telescoping and rotation) if there is a fatal flaw. The 2DoF layout looks like this.

The 2DoF arm is heavier, but lower, and has more margin for arm deployment in the community.

Hopefully whatever generic-type end effector interface we create doesn’t bite us in the butt. On the other hand the programmers will be psyched to have an arm to control earlier in the season.


Let’s talk about gluing stuff.

In a sidebar with @Brandon_Holley (by extension the 125 kids) and @HDrake we discussed how to bond inserts into composite tubing. A lot of good information was centralized in that conversation, and @AllenGregoryIV had the great suggestion to share it with the larger community.

Let’s start with some basics: adhesives are best used in shear, not peel/tension. Think about how easy it is to peel tape if you pull up vs pulling parallel to the surface its stuck to. To put some rough numbers on this, epoxies usually have a shear strength of 1,500-4,000psi*, and a peel strength of 10-50 pli* (pounds per linear inch). A patch of epoxy that could support a car in shear could be peeled apart by hand.

Other basics: composites with fiberglass, aramid, and carbon fiber offer awesome material properties. They can be stronger, lighter, and stiffer than metals. But they are tricky to work with, and you can’t just bolt/rivet to them as you would metal. Gluing composites is a great, and commonly-used, option. When done properly, the CF tube will fail before the insert or adhesive do (called a structural failure).

(From design testing I did in college)

To reach this level of bond strength the following recipe items need to be addressed:

  1. Bondline gap, the thickness filled by epoxy between the two parts, must be controlled and carefully chosen. Look at the TDS for the epoxy you’re using, when in doubt use 0.005in. To ball out of control - get epoxy with glass beads already dispersed in the adhesive.
  2. Surface preparation is critical. At a minimum I suggest a solvent clean, abrasion with 120-220 emery, and another solvent clean. Ideally the parts are etched, but this is not practical for most.
  3. Proper mixing of the adhesive. Use a static mixer tube or other automatic mixer when possible. I really like a duo-pack dispenser and static mixing nozzle for manual dispensing.

    3A) Proper application of adhesive is also critical. I recommend wetting both mating surfaces with adhesive first. When mating the parts together ensure that air pockets can escape.
  4. Cure time and temperature. Read the TDS, and do not disturb the parts before they’re ready. If you can bake out a part reliably this is a great way to get optimal joint properties in a short time. A toaster over can be rigged up with a real temperature sensor and heat controller, but proceed at your own risk.

How can you use this in FRC to leverage composites? Gluing inserts into tubing of course! Tubing inserts or sockets are awesome use cases for adhesives because the adhesive joint can really only be exposed to shear if it is designed well. There are a ton of different ways to do this, and many secondary considerations, but I can only reasonably share a simple exemplary model that covers the big stuff.

-Tapered ID of the insert smooths the stiffness transition from the tube to the insert, reducing stress risers that may result from bending or torsion.
-Longitudinal ribs on the insert ensure a minimum bondgap is set, .005in in this case
-End of the tube bottoms out into an insert feature, helping to control insert placement
-The relief in the insert flange controls squeeze out and contains any splintered ends from cutting the composite
-The core of the insert contributes very little to the system’s strength, so get rid of it for mass savings, thread it for an mount, or use it to run wires/tubes through the tube

Here is an album of insert bond testing that I did in college. By-the-book prep resulted in structural failure of the CF tube at over 3,000lbf. Subpar prep did ~1/2 that and failed adhesively.

*don’t even get me started on how many caveats apply to these numbers, I can’t spend the next week writing this post.


Every year I come back to this thread to follow along and enjoy the in depth analysis done, not only on the game, but also on all parts that go into the robot.

Thank you


Kind words like these are why we keep posting! Thank YOU :slightly_smiling_face:


Let’s talk about when things go wrong. Sideways. Pear-shaped.

This post is partly spleen-venting, partly commiserating, and partly encouragement to work through obstacles you may encounter.

Things will go wrong. In fact, I’d wager that if nothing went wrong in our build/competition season then we weren’t pushing ourselves enough. Though it does seem like this year has more SNAFUs than average…

We preordered the MAXSwerve from REV. Due to a number of circumstances largely or entirely out of their control the kit delivery was ~3 weeks late. No sense it getting upset at REV about it though. I know that they did everything in their power to make up for the delivery delay, including working over the weekend. We got our kits yesterday, phew, and started assembly.

What can we do when a critical part is delayed? Plan, model, read other OA threads, read the MAXSwerve assembly instructions. Plenty of things to be productive before we had the kits.

We ordered a 3D printer farm before the holidays… but… supply chain, holidays, school purchasing systems, and timezone delays means we don’t have them yet. So I am printing stuff at home, and we are changing our design path to avoid quickly-printed parts.

I chose to have the KoP delivered to us this year instead of having someone drive ~3 hours round trip to a kickoff event to pick it up. I figured shipping was easier on our time and lessened our carbon footprint. I even opted us out of the big totes so shipping should be a breeze, right? Nope. $200 for shipping and 6 days later we finally got our game piece box…

This is by far the most frustrating snag so far this season. We lost ~6 days with game pieces and paid $200 when a flat-rate USPS box would have had it to us in one day from HQ. Thank goodness for the other OA teams and Ri3D teams who prototyped lots of intake and gripper prototypes. We studied, read, and watched everything we could to get a good idea of where we wanted to go when it finally arrived so we could hit the ground running.

Stay positive, find what things you can control and work on, keep energy productive and focused. May you find the luck we seem to have lost!


Ours shipped Thursday, we rec’d on Friday. $200 for late shipping and one small box full of stickers is not great.


We still haven’t received ours :cry:



If you want anything tested please post here or in another OA team thread. We will do what we can to accommodate it.


Same here…

1 Like

Lots of things going on. I’m going to post a general overview and tag my students to expand on their respective sections.

Our over-arching design goals are:
-Fast and chaotic (@Kevin_Leonard) e.g. short cycle time with a flexible cycle path
-High effort to minimize arm/effector/moving mass and keep CG low
-Modest flexibility with game piece collection
-Synergy but not dependence between subsystems e.g. arm and gripper can pickup from HP shelf and score, intake alone can ground-load and score in the hybrid nodes, and with the handoff we can ‘touch it, own it’, handoff while driving, then score anywhere
-Vision assist for scoring, code limits/safetys for driving, e.g. make the robot as easy to drive at the limit as we can
-Do a bunch of things we haven’t done before

This is unlikely to be the best recipe for many teams’ goals. We are making intentional design choices to result in a wild, interesting, and fun-to-drive robot. Not necessarily the most competitive robot (though I think if we get it sorted this design has a very high scoring ceiling).

One of @Wesley 's recent tasks has been to write to limit acceleration vs cg location (i.e. the scoring arm in our competition robot) to prevent tipping. The kids… uh… made a CIM lance and cobbed it onto our swerve chassis and… boy that’s a lot of chaotic energy.

Here is a video of some debugging driving. It is mostly working in this video, but not completely. Note the control stick is going full range of input but the robot’s acceleration is extremely limited.

Also, yes, our practice area gets used as storage in the offseason and we haven’t cleaned it out or replaced the carpet yet. It’s on the list.

Our mk1 CAD is mostly roughed in. We are planning on a multi-position linear intake (heavy) that hands-off to a 1DoF gripper on a 1DoF arm (light) riding on top a MAXSwerve chassis.

@JWC_95 is lead on the arm and superstructure. We’re going to use carbon fiber tubes for this framing, but with an aluminum scab plate construction because we don’t have access to high-end/reinforced 3D printing resources. A good bit of care has gone into these terminations and packaging the drive motors and v4b components.

@StephenWitwick is point on the gripper and a few other components including the swerve protector shields, which add a nice splash of color to the MAXSwerve modules.

The gripper, so far the only use of pneumatics on the robot (which we discussed and agreed on), is <3lbs. Keeping this mass as low as possible will maximize robot driving speed and arm speed and ultimately lower cycle times.

End effector mass is a great example of mass-compounding, which I’ll cover in a follow-up post.

I’m taking lead on the intake assembly, which is intended to be heavy to help drive the CG down. It is going to use a linear drive, looking like a round gear rack, to move in/out/. The hotdog style rollers will be driven independently to enable cube intake against the bumper (rolling both inwards) and pinching cone flanges (rolling them against each other).


Tipped cone flange pickup (cone point on the ground, facing away from robot):

Fully deployed to intake cube against bumper:

Naturally there are a lot of details to sort out in CAD, but most of the big things are there.


Acceleration limiting is split into two parts: calculating the maximum acceleration, then actually implementing the limit. James beat me to it on the physics for this one, but the maximum acceleration without tipping works out to gravity * (horizontal distance from CG to edge of wheelbase) / (vertical distance from CG to floor):

This is useful, but in order to actually implement it on the robot, we need to know where the robot CG is and how far it is from the particular edge of the robot that we’re driving towards (or maybe away from? still not sure about that).
Finding the robot CG is simple, because it is just the standard two-mass CG formula, using the chassis cg position and the manipulator cg position. The manipulator cg position will eventually be read from NetworkTables because it will change as the arm moves around.
Finding the horizontal distance is more interesting. First, the actual robot cg is projected onto the line that runs through the geometric center of the chassis, at the desired angle of travel (the “direction line”). One of the four lines that make up the edges of the robot wheelbase is projected onto the direction line— this is really just the point where the direction line intersects the edge of the wheelbase. From there, finding the distance between two points is simple, and the max acceleration can be calculated.
This calculator has most of it, but be warned that it’s not entirely polished and may behave unexpectedly. Also, some of the parameters are in the “calculations” section:

Limiting acceleration:
This part has, surprisingly, caused more trouble than the acceleration calculation. Because the robot is controlled with velocity commands (field relative x and y, in meters per second), we need to turn an acceleration limit into a velocity limit. Seems simple, right? Just use Vf = Vi + at, and you have a maximum allowed velocity. Well, sort of. Vi is easy enough to get, because the WPI kinematics classes exist. The velocities reported by kinematics do need to be converted to field-relative, but this is pretty easy.
a needs to be a vector, because Vi is a vector. Given a direction, the magnitude of a is calculable— that’s what the calcMaxAccel() function described above does.
However, its direction is the same as the change in velocity being requested— in order to reach a new velocity, we must accelerate in the direction of delta V, the difference between current and commanded velocity. Once again, WPI makes this easy, because Translation2d handles all the vector math.
Unfortunately, we still need t. At first, I set t to 0.02 seconds, because the robot loop is 20ms. This resulted in the sluggish acceleration seen in the testing video, which is definitely not the 13m/s/s reported by the acceleration function. This was the cause of much head-scratching, until I eventually remembered hearing about the velocity measurement of NEO/SparkMAX/brushless motors in general being slow. After looking it up, finding a 112ms latency, and adding that to the 20ms loop time, everything seems to be working properly.

All the code for this is here:

Other stuff:
We are planning on going crazy with fancy sensors/cameras this year— we’re looking at 4 limelights and a jetson. This means an 8 port switch on the robot, which means a nice power supply for it and possibly the jetson too. And the limelights when w don’t believe that they can handle unregulated power. James told me to ask @marshall about voltage regulators or buck/boost converters.
As for what these things will do, the jetson will hopefully be running LiDAR localization, at least one camera will be pointed at the intake area for automated gamepiece acquisition, and the rest will be used for AprilTag localization. Maybe one will end up on the arm, and it can do terminal guidance with the retro tape for cone scoring.


Ask away!

1 Like

That’s about all he said. I think he was looking for recommendations for something to power the switch and maybe jetson.

1 Like

My general practice is to start by saying “how low do I need to run this thing at?” and then because, it’s FRC, the answer is typically “as low as I can manage” so I settle on like 3-4V as my lower bound.

From there, I take a trip over to and look at their selection of regulators and then make a decision on if I need boost, buck, or a combination of the two depending on the voltage I am running at.

Then I start looking at the maximum power outputs and various curves and other specs. Most of the time, that gets me to what I want. Sometimes I have to look elsewhere and some other times, I get a new mentor who has an background in EE and embedded work and wants to use Altium with some students to design a highly custom board that I’m eager to see in action.


Gripper materials!

We finally had a chance to test different gripper materials. We have a pretty big collection from over the years, so the first thing the students did was a hand-check to pare down to a few candidate materials for more detailed testing. They picked wedgetop, roughtop, and a firm drawer liner material for additional testing. Here are the results:

This friction test was an inclined plane method, carefully increasing the plane angle until the object slipped. Each measurement was repeated 3-4 times and the cone was tested in two orientations to help understand the effect of edges of the cone digging into the material.

Wedgetop (1) had good grip, but is pretty heavy, so meh
Roughtop (2) had comparable cube grip, but less cone grip, boo
Drawer liner (3) had good friction on both the cone and the cube and is the lightest, yay

So we will proceed with using drawer liner material for our rollers and end effector.


Got a link to your drawer liner?