Skip to content
CrocoDocs
Starter GuideProgrammingEngineeringDesignPortfolio
Documentation

Introduction

IntroductionBIOBUZZ game overview

Getting started

Getting startedBlocksOnBot JavaAndroid StudioYour first OpModeJava basicsMotors and servosNonblocking codeDebugging robot code

Control systems

Control systemsJoystick mappingField-centric mecanum drivePID controlFeedforwardFlywheel velocity controlSystem identificationMotion profilingKalman filterLow-pass filter

Autonomous

AutonomousTimed and encoder movementOdometryLocalization troubleshootingMotion planningReliable autonomous sequencesPure PursuitSensor fusionAuto to TeleOp handoff

Season topics

Season topicsProjectile mathematicsTurret aimingShooting on the move

Code practices

Code practicesNaming conventionsCode organizationLoop timing and bulk readsFormattingComments and documentationTeam collaboration

Libraries

LibrariesNextFTCFTCLibSolversLibPedro PathingRoad RunnerFTC DashboardMercurial v2Mercurial v1PanelsSloth

Community software

Community softwareBlaze FTCOpenLoopHive Vision

Sensors and vision

Vision overviewVision basicsLimelight 3A
Starter Guide
Engineering
Design
Portfolio
Appearance

FTCLib

Run a command sequence after START and clean up when it ends

FTCLib provides utilities and a command scheduler. A command describes an action; the scheduler it, advances it, and checks whether it has finished. This page uses a short test to show that lifecycle.

Installation

The example uses org.ftclib.ftclib:core:2.1.1. Follow the author's installation guide for repositories and project setup. FTCLib and the FTC SDK have independent version numbers; choose compatible releases. These APIs were checked against FTC SDK 12.0.0.

Checked 14 October 2026: 2.1.1 is still the latest release, originally published in February 2023. The repository is unarchived but release activity is slow. SolversLib is a separately maintained fork with different imports and lifecycle details; use its own installation and migration instructions if choosing that route.

Command sequence

An InstantCommand runs its action once. WaitCommand(1000) waits one second while the scheduler continues running. A SequentialCommandGroup initializes the next command when the previous one finishes.

Scheduling can execute code immediately. In FTCLib 2.1.1, schedule() calls the command's initialize(). A sequential group's first instant action can therefore run during the scheduling call. Constructing a sequence during INIT is fine; schedule this motor sequence only after START. Putting it in CommandOpMode.initialize() would request motor power during INIT.

Motor test

Configure an unloaded motor as testMotor. Save the selected language's complete file as FTCLibMotorTest.java or FTCLibMotorTest.kt under TeamCode. The Kotlin tab requires Kotlin support in the project.

package org.firstinspires.ftc.teamcode;

import com.arcrobotics.ftclib.command.Command;
import com.arcrobotics.ftclib.command.CommandScheduler;
import com.arcrobotics.ftclib.command.InstantCommand;
import com.arcrobotics.ftclib.command.SequentialCommandGroup;
import com.arcrobotics.ftclib.command.WaitCommand;
import com.qualcomm.robotcore.eventloop.opmode.Autonomous;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.hardware.DcMotor;

@Autonomous(name = "FTCLib: Timed Motor Test")
public class FTCLibMotorTest extends LinearOpMode {
    @Override
    public void runOpMode() {
        DcMotor motor = hardwareMap.get(DcMotor.class, "testMotor");
        motor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);
        Command sequence = new SequentialCommandGroup(
            new InstantCommand(() -> motor.setPower(0.15)),
            new WaitCommand(1000),
            new InstantCommand(() -> motor.setPower(0.0))
        );
        CommandScheduler scheduler = CommandScheduler.getInstance();
        telemetry.addLine("Test unloaded, then press START.");
        telemetry.update();
        waitForStart();
        if (!opModeIsActive()) return;
        try {
            scheduler.schedule(sequence);
            while (opModeIsActive() && scheduler.isScheduled(sequence)) {
                scheduler.run();
            }
        } finally {
            scheduler.cancel(sequence);
            motor.setPower(0.0);
            scheduler.reset();
        }
    }
}
package org.firstinspires.ftc.teamcode

import com.arcrobotics.ftclib.command.CommandScheduler
import com.arcrobotics.ftclib.command.InstantCommand
import com.arcrobotics.ftclib.command.SequentialCommandGroup
import com.arcrobotics.ftclib.command.WaitCommand
import com.qualcomm.robotcore.eventloop.opmode.Autonomous
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode
import com.qualcomm.robotcore.hardware.DcMotor

@Autonomous(name = "FTCLib: Timed Motor Test")
class FTCLibMotorTest : LinearOpMode() {
    override fun runOpMode() {
        val motor = hardwareMap.get(DcMotor::class.java, "testMotor")
        motor.zeroPowerBehavior = DcMotor.ZeroPowerBehavior.BRAKE
        val sequence = SequentialCommandGroup(
            InstantCommand({ motor.power = 0.15 }),
            WaitCommand(1000),
            InstantCommand({ motor.power = 0.0 })
        )
        val scheduler = CommandScheduler.getInstance()
        telemetry.addLine("Test unloaded, then press START.")
        telemetry.update()
        waitForStart()
        if (!opModeIsActive()) return
        try {
            scheduler.schedule(sequence)
            while (opModeIsActive() && scheduler.isScheduled(sequence)) {
                scheduler.run()
            }
        } finally {
            scheduler.cancel(sequence)
            motor.power = 0.0
            scheduler.reset()
        }
    }
}

INIT maps the device and builds the sequence. START allows scheduling. The active loop advances the scheduler until the sequence finishes or STOP is requested. The finally block cancels the sequence, writes zero, and resets this practice 's scheduler even if execution exits with an exception.

The 0.15 power is an example for an unloaded test. It is not a position controller or a suitable holding command for a loaded lift. Before adding other commands, give commands that share a the same subsystem requirement so the scheduler can prevent conflicts.

Testing

Select the OpMode and press INIT: the motor should remain stopped. Press START: it should run briefly, then stop. Repeat and press STOP during the wait. Confirm that no later action restarts it. Keep the test mechanism clear and use a device whose low-power behavior you have checked.

Pure Pursuit

FTCLib's own documentation labels its Pure Pursuit implementation buggy and does not recommend it. Use the Pure Pursuit article for geometry, and compare maintained implementations such as Pedro Pathing and Road Runner for a robot route.

Sources

  • FTCLib 2.1.1 scheduler source
  • SequentialCommandGroup source
  • FTCLib Pure Pursuit warning
  • author's installation guide

NextFTC

Current NextFTC v2 modules, robot structure, triggers, and command model

SolversLib

Install SolversLib core and run a command sequence with a responsive OpMode

On this page

InstallationCommand sequenceMotor testTestingPure PursuitSources