← Projects FTC Robotics · DECODE · 2025–26

Decode FTC Robot

Team Captain  ·  FTC Team 15083 Overclock

Intakes balls off the floor and shoots them into the goal from anywhere on the field, using Kalman-filtered localization, an auto-aiming turret and vision-generated autonomous paths.

Jump to software ↓
Top 0.1%out of 8k teams
95%win rate
70%3D printed
Zeromechanical failures
CAD render of the robot, front three-quarter view
Overclock · 15083 Full robot
Mechanical · 01

Drivetrain

Low, defense-resistant mecanum base with pocketed aluminum tubing and dead-wheel odometry.

Drive base: goBILDA channel frame, four mecanum wheel modules and Control Hub
Drive base, outer plates hidden
Underside of the drive base showing mecanum wheels, drive motors and odometry pods
Underside: drive motors and odometry pods
Drive
Four 104 mm goBILDA GripForce mecanum wheels (30A rollers for traction)
Motors
Four goBILDA Yellow Jacket 312 RPM
Odometry
Two goBILDA dead-wheel pods + Pinpoint IMU
Structure
Aluminum channel frame, PETG shells; FEA and drop tested
Center of gravity
2.625 in up, 1.428 in back from center
Size
About 16.1 × 17.9 × 17.9 in (18 in limit)
Mechanical · 02

Intake

Full-width “touch it, own it” intake.

Intake assembly: compliant-wheel front roller and mecanum vectoring roller
Compliant-wheel roller with mecanum vectoring roller behind
Side of the intake showing the roller drive
Roller drive and funnel wedges
  • Compliant wheels grab balls; wedges and boot wheels funnel them in.
  • Mecanum wheels vector balls into the indexer to prevent jams.
  • 1150 RPM motor with enough torque not to stall.

Iterations

  1. League Meet 112% jam rate
    • One row of compliant wheels, 280 mm wide
    • Dead zone caused jams; exposed belts wore out
    League Meet 1 intake CAD
  2. Qualifier 14% jam rate
    • Second row of compliant wheels, belt covers
    • Still jammed from poor vectoring
    Qualifier 1 intake CAD
  3. Regionals3% jam rate
    • Second row swapped for mecanum wheels; belt feeds the indexer
    • No dead zones; 3-ball intake time down 86.7% over the season
    Regionals intake CAD
Mechanical · 03

Transfer

Shell-shaped indexer that holds three balls and fires all three in about a second.

Shell-path indexer CAD, front view
Shell-path indexer: curved path, center wheel, kicker, gate
Shell-path indexer CAD from the other side
Sits under the turret bearing
  • Driven by the intake; a center wheel moves balls along the path.
  • A gate prevents mistimed shots; a kicker feeds the shooter continuously.
  • Non-sorting: scored about 30% more than our sorting prototype.

Iterations

  1. Spindexer
    • Could sort by color, but cycles were very slow
    Spindexer prototype holding three balls
  2. Shell path V1
    • Faster, but couldn't hold three balls
    Shell path V1 prototype
  3. Shell path V2
    • Held three, but kicker reset was slow and could misfire
    Shell path V2 with the old kicker
  4. Shell path V3Final
    • Center wheel, gate and continuous kicker: three shots in about a second
    Top-down CAD view of the final shell path indexer
Mechanical · 04

Tipper

Servo-driven lever that pushes against the floor to tilt the robot for parking.

Tipper module with two Axon MAX servos and lever
Two Axon MAX servos geared to the lever
Side view of the tipper lever
Lever pushes down to tilt the robot

Added for Worlds to earn park ranking points. Servos were sized from the torque needed to tilt the robot 15°, with a safety factor of 2.

Mechanical · 05

Shooter & Turret

High-inertia flywheel shooter with an adjustable hood on a 400° turret.

Shooter and turret CAD; use the sliders to rotate the turret and move the hood
0°
400° of turret travel; the hood moves through its servo four-bar linkage.
  • 8,600 g·cm² of flywheels keep shot speed consistent: three shots in under a second.
  • Two 6,000 RPM motors for fast spin-up and recovery.
  • Hood adjusts 50° for close and far shots.
  • Turret: 8 in bearing, 400° range at over 100 RPM, 3D-printed herringbone gears.

Iterations

  1. League Meet 1
    • Fixed shooter, no turret: only worked from certain distances
    League Meet 1 static shooter prototype
  2. Qualifier 1
    • Turret and adjustable hood: usable anywhere
    • Slow, inconsistent flywheel speed
    Qualifier 1 shooter CAD
  3. Regionals & WorldsFinal
    • Second motor and added flywheels: spin-up from 5 s to 3 s
Mechanical · 06

Localization

Limelight 3A on a servo pivot, two dead-wheel odometry pods and a goBILDA Pinpoint odometry computer.

Limelight 3A on its servo pivot; use the slider to tilt the camera
Diagram of the camera pivoting between floor and AprilTag views
Points down for balls in auto, up for AprilTags in teleop

Camera pivot: one camera, two jobs

  • The Limelight sits on a servo-driven four-bar linkage, so the camera's pitch can be changed during a match.
  • Pitched down for ball tracking: the floor in front of the intake fills the frame, so the neural network can find artifacts for the vision-generated paths.
  • Pitched up for AprilTag tracking: a higher angle keeps the goal and field tags in view for localization and aiming.
  • The pivot switches with the robot's state: down while collecting in auto, up when it needs pose corrections, so a single camera covers both without a second Limelight.
Pixel offset → target angle $$\theta_{target} = \arctan\!\left(\frac{x_{px} - \frac{W}{2}}{f}\right), \qquad f = \frac{W/2}{\tan\!\left(\frac{\mathrm{FOV}}{2}\right)}$$
Key component · Software

Kalman-filtered localization

Odometry covers the whole match but drifts; AprilTags are precise but not always visible. A Kalman filter fuses them into one pose estimate within ~5 mm.

SourceStrengthWeakness
Odometry (2 dead wheels + Pinpoint IMU)Tracks the whole match~3–5% drift
AprilTag (Limelight)~2 mm accurateTag not always in view
Kalman-fusedWithin ~5 mm of true position

How the filter works

The filter keeps a pose estimate (x, y, heading) and a number for how uncertain that estimate is. Every loop runs two steps:

  1. 1. Predict with odometryevery loop
    • Dead wheels and the IMU move the estimate forward by how far the robot just traveled.
    • Odometry error adds up, so the estimate's uncertainty grows each loop: the robot knows it is drifting.
  2. 2. Correct with an AprilTagwhen a tag is seen
    • The Limelight reports where the tag says the robot is.
    • The filter shifts the estimate toward that measurement by a weight, the Kalman gain, then shrinks the uncertainty.
    • With no tag in view, the robot keeps running on odometry until the next correction.
1 · Predict (odometry) $$\hat{x}_{k|k-1} = \hat{x}_{k-1} + \Delta x_{odo}$$ $$P_{k|k-1} = P_{k-1} + Q$$
\(\Delta x_{odo}\)
motion measured by dead wheels + IMU
\(P\)
uncertainty of the estimate
\(Q\)
drift added per loop
2 · Update (AprilTag) $$K_k = \frac{P_{k|k-1}}{P_{k|k-1} + R}$$ $$\hat{x}_k = \hat{x}_{k|k-1} + K_k\left(z_k - \hat{x}_{k|k-1}\right)$$ $$P_k = (1 - K_k)\,P_{k|k-1}$$
\(z_k\)
AprilTag pose measurement
\(R\)
noise of the tag reading
\(K_k\)
gain from 0 to 1: how far to shift toward the tag

A shifting bias

  • The gain is a trust factor that changes on its own. The longer the robot runs on odometry, the larger \(P\) gets and the closer \(K\) moves to 1, so the next tag pulls the estimate further.
  • A noisy or distant tag reading has a large \(R\), so \(K\) stays small and the estimate barely moves. One bad detection can't throw off the pose.
  • Right after a good correction \(P\) is small, so odometry carries the estimate smoothly between tags instead of jumping around.
  • The fused pose drives everything downstream: turret aim, shot distance, launch-zone checks and autonomous paths.
Software · 07

Software

Everything runs off one accurate field position: aiming, shot speed, hood angle and autonomous paths. The driver needs two buttons.

07.1

State machines

  • Each subsystem runs its own finite state machine.
  • Independent subsystems keep loop times under 20 ms.
  • New features are new states, not rewrites.
State update $$S_{t+1} = f(S_t,\ \text{inputs})$$
Idle Intaking Anti-jam Loaded (3) Shooting intake jam cleared 3 balls sensed shoot empty
Illustrative intake-to-shoot cycle.
07.2

Autonomous

Constrained to the 30-second autonomous period. Paths run on Pedro Pathing using predictive braking instead of PID path following, with our own state machines on top.

  • Full Field Auto: 21 balls scored.
  • Infinite Far Auto: cycles until time runs out, 33 balls scored.
Full-field autonomous path plot
Full Field Auto (21)
Infinite far autonomous path plot
Infinite Far Auto (33)
Key component · Software

Bézier curve pathing

Every autonomous path is a chain of Bézier curves. Instead of listing every point the robot drives through, each segment is described by a handful of control points; the curve starts at the first, ends at the last, and is pulled toward the ones in between.

P₀ start pose P₃ end pose P₁ control P₂ control path
A cubic segment: P₀ and P₃ are on the path; P₁ and P₂ only shape it. Orange arrows show the starting and ending direction of travel.

What the control points do

  • The end points P₀ and P₃ are the poses the robot starts and finishes at.
  • The line from P₀ to P₁ sets the direction the robot leaves in; P₂ to P₃ sets the direction it arrives in.
  • Moving a control point farther out makes the robot hold that direction longer before turning, giving a wider, gentler arc.
  • Lining up the control points across a joint keeps the path smooth, so the robot never has to stop and turn between segments.
Cubic Bézier segment $$B(t) = (1-t)^3 P_0 + 3(1-t)^2 t\, P_1 + 3(1-t) t^2 P_2 + t^3 P_3$$
\(t\)
progress along the segment, 0 to 1
\(P_0, P_3\)
start and end poses
\(P_1, P_2\)
control points that shape the curve
Direction and turn tightness $$B'(t) = 3(1-t)^2 (P_1 - P_0) + 6(1-t)t\,(P_2 - P_1) + 3t^2 (P_3 - P_2)$$ $$\kappa(t) = \frac{\lvert B'(t) \times B''(t) \rvert}{\lvert B'(t) \rvert^3}$$
\(B'(t)\)
tangent: the direction of travel
\(\kappa(t)\)
curvature: how sharply the path bends

Following the curve

  • Each loop the follower finds the closest point on the curve to the robot's Kalman-filtered pose.
  • It drives along the tangent \(B'(t)\) at that point, and adds a correction that pushes the robot back onto the curve if it has drifted off.
  • Curvature tells it how much centripetal force a turn needs, so it compensates before the robot slides wide on tight bends.
  • Predictive braking uses the distance left along the curve to slow down early and stop on the end point, instead of overshooting and correcting with a PID.

Generating a path automatically

  1. 1Detect ballsFind the balls to collect
  2. 2Start pointP₀ = the robot's current pose
  3. 3End pointP₆ past the last ball
  4. 4Bend pointP₃, where the path changes direction
  5. 5Control pointsP₁ P₂ and P₄ P₅ shape each segment; P₂, P₃, P₄ in line keeps the bend smooth
  6. 6Draw the pathTwo cubic Bézier segments joined at P₃
  7. 7Follow and collectDrive the path, intake each ball
Illustration: two cubic Bézier segments joined smoothly at a bend point, built around four detected balls, then followed by the robot.
Recursive form (de Casteljau), used for live-generated paths $$B_{P_0}(t) = P_0, \qquad B_{P_0\ldots P_n}(t) = (1-t)\,B_{P_0\ldots P_{n-1}}(t) + t\,B_{P_1\ldots P_n}(t)$$

The same math powers the vision-generated paths: the robot places control points around the detected ball cluster at run time, so one curve sweeps through every ball in the cluster.

07.3

Vision-generated paths

  • Custom TensorFlow model trained on 5,436 images detects balls.
  • The robot finds the densest cluster and generates a Bézier path live to collect three.
  • A* search handles the on-the-fly path planning.
  • In teleop it cuts about 5% of driving time.
Neural network detections drawn as boxes around purple and green balls
Ball detections
Two generated Bézier paths through clusters of balls
Live-generated paths through detected balls
07.4

Turret aiming

Aims from field position, not the camera, so it works even when the goal is blocked. The turret motor control algorithm uses a trapezoidal motion profile.

Target angle $$\theta_{aim} = \arctan\!\left(\frac{y_{goal} - y_{robot}}{x_{goal} - x_{robot}}\right)$$
Trapezoidal motion profile $$v(t) = \begin{cases} a\,t, & 0 \le t < t_a \\ v_{max}, & t_a \le t < t_a + t_c \\ v_{max} - a\,(t - t_a - t_c), & t_a + t_c \le t \le t_f \end{cases}$$
Field diagram with the robot aiming at the goal from several positions
Aiming from anywhere on the field
Key component · Software
07.5

Shot control

Every shot is set by distance to the goal. Three lookup tables, tuned by shooting from measured spots on the field, map that distance to a flywheel speed, a hood position and the ball's flight time.

Three plots against distance to goal from about 48 to 163 inches: flywheel speed rising from about 995 to 1540 encoder ticks per second, hood servo position falling from 0.86 to about 0.66, and ball flight time between 0.52 and 0.75 seconds
The robot's lookup tables: tuned points (16 for speed and hood, 9 for flight time) and the curves between them, drawn with the same interpolation the robot uses
  • Interpolation: The lookup table fits a smooth cubic Hermite spline through the points, so any distance in range gets a value. Distances outside the table are clamped to its ends.
  • Bang-bang flywheel control: full power when more than 15 encoder ticks/s below target and coasting near it. It only drives backward if more than 120 encoder ticks/s over, which gives the fastest recovery between shots.
  • Ready check: the shoot command waits until the flywheel is within 60 encoder ticks/s of its target.
Cubic Hermite interpolation $$H(t) = (2t^3 - 3t^2 + 1)\,p_0 + (-2t^3 + 3t^2)\,p_1 + (t^3 - 2t^2 + t)\,m_0 + (t^3 - t^2)\,m_1$$
Key component · Software
07.6

Shoot on the move

A ball shot while driving keeps the robot's velocity, so the robot aims from where it will be when the ball arrives, not where it is now.

  • Flight time from the table: the distance gives a flight time, which gives a predicted shooter position from velocity and acceleration.
  • Iterated 5 times: the new position changes the distance, which changes the flight time, so the loop repeats until it settles.
  • One distance for everything: the compensated distance sets the turret angle, flywheel speed and hood together.
  • Filtered acceleration: a low-pass filter keeps noisy acceleration readings from shaking the aim.
The robot driving across the field while shooting balls into the goal
Shooting while driving
Iterative lead compensation (k = 0 … 4) $$t_k = T_{LUT}(d_k), \qquad \mathbf{p}_{k+1} = \mathbf{p}_0 + \mathbf{v}\,t_k + \tfrac{1}{2}\,\mathbf{a}\,t_k^2, \qquad d_{k+1} = \lVert \mathbf{g} - \mathbf{p}_{k+1} \rVert$$
\(\mathbf{p}_0, \mathbf{v}, \mathbf{a}\)
shooter position, velocity and filtered acceleration now
\(\mathbf{g}\)
goal position
\(T_{LUT}\)
flight-time lookup table
Lead-compensated aim $$\theta_{aim} = \tan^{-1}\!\left(\frac{(y_{goal} - y_{robot}) - v_{y}\,t_{flight} - \tfrac{1}{2}a_y t_{flight}^2}{(x_{goal} - x_{robot}) - v_{x}\,t_{flight} - \tfrac{1}{2}a_x t_{flight}^2}\right)$$
07.7

Driver automation and sensors

  • Two buttons: one to intake, one to shoot. Plus a full-auto mode and auto-park.
  • Three color sensors track balls through intake, transfer and shooter.
  • Current sensing on the intake triggers an automatic anti-jam.
  • 21-LED strip shows ball count; the controller vibrates when ready to shoot.
Color sensor locations under the shooter, inside the transfer and inside the intake
Color sensor locations
LED strip along the side of the robot
Ball-count LED strip
Process

Design approach

“Fail fast, learn faster.” Decide with data, test cheaply, iterate often, and only keep complexity that earns its place.

From idea to final part

  1. 1. Decide with data
    • Key choices start with decision matrices and measured numbers, not opinions.
    • Example: we built and timed both a sorting and a non-sorting indexer. The non-sorting design scored about 30% more, so it won despite making the Pattern RP harder.
  2. 2. Test with low-fidelity jigs
    • Concepts are proven on quick jigs before any final CAD, such as a modular intake with adjustable mounting holes to find the right compression.
  3. 3. Iterate in small steps3+ versions per subsystem
    • Every subsystem went through at least three major iterations, each fixing one measured problem.
    • Intake jam rate fell 12% → 4% → 3% and three-artifact intake time dropped 86.7%; shooter spin-up went from 5 s to 3 s.
  4. 4. Validate before competition
    • Structural parts get FEA and drop tests; the robot is checked against heavy defense before events.
  5. 5. Simplify
    • Features that stop paying off get removed. The early brake pads were taken off once shoot-on-the-move worked, and a parking mechanism waited until it was worth the weight (the Worlds tipper).

CAD and analysis

  • Onshape for collaborative CAD, using industry practices like master sketches and variable dimensions, so whole parts update from a single value.
  • Onshape mass properties gave the flywheels' moment of inertia to tune shooter spin-up.
  • Fusion 360 FEA on structurally important parts to find likely failure points before printing.
  • Team members earned Certified Onshape Associate, SolidWorks Additive Manufacturing and iCEV safety certifications.
FEA stress plot of a side plate
FEA stress check on a side plate

Materials and manufacturing

Rather than switching to aluminum after prototyping, we kept 3D printing for the final robot: over 70% printed on an aluminum superstructure. It made manufacturing faster, iteration easier and the robot lighter and modular, and it made parts like the shell-shaped indexer possible.

3D printingAluminum
Prototype speedQuickerSlower
CostCheaperPricier
WeightLighter, modularHeavier, less modular
StrengthWeakerStronger (kept for the frame)
PLAPETG
UsePrototypesFinal parts
Cost / print timeCheaper, fasterLonger print time
StrengthLess durableStronger
HeatMelts in extreme heatBetter heat resistance

The filament split came from testing each material. PETG shells also protect the electronics while weighing less than aluminum panels.

Designing to take a hit

  • Low center of gravity, 2.625 in up and 1.428 in back from center, so defenders can't easily push the robot.
  • 30A durometer mecanum rollers for traction and acceleration under contact.
  • Durable side plates, checked with FEA and drop tests.
  • Result: the robot held up through very aggressive defense at Regionals and States with zero mechanical failures on the season.