FIRST
Aoide

Aoide at Competition

Aoide is 4467's robot for the 2024 FIRST Robotics Competition, Crescendo.


Summary

Aoide was the robot I worked on during my rookie season of FRC. I held roles in software engineering, mechanical fabrication and design, and some electrical wiring. Being that it was my first season, there was a lot of learning through trial and error, but by the end of the season, I was able to have a tangible impact on the team and the robot.


Aoide was designed to be a robust "everything" robot with a low COG (8 in. high to be exact). It could play into every major game objective and strategy. For example, it could play a defensive role with the sturdy robot design. It could also play a passing or scoring role on offense with the ability to shoot cross field, into the goal, and amp. Not to mention, it could climb and score into the trap, which is considered one of the most difficult game objectives of all time. On the programming side of things, Aoide was programmed in Java and utilized an IO framework to allow for live data collection, future analysis, and simulation through AdvantageKit. It had 6 distinct subsystems, each with their own commands. It also had a near limitless amount of autonomous paths thanks to Choreo path generation and Pathplanner path splicing.


Aoide's build team consisted of around 10 students and 5 mentors. She was designed and built in around 7 weeks. She was programmed in about 3 weeks. She was expanded on through continuous iteration up until the final competiton through. While the robot didn't perform to the teams' expectations (Qualifying for the World Championship), it was still the top performing robot in the Western Pennsylvania region according to Expected Points Added advanced metric and it won awards at both competitons it competed at. Big shoutout to all of Titans! Especially our programming lead, Logan.


Mechanical Notebook

Aoide at Competition

Shoutout to my favorite captain and design lead, Ian. Check out his work here → Aoide Onshape


Drivetrain

Aoide Drivetrain!

Aoide's drivetrain used L3 gear ratio Mk4i modules with Kraken X60s as drive motors and Falcon 500s as azimuth motors. We originally had L3+ gear ratio but switched them out in favor of L3. We did this because we realized we would need more torque and acceleration as defense and collisions were a big part of this year's game. Each swerve module had a built-in encoder. Additionally, we used a Pigeon 2 IMU and 2 cameras mounted on to modules to assist with localization.


Intake

Aoide Intake!

We had an Under-The-Bumper intake attached to the drivetrain frame. It had three deadaxle rollers, two polycarb with silicon tubing for initial contact and a third rube with rubber coating for centering, powered by a 1:1 kraken and driven through a belt-pulley system. On each side, there were two 3" compliant wheels for centering. These were powered by a 5:1 Kraken driven through a different belt-pulley system. The intake was an instagrab handoff straight into the shooter. The intake plates were thickened throughout the season, all the way up to 1/4 aluminum because they kept getting bent from all the collisions. Even after the change, they still got bent lol. Lastly, we had another camera mounted to the intake for further vision assistance.


Shooter

Aoide Shooter!

Aoide's shooter had two sets of polycarb + silicon rollers powered by a Kraken with a 1:5:1 ratio. The shooter used two sets of 4" urethane wheels with 1/2 in of compression to create spin. Both sides were individually powered by a Falcon 500. The shooter rotated around a MAXSpline and sprocket to shoot or pass at a variety of angles and position correctly to score into the amp. In late iterations, polycarb "horns" were added to the shooter to push open a trapdoor-like obstacle to enable scoring into the trap.


Arm

Aoide Arm!

The arm was a virtual four-bar, which featured two MAXSpline cross shafts to rotate the shoulder and wrist joints by chain and sprocket. The shoulder was powered by two Krakens in a custom 202.8:1 gearbox while the wrist was also powered by two Krakens but with a custom 152.1:1 gearbox. The arm pops up completely vertically for climbing and amp scoring. This system proved to be a slight pain for our team. A couple weeks after practicing with the robot, we discovered that the shoulder had a slight tilt. At first, we thought it may have been caused by uneven tensioning of the chains, so we attempted to even out the chain tensioner bolts. Must have been a placebo effect because we thought we had mostly fixed the issue. As we continued troubleshooting, we investigated several other possible causes, including being assembled out of square. Although increasing chain tension and reassembling the shooter improved the symptoms, neither fully resolved the problem. At competition, we eventually discovered that one of the shoulder sprockets had been clocked incorrectly relative to the other side. After correcting the sprocket clocking, the shoulder returned to proper alignment and operated as intended.


Climber

Aoide Climbers!

The climber was a custom telescoping tube design. Each tube was powered by a Kraken with a 36:1 Max Planetary gearbox. The entire elevator system was driven through a spool and rope mechanism. As the spool winds up, climber extends and vice versa. On each tube there were constant force springs to aid with lifting the stages of the climber as it lifted the hefty 125ish pound robot. Lastly, a custom slotted chain hook was what kept the robot secured firmly while climbing.


Takeaways

I hate bumpers (common theme of every robot to come). Like other teams, we had issues with the bumpers getting beat up/broken during competiton. Unlike many teams, we decided to do reversible bumpers. These were hell to make, and in a game where bumpers were broken left and right, we wouldn't be able to quickly make a spare set if they broke. Additionally, the elastic used to be able to flip the fabric got stuck in weird places, such as in the swerve drive, and costed us performance-wise. Everything that could break, broke. Including the aluminum brackets with the velcro to switch the bumper fabric. The bracket was bent so bad, we hammered it back into place between matches. I made too many sets of bumpers this year, and I would unfortunately continue to do that. One more mechanical highlight or lowlight from this season was me snapping one of the shoulder chains. Wasn't a mechanical oversight more so a personal oversight. After changing a battery one time, I forgot to set the robot back down to a resting position and left it resting completely vertical with the shooter horizontal. By default, the driver sets the robot to stow position upon start. With the arm being a virtual four-bar design, the shooter ate into the arm chain while going to the stow position and snap. That never happened again, fortunately.


Broken Bumpers!

This season I was mainly a programmer. However, having spent way too many hours at the workshop and practice field (peaking at around 60ish hours a week), I learned a lot about the mechanical process. From fabrication to assembly, I was eased into a lot of different roles and garnered a ton of nicknames: battery boy, bumper boy, Sewickley, etc... I wasn't an expert by any means, but I definitely developed the skils to be a big-time contributor in the following season.


Programming Documentation

General Overview

Aoide was coded in Java through IntelliJ and used the Shuffleboard dashboard. To improve maintainability and logging, we decided to use an IO layer architecture. Hardware interactions are isolated in IO classes, while subsystem classes contain control logic. This separation allowed for AdvantageKit logging, simulation capabilities, and simpler hardware migrations throughout the season. Throughout the season, I set up the baseline for these IO/subsystem classes. I created them, added functions to log data, carry out commands, etc. Check out the repository here → Aoide Github


Subsystems

The most complicated system I helped on was the swerve drive. Probably the most complex thing I worked on was proportional velocity control for the swerve drivetrain. While the implementation itself was straightforward, understanding the underlying control concepts was a little tricky. Rather than using linear joystick scaling, we implemented cubic scaling to improve low-speed precision while maintaining full-speed capability at maximum joystick deflection. I also contributed to drivetrain deadbanding, feedforward characterization, and PID tuning. We used WPILib SysId to model drivetrain behavior and determine feedforward gains, then tuned PID controllers through telemetry analysis to improve overall control performance. To maintain accurate field localization, the robot used swerve odometry derived from wheel encoder and gyro measurements. To reduce accumulated drift, AprilTag-based vision measurements were fused with odometry through a pose estimator, providing accurate field-relative localization.


The arm is probably the most complicated algorithm on Aoide. While I didn't program this, I can explain the overarching ideas. The arm subsystem uses a state machine–based control system where each of the 11 robot modes corresponds to a specific behavior with predefined arm and wrist setpoints. The active state determines what angles the arm should move to, and the system continuously updates motor commands based on that state. The transitions between actions became more predictable and easier to manage because we turned an otherwise complex behavior into a set of discrete behaviors. Each state also applies its own motion rules, such as velocity limits and safety constraints, to ensure stable and collision-free movement between the independently-moving shoulder and the dependently-moving wrist. Lastly, a climber lock input acts as a safety interlock between subsystems, overriding normal state changes when the climber is active so the arm prioritizes climbing-related positions and avoids configurations that could interfere with the climber.



Our "aimbot" system combined vision, drivetrain alignment, and rpm control to improve scoring consistency. Using Aoide's estimated field position, the aimbot command calculated the required wrist angle and flywheel speeds based on the distance to the speaker. The wrist angle was determined using a polynomial curve fit generated from successful shot data, allowing the robot to automatically adjust its trajectory from different locations on the field. Originally, the system relied on interpolation tables that mapped distance to wrist angles and flywheel RPMs. While functional, the interpolation-based approach produced inconsistent results while shooting. To improve reliability, the wrist angle calculation was replaced with a fitted equation and the shooter RPMs were simplified into several distance-based operating zones. Before a note could be fired, the system verified three conditions: the flywheels had reached their target rpm, the drivetrain was aligned with the target within an acceptable angular error, and a TOF sensor confirmed that a note was present in the robot. All in all, this reduced wasted shots and increased accuracy.



The last two subsystems I'm especially proud of because I programmed these by myself. The climber managed both climber motors and introduces a climber lock mechanism that acts as a safety interlock for the rest of the robot. Whenever the climber is activated, a lock flag is set that other subsystems can check before performing potentially unsafe actions. The subsystem supports both manual voltage control and closed-loop position control, allowing the climber to be engaged directly by the driver or commanded to specific positions. The LED subsystem provided visual feedback to drivers using a CANdle LED controller. Rather than requiring other subsystems to directly control the LEDs, it accepts a boolean supplier that continuously reports whether the robot has a note. Based on this state, the subsystem automatically switches between different LED animations to indicate whether the robot is loaded or empty.



Autonomous

Last but not least, autonomous. We used a combination of Choreo and PathPlanner to create autonomous routines. Choreo generated optimized trajectories between points on the field, while PathPlanner allowed us to connect paths together and trigger commands such as shooting and intake at specific waypoints. The completed routines were loaded into a WPILib utility called a SendableChooser, which allowed drivers to select the desired autonomous routine from the dashboard before the match began. We could make a near limitless number of paths, but we had 10 competition autonomous options that encompassed every starting location. In addition, these paths were 90% consistent. Last thing I learned was to never have an auto routine run full speed before fully testing it. We forgot to do that once and the robot, with no bumpers, slammed into the wall (oops).



Gallery