# ftc-lib ## Yes, ts was generated... No I do not believe in an AI takeover **ftc-lib** is a high-performance, state-machine-driven framework designed for FTC teams who prioritize clean code, modularity, and hardware optimization. It provides a robust abstraction layer over standard FTC OpModes, integrating **PedroPathing** for precision movement and **Panels (Sloth)** for live configuration and telemetry. --- ## 🚀 Key Features * **Template Method Pattern:** A locked-down backend that handles the "boring stuff" (Bulk reads, FPS capping, Telemetry timing) so you only write robot logic. * **Subsystem Architecture:** Fully isolated mechanisms with their own internal "Micro-States." * **Hierarchical State Machines:** Orchestrate complex robot actions by mapping a "Global State" to specific "Subsystem States." * **Automatic Hardware Optimization:** * **Bulk Reads:** Automatically sets all expansion hubs to Manual Caching mode for the fastest possible loop times. * **FPS Capping:** Prevents CPU/Battery waste by locking loop speeds to a target (e.g., 50 FPS). * **Stateful PID Control:** A built-in PID utility that handles time-deltas ($dt$) and integral sums internally. * **Unified Telemetry:** A joined engine that pipes data to both the Driver Station and the **Panels** dashboard simultaneously. * **Live Tuning:** Centralized `Constants.java` utilizing `@Configurable` for real-time value editing without recompiling. --- ## 📂 Project Structure ```text teamcode/ ├── lib/ # The Core Framework (Don't touch) │ ├── BaseStateOpMode.java # The engine that runs the robot │ ├── Subsystem.java # The blueprint for all mechanisms │ ├── SubsystemManager.java # Automates the lifecycle of subsystems │ └── PIDController.java # Stateful math utility ├── subsystems/ # Your robot parts (Drivetrain, Lift, Intake) ├── util/ # Utilities (AutoTransfer, FPSCounter) ├── Constants.java # The "Control Panel" for the entire robot └── opmodes/ # Your actual TeleOp and Autonomous files ``` --- ## 🛠 Usage Guide ### 1. Define your Constants Use the `Constants.java` file to store every hardware name, PID value, and speed multiplier. ```java @Configurable public static class LIFT { public static double kP = 0.015; public static int SCORING_POS = 2500; } ``` ### 2. Create a Subsystem Inherit from `Subsystem`. Define "Micro-States" for this specific mechanism. ```java public class LiftSubsystem extends Subsystem { public enum LiftState { IDLE, EXTENDING } private LiftState state = LiftState.IDLE; @Override public void update() { // Run PID logic here } } ``` ### 3. Build your TeleOp Inherit from `BaseStateOpMode`. This gives you the `stateMachineUpdate()` hook where you map gamepad inputs to states. ```java @TeleOp public class MainTeleOp extends BaseStateOpMode { @Override protected void setupSubsystems() { manager.register(new DriveSubsystem(), new LiftSubsystem()); } @Override protected void stateMachineUpdate() { if (gamepad1.aWasPressed()) { robotState = GlobalState.SCORING; } } } ``` --- ## ⚡ Performance Details ### The "Tick" Lifecycle Every loop, `ftc-lib` executes in this strict order: 1. **Hardware Sync:** Clears Bulk Cache on all Hubs. 2. **Logic Tick:** Runs your `stateMachineUpdate()`. 3. **Subsystem Tick:** All subsystems calculate PIDs and update motor powers. 4. **Telemetry Gate:** If the `TELEMETRY_DELAY_MS` has passed, it pushes data to Panels and the Driver Station. 5. **Sync Sleep:** Adjusts thread sleep time to maintain a consistent `TARGET_FPS`. ### Auton-to-TeleOp Persistence Using the `AutoTransfer` utility, this library can automatically carry over the robot's end-of-auton position (from **PedroPathing**) and the Alliance color into TeleOp, ensuring your field-centric drive and automation remain seamless. --- ## 📦 Dependencies * [PedroPathing](https://github.com/pedropathing/pedro-pathing) * [Panels/Configurables (Sloth)](https://panels.bylazar.com/) * [Panels/Telemetry (Sloth)](https://panels.bylazar.com/) --- ## 🤝 Contribution When adding new subsystems: 1. Ensure all hardware names are in `Constants`. 2. Ensure `publishTelemetry` only sends data when `GLOBAL.DEBUG_MODE` is true. 3. Never use `sleep()` inside a subsystem; use state timers instead.