← All projectsHoward County Library SystemJul to Aug 2024

FTC CENTERSTAGE Offseason Robot

Telescoping pitching arm

An FTC CENTERSTAGE robot with a pitching claw on four-stage belt-driven slides, built in less than a week to demo at the library system's STEAM Carnival.

Less than a weekFor everything, so off-the-shelf goBILDA parts wherever I could
979 mmOf slide travel: four stages of 245 mm (from my CAD)
1.49 mFrom the pivot to the claw tip at full reach (from my CAD)
About 109°Between the arm's two presets, held by P control plus gravity feedforward
The finished robot: the slides run out along the floor, then the arm pitches up
Before the sideplates went on: the claw out at two pixels, then the arm pivots up and back down

For my internship with the Howard County Library System, I was tasked with building an eye-catching FIRST Tech Challenge robot to demo at the STEAM Carnival the library system hosts, to recruit for the library system's FTC class, which I taught. Inspired by the FTC team KookyBotz, I designed a pitching claw robot for the CENTERSTAGE game: four-stage belt-driven Viper-Slides on a pivot, so one mechanism reaches out along the floor to grab two pixels, then swings up over the back of the robot to score them. I had less than a week for everything, so I used as many off-the-shelf goBILDA parts as I could.

It ran at the carnival on Aug 3, 2024, where visitors from the community, children and adults, drove it. Two things broke. The low-side U-channel that carries the slides cracked just past the pivot and then snapped, after the arm had pivoted several times with the slides all the way out; my FEA of it is below. And in the weeks after the demo, a student picked the robot up by one of the laser-cut acrylic sideplates and broke it. The code is on GitHub.

One full cycle

Scroll to run one cycle on my real CAD, in the order the robot works: reach out, grab two pixels, pull in, pitch over the back, reach again and drop them on the backdrop.

  1. 1. Stowed

    Slides in, the arm tilted up so the claw hangs clear of the floor. Two pixels wait where the claw lands at full reach.

  2. 2. Reach

    One 435 rpm motor drives a single belt through all four slide stages at once: 245 mm each, 979 mm in all (from my CAD).

  3. 3. Grab

    Each finger has its own servo and its own bumper on the second gamepad; the right trigger moves both. Two pixels, side by side.

  4. 4. Pull in

    The slides come back in with both pixels before the arm swings up; it only tilts enough to keep the claw off the floor. The code never enforced that order: see what broke.

  5. 5. Pitch

    Two 43 rpm motors swing the arm over the back to 120 degrees from flat, until the slides are parallel to the backdrop's 60 degree face. The wrist turns the claw over, so the pixels face the backdrop.

  6. 6. Reach again

    The slides run out along the face, still parallel to it, and the wrist lays the pixels flat on it: the claw rests right against the face without overlapping it.

  7. 7. Drop

    The fingers open and both pixels slide down the face into the two middle notches of the bottom row. Then slides in, arm down, and the next pair.

My real CAD, rigged about its real axes: the arm turns about the line through both pivot motor shafts, the four slide stages run along the arm (each ball carriage at half its stage's speed, as in a real Viper-Slide), and the wrist and each finger turn about their servo output splines. The pixels and the floor are added for the animation. The backdrop is the official CENTERSTAGE backdrop from the field CAD (AndyMark am-5103), its bottom edge against the robot's back; in step 6 a cut through the middle of the claw shows the claw and a held pixel touching its face. The claw is drawn 100 mm longer than in my CAD (the stem between the wrist and the fingers is stretched), because my CAD is likely an older version than the robot I built: at that length the claw touches the face with the slides parallel to it, and nothing overlaps the backdrop. The CAD has the belt only fully in and fully out, so it is hidden while the slides move.

The brief

The Howard County Library System hosts a STEAM Carnival, and as part of my internship there as a STEM instructor and youth peer intern, I was tasked with making an eye-catching FIRST Tech Challenge robot to demo at it, to recruit for the library system's FTC class. I had less than a week for everything, so the plan was to use as many commercial off-the-shelf parts as possible and design only what I had to.

The game was CENTERSTAGE, the 2023-24 FTC game: robots pick up hexagonal pixels and place them on the backdrop, a slanted board. I started from an older goBILDA robot, a Strafer chassis with cable-driven Viper-Slides, a claw and a wrist, took it apart and rebuilt it around a pitching arm, inspired by the FTC team KookyBotz. The slides rotate for horizontal extension and for height, so one mechanism reaches out across the floor for pixels and also lifts them to the backdrop. The claw in my CAD is still called "kooky claw v2".

Problem No dual blocks

The layout needed goBILDA dual blocks to put channels in the right places, and I did not have any.

Fix

I improvised the same positions from U-channels and quad blocks I had on hand.

Jul 29: the old robot coming apart: Control Hub, cable-driven Viper-Slides and wiring
Jul 29: the old robot coming apart: Control Hub, cable-driven Viper-Slides and wiring
Aug 1: the rebuilt robot from above before the sideplates, with the pivot motors and the slides stowed
Aug 1: the rebuilt robot from above before the sideplates, with the pivot motors and the slides stowed

How it works

My CAD of the finished robot, posed the way I designed it: arm flat, slides all the way out.

  1. The whole robot

    430 mm across the sideplates, 456 mm long with the bumpers (from my CAD). Arm, slides and claw all sit on one pivot in the middle; at full reach the claw tip is 1.49 m out from it.

  2. Drive

    A goBILDA Strafer chassis: four 312 rpm motors along the side channels, each turning a 96 mm mecanum wheel through 1:1 bevel gears. Free speed: 312 rpm × π × 96 mm = about 1.6 m/s.

    The code is standard mecanum mixing, strafe scaled by 1.1 "to counteract imperfect strafing".

  3. Pivot

    Two 43 rpm motors face each other on one axis, 94 mm above the floor, each on its own 72 mm U-channel tower. Their hubs bolt to a third 72 mm U-channel; the slide kit's 1-hole U-channel and low-side U-channel stack on it and carry the slides. Direct drive, load shared.

  4. Slides

    A goBILDA belt-driven four-stage Viper-Slide kit, 336 mm slides. One 435 rpm motor at the base of the arm pulls one belt, and all four stages move together: 245 mm each, 979 mm in all. The motor pivots with the arm.

  5. Claw and wrist

    A servo at the end of the slides pitches the whole claw (the wrist). Two red fingers, each on its own servo, hold two pixels side by side. Printed body and mounts; a LEGO ball caster under it (not in the CAD).

  6. Sideplates and back plate

    Red acrylic truss sideplates, about 3 mm thick and 432 mm long, on eight printed 56 mm standoffs. The printed back plate spells HOWARD COUNTY LIBRARY SYSTEM in 25 red letters beside the library's logo.

The build, day by day

  1. Jul 25

    First layout in CAD

    The first layout in Fusion 360: the slides reaching far out past a Strafer chassis, on a pivot in the middle of the robot.

    Jul 25: the first layout in Fusion 360, slides far out past the chassis
    Jul 25: the first layout in Fusion 360, slides far out past the chassis
  2. Jul 29

    Teardown and a new frame

    I took the old robot apart and started the new frame from its parts. The drive stayed the Strafer's: four 312 rpm motors, each turning a 96 mm mecanum wheel through a pair of bevel gears.

    Jul 29: the bevel gears inside a drive channel of the Strafer chassis
    Jul 29: the bevel gears inside a drive channel of the Strafer chassis
  3. Jul 30

    The slides go from cable to belt

    I took the old cable-driven slides apart and converted them to belt drive: bearing idlers, end stops and pulleys on each stage, then the belt routed through them. That evening I rendered the whole robot in its red and black.

    Jul 30: the four-stage slide assembled after the belt conversion
    Jul 30: the four-stage slide assembled after the belt conversion
    Jul 30: my render of the robot, slides out with the claw
    Jul 30: my render of the robot, slides out with the claw
  4. Jul 31

    First motion, and a new pivot motor

    I printed the wrist and claw parts at home in the morning, then ran the slides for the first time: straight up, then flat along the floor. The pivot needed as much torque as I could get, which meant as low a motor speed as possible, and at first I only had 312 rpm motors. That night at home I swapped in 223 rpm motors borrowed from a friend, with new D-bore hubs, and tested the pivot with the claw on.

    Problem

    One of the 223 rpm motors had a damaged JST-PH connector.

    Fix

    I soldered the motor's leads to a JST-PH connector and heat-shrank the joints.

    Jul 31: the first extension test, slides straight up on the bare chassis
    Jul 31: the slides lying flat, running out across the tiles
    Jul 31, at home: the first pivot test with the printed wrist and claw
  5. Aug 1

    Claw, final pivot motors, sideplates

    The two-finger claw went on in the morning. The 43 rpm motors that had been ordered arrived, so the pivot changed motors a final time, with new 8 mm REX hubs, and I tuned its controller. In the afternoon I laser cut the truss sideplates from red acrylic, and that night I printed the letters and the logo for the back plate.

    Aug 1: the two-pixel claw with its two red fingers
    Aug 1: the two-pixel claw with its two red fingers
    Aug 1: the laser cutter tracing a truss sideplate in red acrylic
  6. Aug 2

    Finished

    Sideplates and the lettered back plate on, then drive tests with the finished robot.

    Aug 2: the finished robot, red truss sideplates and the lettered back plate
    Aug 2: the finished robot, red truss sideplates and the lettered back plate

Holding a long arm steady

The pivot is the hard part of a pitching robot. Gravity pulls hardest on the arm when it lies flat and not at all when it stands straight up, and the slides make the arm longer or shorter on top of that. A plain proportional controller has to build up error before it pushes back, so the arm would sag below its target by an amount that changes with the angle.

So the pivot runs a proportional term plus a gravity feedforward term. The feedforward gives the motors the power gravity needs at the current angle, and the proportional term only has to close what is left:

angle      = -360 * position / 3895.9       (degrees)
gravity    = 0.18 * cos(angle + 110°)
pitchPower = -0.001 * (target - position) + gravity

The motors drive the arm directly, with no gears or belts between them and the arm, so their gearboxes set the torque. I needed as much torque as possible, which meant as low a speed as possible: I started with the 312 rpm motors I had, moved to 223 rpm motors borrowed from a friend, and ended on the 43 rpm motors that had been ordered.

Aug 1, mid-tuning: TestTeleop on my laptop with the gravity feedforward lines. The down preset was still 1,280 ticks here; the final code uses 1,225
Aug 1, mid-tuning: TestTeleop on my laptop with the gravity feedforward lines. The down preset was still 1,280 ticks here; the final code uses 1,225

Calculation Which pivot motors could hold the arm out?

Gravity moment about the pivot, arm flat, slides in4.1 N·mmy CAD (masses and positions of every part on the arm)
The same, slides all the way out12.4 N·mmy CAD
Stall torque, 312 rpm motor24.3 kg·cm = 2.38 N·mgoBILDA 5203, 19.2:1
Stall torque, 223 rpm motor38.0 kg·cm = 3.73 N·mgoBILDA 5203, 26.9:1
Stall torque, 43 rpm motor185 kg·cm = 18.1 N·mgoBILDA 5203, 139:1
Pivot motors2, direct drivemy CAD
  1. 312 rpm pair: 2 × 2.38 = 4.8 N·m, barely above 4.1 with the slides in and well under 12.4 with them out
  2. 223 rpm pair: 2 × 3.73 = 7.5 N·m, 1.8 times the load with the slides in, still under 12.4
  3. 43 rpm pair: 2 × 18.1 = 36.3 N·m, 2.9 times the load with the slides out

Only the 43 rpm pair can hold the arm flat with the slides out, and stall torque is the most a motor gives, at zero speed: neither faster pair could have lifted the full reach at all.

Estimate: stall torque at 12 V; the arm weighs 1.98 kg in my CAD, with the printed claw parts taken as solid plastic, so the loads are an upper bound.

With the 43 rpm goBILDA gearmotors on the arm directly, 3,895.9 encoder ticks are one turn of the arm, about 10.8 ticks per degree. Both motors get the same power, and only one encoder is read. The driver has two presets on the second gamepad's D-pad, up (50 ticks) and down (1,225 ticks), about 109 degrees apart, and each preset also moves the wrist, so the claw points the right way at both ends. I tuned it on the robot, with the target and the measured position on the Driver Station screen.

Aug 1: the Driver Station while tuning; the two telemetry lines are the pivot's target and its measured position
Aug 1: the Driver Station while tuning; the two telemetry lines are the pivot's target and its measured position

Calculation Why the gravity term: how far would P alone sag?

Proportional gain kP0.001 power per tickTestTeleop.java
Gravity gain kG0.18 power, arm flatTestTeleop.java
Encoder at the arm3,895.9 ticks per turngoBILDA 5203, 139:1
Stall torque, 43 rpm motor185 kg·cm = 18.1 N·mgoBILDA 5203, 139:1
Pivot motors2, direct drivemy CAD
  1. Ticks per degree = 3,895.9 / 360 = 10.8
  2. Flat, the arm needs about 0.18 power just to hold still; the gravity term supplies it
  3. P alone gives 0.18 only at an error of 0.18 / 0.001 = 180 ticks = 180 / 10.8 = 16.6°
  4. Torque at 0.18 power, stalled: 2 × 0.18 × 18.1 N·m = 6.5 N·m
  5. Up preset, 105° from flat: 0.18 × cos 105° = -0.05, a light push back toward vertical

Without the cosine term the arm would sit about 17 degrees below its target at flat before P pushed as hard as gravity pulls. With it, the motors hold about 6.5 N·m at flat, and P only closes what is left.

Estimate: assumes 0.18 balances the arm at flat, a stalled motor's torque in proportion to its power, and no friction; the load also changes with how far out the slides are.

The rest of the code

The whole robot runs from one TeleOp OpMode: a single loop that reads both gamepads, mixes the mecanum drive, runs the pivot controller and sets the slides and servos on every pass.

Motor speeds from the part numbers in my CAD; everything else from TestTeleop.java.
OutputHardwareControl
Drive4 goBILDA motors, 312 rpm, mecanumMecanum mixing on gamepad 1, strafe x 1.1
Pivot2 goBILDA motors, 43 rpm, direct driveP plus gravity feedforward, two presets
Slides1 goBILDA motor, 435 rpm, one beltOpen loop on the left stick of gamepad 2
Wrist1 servoSet by each pivot preset
Fingers2 servosA bumper each; the right trigger moves both

The slides run open loop: the stick sets the slide motor's power directly, and when it is let go the motor still gets a small holding power, a different one in each pivot preset. The code never knows how far out the slides are, which matters in the next section.

Code: TestTeleop.java in github.com/jerryli08/newftccad. The angles and the 109 degrees are computed from its constants.

Aug 1: the arm pitching up under the P plus feedforward controller

Why the pivot broke

The same arm and the same controller, first with the slides in, then all the way out, and then what that did to the channel that carries the slides.

  1. Two presets, one controller

    Slides in, the arm swings up past vertical. The readout is the code's own math: the P term fades near the target; the gravity term falls from 0.18 at flat to zero at vertical and turns negative past it.

  2. The same arm, slides out

    The claw goes from 0.44 m to 1.42 m from the pivot (from my CAD): 3.2 times its torque, and about 10 times its inertia every time the arm starts or stops.

  3. Where the load goes

    The motor hubs turn a 72 mm U-channel. The slide kit's 1-hole U-channel sits on it, and the low-side U-channel carrying the slides sits on that. For the first 16 mm past the 1-hole channel, that 12 mm tall channel and one small steel bracket carry the whole arm.

  4. Every full-power start

    Pressing the up preset from rest puts both motors at stall: 36.3 N·m. My FEA puts 560 MPa at the side-wall hole 8 mm past the 1-hole channel, against 276 MPa yield: a safety factor of 0.49.

  5. Pivot after pivot

    The down preset starts at stall the other way, so every pivot swings the stress at that hole from +600 to -570 MPa: past yield both ways, six times the fatigue limit. A crack starts at the hole and grows.

  6. The snap

    The crack ran across the channel and it snapped cleanly: the slides and the claw fell, and the stub left on the pivot swung up. The crack and the snap are drawn, not simulated.

  7. The rule I would add

    Slides in first, then pivot. With the slides out the pivot stays locked; only fully retracted may it move.

Steps 1 and 2: the readout is computed from the constants in TestTeleop.java at each angle, with the target set to the up preset; the torque and inertia ratios compare the claw at its two distances from the pivot and count the claw only. Steps 4 to 6: the colours are my FEA's von Mises stress on the low-side U-channel at the up start and at the down start, on a scale that ends at 6061-T6's 276 MPa yield (dark red is past it). The crack follows the row of holes where the FEA peak is, and it and the snap are an illustration of the failure; the drawn pivots swing 16 degrees to stay in frame, where the real up preset is 105.

What broke, and what I would change

Problem The low-side U-channel snapped

The low-side U-channel that holds the slides cracked between the 1-hole U-channel and the slide mount. With the whole extension out, the slides put a large load on it, and so does the 1-hole U-channel under it, which the two 43 rpm motors drive through the 72 mm channel. The arm pivoted several times fully extended; every pivot deformed the channel a little more, until it snapped cleanly.

To see why, I ran a finite element analysis on my CAD: the low-side, 1-hole and 72 mm U-channels, the steel angle bracket beside them and the slide's fixed outer rail, joined where the kit's screws are and held where the motor hubs bolt on. The rest of the arm, 1.98 kg in my CAD, goes in as its weight and inertia at its real place.

Aug 7, after the carnival: the low-side U-channel that snapped, the break running from one of its large holes through the small holes beside it
Aug 7, after the carnival: the low-side U-channel that snapped, the break running from one of its large holes through the small holes beside it
My FEA at the worst moment: the up preset pressed from rest with the slides all the way out, both motors at stall. Von Mises stress on my CAD's parts, from the left and above; dark red is past 6061-T6's typical yield.
My FEA at the worst moment: the up preset pressed from rest with the slides all the way out, both motors at stall. Von Mises stress on my CAD's parts, from the left and above; dark red is past 6061-T6's typical yield.

Calculation Safety factor of the low-side U-channel at a full-power start, slides out

Motor torque, preset pressed from rest2 × 185 kg·cm = 36.3 N·m (stall)goBILDA 5203, 139:1; direct drive, my CAD
Arm inertia about the pivot, slides out1.50 kg·m²my CAD
Gravity moment, arm flat, slides out12.4 N·mmy CAD
Low-side U-channelgoBILDA 1121-0015-0384, aluminium, 130 ggoBILDA; 6061 (Jerry)
6061-T6 yield strength276 MPa typical, 240 MPa minimum6061 aluminium alloy
  1. Angular acceleration at the start: (36.3 - 12.4) / 1.50 = 15.9 rad/s²
  2. Nearly all of the arm is past the crack, so nearly all of the 36.3 N·m goes through the channel there: 29 N·m in the channel itself, the rest through the bracket beside it (FEA)
  3. FEA peak, von Mises, at the side-wall hole 8 mm past the 1-hole channel: 560 MPa; just holding the arm flat: 190 MPa
  4. Safety factor = 276 / 560 = 0.49 (0.43 on the 240 MPa minimum); holding still: 276 / 190 = 1.45

Below 1: every full-power start with the slides out pushes the metal at that hole past yield. Holding the arm out was fine; starting and stopping it was not.

Linear FEA (CalculiX, 10-node tetrahedra, about 800,000 unknowns) on my CAD's parts; above yield the real stress is capped by plasticity, so the number means the metal deforms there. The peak moved 1% when the elements at the hole went from 0.45 to 0.25 mm. Estimate: rigid arm, stall torque at 12 V, the printed claw parts taken as solid plastic.

The same moment, the low-side U-channel's left side wall seen from the left: the metal past yield runs along the top of the wall over the 1-hole channel and peaks at the hole 8 mm past it, before the slide's first screws.
The same moment, the low-side U-channel's left side wall seen from the left: the metal past yield runs along the top of the wall over the 1-hole channel and peaks at the hole 8 mm past it, before the slide's first screws.

Why the extension mattered: with the slides out the arm is 8.5 times harder to spin up, so at every start the motors stay above 80% of stall about ten times longer (about 70 ms, against 6 ms with the slides in, from a simulation of the code's controller), and gravity alone already takes 190 of the channel's 276 MPa at that hole.

Calculation Why it cracked, then snapped

Stress along the channel at the hole, up start+600 MPa (tension)my FEA
The same, down start (both motors at stall the other way)-570 MPa (compression)my FEA
6061-T6 fatigue limit97 MPa for 5 × 10⁸ fully reversed cycles6061 aluminium alloy
6061-T6 yield strength276 MPa typical6061 aluminium alloy
  1. Each pivot, up then back down, is one cycle: amplitude (600 + 570) / 2 = 585 MPa, mean +15 MPa, so fully reversed
  2. 585 / 97 = 6 times the fatigue limit, and past yield in both directions

Every pivot bent the metal at the hole past yield, one way going up and the other way coming down. That is low-cycle fatigue: plastic deformation in each cycle, and a low number of cycles to failure. A crack started at the hole, grew with each pivot, and the channel finally snapped cleanly across.

The code starts both moves at full power: pressing a preset from the other one gives a P term over 1 (0.001 × 1,175 ticks), which is clipped to full power (TestTeleop.java). The amplitude is the elastic FEA value at the edge of the hole; the real one is capped by plasticity, which is what makes each cycle a small permanent deformation.

Next time

Reinforce the pivot.

Problem No interlock in the code

Nothing stopped the arm from pivoting at full extension. The pivot presets never checked the slides, and the slides ran open loop, so the code did not even know how far out they were.

Next time

Hard states that keep the arm from pivoting unless the slides are fully retracted.

That needs the code to know where the slides are, from the slide motor's encoder or a switch at full retraction, and then a small state machine: retract, pivot, extend.

The sideplates

Problem Acrylic sideplates

I laser cut the sideplates from acrylic because it was the only material I had access to. In the weeks after the demo, a student picked the robot up by one of them, and it broke.

Next time

Cut the sideplates from polycarbonate, or, as a second choice, Delrin, which costs more.

Aug 1: a truss sideplate cut from red acrylic on the laser cutter bed
Aug 1: a truss sideplate cut from red acrylic on the laser cutter bed
Aug 2: a sideplate bolted to the robot
Aug 2: a sideplate bolted to the robot

At the STEAM Carnival

On Aug 3, 2024 the robot ran on a field with CENTERSTAGE backdrops and pixels, set up under a tent at the STEAM Carnival. Visitors from the community, children and adults, drove it.

It was there to recruit for the library system's FTC class, which I taught, and the class was overbooked. As part of the same internship I also wrote and taught a robotics curriculum.

At the carnival: the robot on the field with its arm up
Aug 3: the robot on the field, the backdrop behind it
Aug 3: the robot on the field, the backdrop behind it

More from the build

Jul 31, late: the first full assembly, arm up
Jul 31, late: the first full assembly, arm up
Jul 31: the pivot swinging forward to vertical and back
Jul 31: the claw with the LEGO ball caster under it
Jul 31: the claw with the LEGO ball caster under it
Aug 1: the red fingers driven from the Driver Station
Aug 1: the cut truss sideplate lifted out
Aug 1: the cut truss sideplate lifted out
Aug 1: printing the red logo and letters for the back plate
Aug 1: my render of the lettered back plate and the truss sideplates
Aug 1: my render of the lettered back plate and the truss sideplates
Aug 2: the printed back plate with the red letters pressed in
Aug 2: the printed back plate with the red letters pressed in
Jul 31: the pivot with its two motors
Jul 31: the pivot with its two motors