FRC / Vision / Controls

Turret Auto Align

A vision-assisted FRC turret alignment system that combines Java robot logic, Limelight targeting, AprilTag measurements, and a Python tuning pipeline to keep the turret centered while the robot is moving.

Controls and ML tuningJavaLimelightAprilTagPython

Vision Pipeline

Combined Limelight values with AprilTag-based measurements to estimate target offset and maintain a stable lock under changing field conditions.

Java Control Loop

Structured the robot loop around sensor refresh, PID correction, and fallback handling so the turret behaved predictably when targets dropped out.

ML-assisted Tuning

Turned robot log data into response features and trained regressors that suggested improved PID multipliers from observed motion quality.

Project Notes

The details that mattered.

What it did

The turret continuously selected a target, computed angular error, and corrected aim while the rest of the robot was in motion. The goal was not just static accuracy, but stable tracking under realistic match movement.

How tuning worked

I exported drivetrain and turret logs, extracted rise time, settling time, overshoot, steady-state error, and oscillation metrics, then trained separate regressors for P, I, and D multipliers. That gave the controls workflow a repeatable data loop instead of pure manual tuning.

Videos

Project demos and test footage.

Turret view and target lock

On-robot field test

Alignment behavior pass

Code

Python training backend

import pandas as pd
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_absolute_error

FEATURE_COLUMNS = [
    "rise_time",
    "settling_time",
    "overshoot_pct",
    "steady_state_error",
    "oscillation_score",
]

LABEL_COLUMNS = ["p_multiplier", "i_multiplier", "d_multiplier"]

df = pd.read_csv("datasets/step_features.csv").dropna(subset=LABEL_COLUMNS)
X = df[FEATURE_COLUMNS].fillna(0.0)

for label in LABEL_COLUMNS:
    X_train, X_test, y_train, y_test = train_test_split(
        X,
        df[label],
        test_size=0.2,
        random_state=42,
    )
    model = RandomForestRegressor(n_estimators=200, max_depth=8)
    model.fit(X_train, y_train)
    print(label, mean_absolute_error(y_test, model.predict(X_test)))