Skip to content
Apex Robotics
[ 04 / CAD ]

Designed in CAD, built in shop.

Every subsystem is modelled before a single part is cut. Until our assemblies are public, this sheet shows the concept model generated from our code — take it apart, cut a section through it, and read why each mechanism is the shape it is.

DWG
DWG-004
REV
A
UPDATED
2026-10-12
TOOLS
Onshape · Fusion 360
MODEL
Concept · real CAD pending

Concept model · generated from RobotConstants.java · real CAD pending

Revisions
RevDescriptionDate
AFirst issue — concept model generated from RobotConstants.java2026-10-12
[ VIEW 1 / GENERAL ASSEMBLY ]

Take it apart. Cut through it.

Pick an assembly, then explode it or slide the section plane through it. The dimensions on the drawing are the team's own numbers.

CAD-001All eight subsystems

Full assembly

Eight subsystems packaged inside the 18 in start cube: drivetrain, odometry, electronics, intake, hopper, turret, shooter and vision.

Parts list · item = balloon

  • Item 1: Drivetrain
  • Item 2: Odometry
  • Item 3: Intake
  • Item 4: Hopper + sorter
  • Item 5: Turret
  • Item 6: Shooter
  • Item 7: VisionCAD-001
  • Item 8: ElectronicsCAD-001
Public Onshape link pending

Concept model · generated from RobotConstants.java · real CAD pending

Dimensions are the team's numbers: the R102 start cube, the 14 in muzzle and the fixed 40° hood.

Critical dimensions

  • 18.00 in

    Start cubeManual · R102

  • 14.00 in

    Muzzle heightShoot.MUZZLE_Z_IN

  • 40°

    Fixed hoodShoot.LAUNCH_PITCH_DEG

  • ±170°

    Turret travelTurret.MIN / MAX · 5 : 1

  • Ø4.00 in

    FlywheelShoot.FLYWHEEL_DIAMETER_IN

  • Ø104 mm

    Mecanum × 4Drive.WHEEL_DIAMETER_IN

[ LIST / MODEL INDEX ]

Four documents, one robot.

Each subsystem lives in its own CAD document. The public links go here as soon as the documents are shared.

  1. CAD-001

    Full assembly

    All eight subsystems

    Public Onshape link pending
  2. CAD-002

    Drivetrain

    Drivetrain · odometry

    Public Onshape link pending
  3. CAD-003

    Intake

    Intake · hopper + sorter

    Public Onshape link pending
  4. CAD-004

    Scoring / turret

    Turret · shooter

    Public Onshape link pending
[ DS / DESIGN STORIES ]

Why each mechanism is the shape it is.

Requirement, options, decision and the maths behind it, what changed, and what could still go wrong, for each mechanism.

DS-01Drivetrain + odometry

Know where the robot is — without the AprilTags.

BIOBUZZ™ AprilTags ride on the HIVE, and the HIVE tips. So the robot carries its own position sensor on the drivetrain, and vision only measures the target.

  1. Requirement

    • R102 in the Competition Manual (opens in a new tab)

      Start inside an 18 × 18 × 18 in cube. The drivetrain sets the footprint.

      Competition Manual TU04 · R102

    • Reposition while the turret keeps its aim — strafe and turn at the same time.

      docs/03-ARCHITECTURE.md · shooting while moving

    • “Since BIOBUZZ AprilTags move, they are not suitable for absolute Field Localization.”

      FTC SDK 12.0 release notes, quoted in docs/03-ARCHITECTURE.md

  2. Options

    Who answers “where is the robot?”

    • Usual FTC pattern

      AprilTags give an absolute pose; the goal is a hard-coded field constant.

    • What BIOBUZZ needsChosen

      Odometry localises the robot. Vision measures the target live.

    docs/03-ARCHITECTURE.md

  3. Decision + math

    • 4 × goBILDA 5203 motors (19.2 : 1, 312 RPM) on 104 mm mecanum wheels.
    • goBILDA Pinpoint (“odomcomp”) with two dead-wheel pods: the X pod 84 mm right of the tracking point, the Y pod 168 mm behind it.
    • Heading rate from the Pinpoint's fused IMU at 1500 Hz, plus 0.5 s of pose history so each camera frame meets the pose from when its shutter opened.
    Worked numbers
    Wheel104 mm ÷ 25.4Using 4.0 would read every distance 2.4 % short.4.094 in
    Ticks per inch537.7 ÷ (π × 4.094 in)41.80
    Free speed312 rpm ÷ 60 × π × 4.094 inAn upper bound: expect 53–58 in/s forward and 42–46 in/s strafing.66.9 in/s
    Stale frame60 in/s × 0.1 sWhy the pose history exists.6 in
  4. Iterations

    1. 2026-10-11

      Rewire: left drive motors to the Expansion Hub, right to the Control Hub. No Java changed — devices are found by name.

      hub-backup/README-rewire.md

    2. 2026-10-11

      Forward drove backward, cleanly, with no veer — so all four motor directions were flipped together.

      RobotConstants.java · Drive.REVERSE_*

  5. Risk

    • watch

      If the Pinpoint reports robot-relative velocity, the turret leads correctly along one axis and backwards along the other.

      Mitigation · T3 Velocity Frame Test answers it in about 20 s. Set to field-relative for now, on Pedro Pathing's evidence.

      RobotConstants.java · Odo.VELOCITY_IS_ROBOT_RELATIVE

    • watch

      Left and right sides sit on different hubs, so latency is asymmetric — in principle a slight veer under hard acceleration.

      Mitigation · Usually smaller than wheel scrub and battery sag. Only chase it if odometry tuning can't explain a drift.

      hub-backup/README-rewire.md

DS-02Intake + sorter

Hold four, and never the opponent's NECTAR.

The colour sensor in the hopper throat has two jobs: choose the flywheel RPM for the ball it sees, and throw out the ball we aren't allowed to keep.

  1. Requirement

  2. Options

    How to tell the balls apart

    • Raw RGB

      Every channel scales with light: a yellow ball in shadow and a red ball in bright light can read alike.

    • Hue + saturationChosen

      Hue is the angle around the colour wheel and barely moves with brightness; saturation confirms it is a coloured object.

    BallSorter.java

    How NECTAR gets more RPM

    • Fixed RPM bump

      Only correct at the distance where it was measured.

    • Efficiency per ballChosen

      One number per ball type, correct at every distance.

    docs/03-ARCHITECTURE.md

  3. Decision + math

    • REV Color Sensor V3 in the hopper throat, 5–15 mm from the ball. A distance reading under 25 mm means a ball is present.
    • Hue windows: POLLEN 35°–85°, RED 340°–20° (wrapping through 0°), BLUE 190°–265°. Below 0.35 saturation counts as no ball.
    • Opponent NECTAR is ejected automatically (BallSorter.shouldReject() in TeleOpMain).
    Worked numbers
    Flywheel speedrpm = 60 · v ÷ (η · π · D)
    POLLEN, 96 in shotη = 0.502,251 rpm
    NECTAR, same shotη = 0.4219 % more RPM for the same arc.2,680 rpm
    PRB0°90°180°270°SAT ≥ 0.35BALL < 25 mm
    Detail B · hue windows · P 35–85° · R 340–20° · B 190–265°
  4. Iterations

    Pending — log from build

    Every change to the real mechanism gets a dated row here.

  5. Risk

    • planned

      Alliance colour left on the wrong setting: the sorter keeps their NECTAR and rejects ours.

      Mitigation · Duplicate TeleOpMain into a red and a blue version, so nobody has to remember.

      docs/03-ARCHITECTURE.md

    • planned

      The hue windows are first guesses until measured under venue lighting.

      Mitigation · T6 Color Sensor Calibration prints hue; adjust RobotConstants.Colors to match.

      RobotConstants.java · Colors (TUNE ME)

DS-03Turret

Hold the aim while the chassis turns underneath.

When the chassis spins counter-clockwise at ω, the turret has to spin clockwise at ω just to stand still in the field.

Turret motor not yet configured on the robot (config name “turret” reserved).

  1. Requirement

    • R105 in the Competition Manual (opens in a new tab)

      After the start, stay inside 18 × 24 × 29 in. A turret turning in the horizontal plane is legal only if its maximum extent stays inside (Fig. 12-6).

      Competition Manual TU04 · R105

    • Hold a field-frame bearing while the robot drives and spins.

      Turret.java

  2. Options

    Control law

    • Position PID only

      Always lags while the chassis spins: it reacts only after an error exists.

    • PID + heading feedforwardChosen

      Adds −ω · kV before the PID sees an error. ω comes from the Pinpoint at 1500 Hz.

    Turret.java

    Trade study · external reduction G
    GTicks / °Slew °/sNote
    1 : 11.491,872Not viable — too coarse
    5 : 17.47374Chosen
    6.25 : 19.34300In the 5–8 band
    8 : 111.95234In the 5–8 band
    10 : 114.94187—
    20 : 129.8794Too slow

    RobotConstants.java · comment above Turret.TICKS_PER_RAD

  3. Decision + math

    • ±170° of travel through one clean external reduction, G = 5.
    • turretAngle = wrap(azimuth − robotHeading), output += −ω · kV with kV = 0.11.
    • On target within 1.5°; power capped at 85 %.
    Worked numbers
    Resolution537.7 × 5 ÷ 2π7.5 ticks per degree.427.9 ticks/rad
    Free slew1872 ÷ 5≈ 318 °/s at the 85 % power cap.374 °/s
    Motor turns, full travel340° × 5 ÷ 360°4.7 turns
  4. Iterations

    Pending — log from build

    Every change to the real mechanism gets a dated row here.

  5. Risk

    • planned

      Wiring tear-out: full travel is 4.7 turns of the motor shaft.

      Mitigation · Route the turret wiring with a service loop.

      RobotConstants.java · Turret

    • planned

      Backlash, not encoder resolution, sets the accuracy — and every gear stage adds its own.

      Mitigation · One external stage. Measure ticks per radian against a protractor instead of trusting the nameplate ratio.

      RobotConstants.java · Turret.TICKS_PER_RAD

    • in code

      A target in the 20° dead zone behind the robot.

      Mitigation · The solver refuses (“turret can't reach that angle — rotate the chassis”) and the PID never pushes past ±170°.

      Ballistics.java · Turret.java

DS-04Shooter

A soft lob, solved in closed form.

A HIVE TIP is worth 20 points against 2 for each element in a CELL, so the shooter is built for repeatable shots rather than long ones.

  1. Requirement

    • Drop balls into the upward CELL, an opening about 20 × 14 in.

      Competition Manual TU04 · 9.6.2

    • HIVE TIP 20 points vs 2 per element in a CELL — consistency is what scores.

      Competition Manual TU04 · Table 10-2

    • Launch POLLEN (2.8 in) and NECTAR (3.6 in) off the same wheel.

      BallType.java

  2. Options

    Hood

    • Adjustable

      Angle and speed are both unknowns, so the solver has to search.

    • Fixed 40°Chosen

      Flight time falls straight out of the geometry and the solver only picks RPM. 35–45° is the usual sweet spot for dropping into an upward opening.

    RobotConstants.java · Shoot.LAUNCH_PITCH_DEG · docs/03-ARCHITECTURE.md

    Drive

    • Belted

      Moves the motor off its peak-power point and makes recovery between shots worse.

    • Direct 1 : 1Chosen

      Held at 2700–2900 rpm, a bare 5203 makes 22.6 W of its 22.64 W peak.

    Shooter.java

    Motors

    • Two

      Buys nothing here.

    • OneChosen

      1.1 J (POLLEN) or 1.8 J (NECTAR) per shot against ~25 J stored in the wheel: 65–108 rpm of droop, recovered in 0.05–0.08 s.

    Shooter.java

    Speed control

    • Power number

      A different RPM at 13.5 V than at 11.8 V, and the wheel slows after every shot.

    • Closed-loop RPMChosen

      The Hub's velocity PIDF holds the RPM, and no ball feeds until it has settled.

    Shooter.java

  3. Decision + math

    • One 4.0 in flywheel on a goBILDA 5203 (1 : 1, 6000 rpm free) under a fixed 40° hood. The muzzle sits 14 in up and 2 in forward.
    • Ready to fire after ±100 rpm has held for 0.15 s. Commands ramp at 4000 rpm/s and clamp at 5000 rpm.
    Worked numbers
    Flight timet = √(2(d·tanθ − h) ÷ g)0.532 s
    Exit speedv = d ÷ (t · cosθ)236 in/s
    Flywheel60 · v ÷ (0.50 · π · 4 in)2,251 rpm
    Apexz₀ + v_z² ÷ 2g43.7 in
    Range per rpm≈ 0.117 in/rpmRoughly half a CELL opening — why the ready gate exists.40 rpm ≈ 4.7 in
  4. Iterations

    1. Undated

      Flywheel direction set explicitly. It had been running whichever way the motor was wired — on this robot, backwards.

      RobotConstants.java · Shoot.REVERSE_FLYWHEEL

  5. Risk

    • open

      The 0.8 in gap between POLLEN and NECTAR is 2–4× the usable compression of a compliant wheel, so one fixed gap can't grip both.

      Mitigation · Needs a sprung or floating hood — no PIDF value fixes a ball that isn't touching the wheel.

      Shooter.java

    • in code

      A stepped RPM command draws close to the 9.2 A stall current for over a second — a Control Hub brown-out mid-match.

      Mitigation · Commands ramp at 4000 rpm/s.

      RobotConstants.java · Shoot.RPM_RAMP_PER_SEC

    • in code

      28 counts/rev is the coarsest velocity feedback on the robot.

      Mitigation · Average 5 samples; hold a 100 rpm tolerance.

      Shooter.java

[ T / TOOLCHAIN ]

From model to part.

  1. T-01CAD

    Onshape

    Subsystem models and assemblies. Exports GLB natively since release 1.217.

  2. T-02CAD

    Fusion 360

    No native GLB: export STEP, import it into Onshape, export GLB from there.

  3. T-03Fab

    3D print

    Printed parts.

  4. T-04Fab

    Mill

    Machined parts.

Drawing notes and title block

Notes

  1. 01Concept model generated from RobotConstants.java. It shows the team's real numbers; geometry between them is estimated until the real CAD is public.
  2. 02Dimensions in inches [millimetres]. Angles in degrees.
  3. 03Robot frame: +X forward, +Y left, +Z up, heading counter-clockwise — the same convention as every file in TeamCode.
  4. 04Values marked TUNE ME in RobotConstants.java (muzzle position, hood angle, pod offsets, hue windows) are design values until measured on the built robot.
  5. 05Rules cited from the BIOBUZZ™ Competition Manual as of Team Update 04 — ftc.game/manual ↗ (opens in a new tab).
Drawn by
Apex Robotics
FTC 36674 · Tracy, CA
Title
APEX-R1 general assembly
Drawn
Apex Robotics
Date
2026-10-12
Units
in [mm]
Dwg no
DWG-004
Rev
A
Sheet
1 of 1
Scale
1 : 4
Proj.
Status
Concept model · real CAD pending