Create Your Test Drivetrain Program¶
Configure a drivetrain project for your motor controllers and deploy it to Systemcore. The next page covers motor testing with the wheels off the floor.
Use the Java, C++, or Python walkthrough below, or start with a Blocks sample.
Before beginning, confirm that WPILib and any language-specific tools from Step 2 are installed, Step 3 is complete, and you know the motor-controller type, port numbers or CAN IDs, and team number for your robot.
Start with the WPILib Getting Started example, then check its motor configuration before deploying it to your robot.
Important
Choose the hardware tab that matches the motor controllers on your robot. The PWM tab covers the motor controller included in the FRC Kit of Parts. The CTRE tabs cover Talon controllers, and the REV tab covers SPARK controllers. Before deploying a CAN example, install the required vendor library, update the devices, and assign unique CAN IDs using the manufacturer’s instructions.
Starting a Drivetrain Project in Blocks¶
In the Blocks editor, select Samples…, choose a drivetrain sample, then select Create New Project From Sample to make an editable copy. Choose the sample that matches your hardware:
DifferentialDrive301: a two-motor differential drivetrain with A301 motor controllers.
MecanumRobot301: a four-motor mecanum drivetrain with A301 motor controllers.
MecanumRobotExpansionHub: a four-motor mecanum drivetrain with motors connected to a REV Expansion Hub.
See Complete Drivetrain Samples for screenshots and links to each sample’s source. Before running a sample, check the motor connections, controller assignment, and inversion against your robot. A sample for a different motor controller is not a drop-in replacement for your hardware.
Note
The detailed Systemcore Blocks deployment walkthrough is still being completed. Once your program is deployed, FRC teams can follow Running Your Test Program for the pre-enable checks and first drive.
Note
More drivetrain examples for Blocks are coming soon.
The remaining sections describe the Java, C++, and Python workflow.
Creating a New WPILib Project (Java/C++)¶
Open WPILib VS Code. Open the WPILib command palette and select Create a new project:

The WPILib New Project Creator opens.

Select Example, then Next. This starts from a working WPILib example instead of an empty template.
The next page asks for a language and project base.

Language: select Java or C++ to match your choice in Step 2.
Project Base: select Getting Started for this walkthrough.
After making the selections, click Next.
On the Project and Configuration page, choose where to save the project and enter your team number.

Base Folder: This determines the folder in which the robot project will be located.
Project Name: The name of the robot project. This also specifies the name that the project folder will be given if the Create New Folder box is checked.
Create a New Folder: If this is checked, a new folder will be created to hold the project within the previously-specified folder. If it is not checked, the project will be located directly in the previously-specified folder. An error will be thrown if the folder is not empty and this is not checked.
Team Number: The team number for the project, which will be used for package names within the project and to locate the robot when deploying code.
Enable Desktop Support: Enables unit test and simulation support (see Introduction to Robot Simulation). While WPILib supports this, third party software libraries may not. If libraries do not support desktop, then your code may not compile or may crash. It should be left unchecked unless unit testing or simulation is needed and all libraries support it. For this example, do not check this box.
Warning
Creating projects on OneDrive is not supported as OneDrive’s caching interferes with the build system. Some Windows installations put the Documents and Desktop folders on OneDrive by default.
Once all the above have been configured, click Next.
This will bring up the Review and Create window. The Review and Create page shows the settings you selected.

Check the language, example, folder, and team number. Use Back to correct a setting, then select Create Project.
Expected result: VS Code offers to open the new project. If creation fails, read the error notification before trying again.
Note
Any errors in project generation will appear in the bottom right-hand corner of the screen.
Opening the New Project¶

Accept the prompt to open your new project. To open it later, press Ctrl+K then Ctrl+O (or Command+O on macOS) and select the project folder.

Click Yes I trust the authors.
The file explorer shows the project folders. Open the Robot source file to inspect the example you will configure in the following sections.

C++ Configurations (C++ Only)¶
For a C++ project, accept the prompt to refresh C++ configurations. Select Yes to set up IntelliSense for this project.

Creating a New WPILib Project (Python)¶
Running the robotpy init command will initialize a new robot project:
py -3 -m robotpy init
python3 -m robotpy init
python3 -m robotpy init
This will create a robot.py and pyproject.toml file, but will not overwrite an existing file.
The
pyproject.tomlfile contains the requirements for your project, which are downloaded and installed via therobotpy synccommand.The
robot.pyfile is where you will put your Robot class.
See also
Basic Drivetrain Example¶
Read the complete PWM example below to see how the Robot class connects controller input to motor output. Then use the hardware tabs in the following sections to configure the example for your motor controllers.
Note
the Python example below is from https://github.com/robotpy/mostrobotpy/tree/main/examples/robot/GettingStarted
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5package org.wpilib.examples.gettingstarted;
6
7import org.wpilib.drive.DifferentialDrive;
8import org.wpilib.drivers.motor.PWMSparkMax;
9import org.wpilib.driverstation.Gamepad;
10import org.wpilib.framework.TimedRobot;
11import org.wpilib.system.Timer;
12
13/**
14 * The methods in this class are called automatically corresponding to each mode, as described in
15 * the TimedRobot documentation. If you change the name of this class or the package after creating
16 * this project, you must also update the manifest file in the resource directory.
17 */
18public class Robot extends TimedRobot {
19 private final PWMSparkMax leftDrive = new PWMSparkMax(0);
20 private final PWMSparkMax rightDrive = new PWMSparkMax(1);
21 private final DifferentialDrive robotDrive =
22 new DifferentialDrive(leftDrive::setThrottle, rightDrive::setThrottle);
23 private final Gamepad controller = new Gamepad(0);
24 private final Timer timer = new Timer();
25
26 /** Called once at the beginning of the robot program. */
27 public Robot() {
28 // We need to invert one side of the drivetrain so that positive voltages
29 // result in both sides moving forward. Depending on how your robot's
30 // gearbox is constructed, you might have to invert the left side instead.
31 rightDrive.setInverted(true);
32 }
33
34 /** This function is run once each time the robot enters autonomous mode. */
35 @Override
36 public void autonomousInit() {
37 timer.restart();
38 }
39
40 /** This function is called periodically during autonomous. */
41 @Override
42 public void autonomousPeriodic() {
43 // Drive for 2 seconds
44 if (timer.get() < 2.0) {
45 // Drive forwards half velocity, make sure to turn input squaring off
46 robotDrive.arcadeDrive(0.5, 0.0, false);
47 } else {
48 robotDrive.arcadeDrive(0.0, 0.0, false); // stop robot
49 }
50 }
51
52 /** This function is called once each time the robot enters teleoperated mode. */
53 @Override
54 public void teleopInit() {}
55
56 /** This function is called periodically during teleoperated mode. */
57 @Override
58 public void teleopPeriodic() {
59 robotDrive.arcadeDrive(-controller.getLeftY(), -controller.getRightX());
60 }
61
62 /** This function is called once each time the robot enters utility mode. */
63 @Override
64 public void utilityInit() {}
65
66 /** This function is called periodically during utility mode. */
67 @Override
68 public void utilityPeriodic() {}
69}
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include "wpi/drive/DifferentialDrive.hpp"
6#include "wpi/drivers/motor/PWMSparkMax.hpp"
7#include "wpi/driverstation/Gamepad.hpp"
8#include "wpi/framework/TimedRobot.hpp"
9#include "wpi/system/Timer.hpp"
10
11class Robot : public wpi::TimedRobot {
12 public:
13 Robot() {
14 // We need to invert one side of the drivetrain so that positive voltages
15 // result in both sides moving forward. Depending on how your robot's
16 // gearbox is constructed, you might have to invert the left side instead.
17 right.SetInverted(true);
18 robotDrive.SetExpiration(100_ms);
19 timer.Start();
20 }
21
22 void AutonomousInit() override { timer.Restart(); }
23
24 void AutonomousPeriodic() override {
25 // Drive for 2 seconds
26 if (timer.Get() < 2_s) {
27 // Drive forwards half velocity, make sure to turn input squaring off
28 robotDrive.ArcadeDrive(0.5, 0.0, false);
29 } else {
30 // Stop robot
31 robotDrive.ArcadeDrive(0.0, 0.0, false);
32 }
33 }
34
35 void TeleopInit() override {}
36
37 void TeleopPeriodic() override {
38 // Drive with arcade style (use right stick to steer)
39 robotDrive.ArcadeDrive(-controller.GetLeftY(), controller.GetRightX());
40 }
41
42 void UtilityInit() override {}
43
44 void UtilityPeriodic() override {}
45
46 private:
47 // Robot drive system
48 wpi::PWMSparkMax left{0};
49 wpi::PWMSparkMax right{1};
50 wpi::DifferentialDrive robotDrive{
51 [&](double output) { left.SetThrottle(output); },
52 [&](double output) { right.SetThrottle(output); }};
53
54 wpi::Gamepad controller{0};
55 wpi::Timer timer;
56};
57
58#ifndef RUNNING_WPILIB_TESTS
59int main() {
60 return wpi::StartRobot<Robot>();
61}
62#endif
1#!/usr/bin/env python3
2#
3# Copyright (c) FIRST and other WPILib contributors.
4# Open Source Software; you can modify and/or share it under the terms of
5# the WPILib BSD license file in the root directory of this project.
6#
7
8import wpilib
9import wpilib_drivers
10
11
12class MyRobot(wpilib.TimedRobot):
13 def __init__(self):
14 """
15 This function is called upon program startup and
16 should be used for any initialization code.
17 """
18 super().__init__()
19 self.left_drive = wpilib_drivers.PWMSparkMax(0)
20 self.right_drive = wpilib_drivers.PWMSparkMax(1)
21 self.robot_drive = wpilib.DifferentialDrive(self.left_drive, self.right_drive)
22 self.controller = wpilib.Gamepad(0)
23 self.timer = wpilib.Timer()
24
25 # We need to invert one side of the drivetrain so that positive voltages
26 # result in both sides moving forward. Depending on how your robot's
27 # gearbox is constructed, you might have to invert the left side instead.
28 self.right_drive.set_inverted(True)
29
30 def autonomous_init(self):
31 """This function is run once each time the robot enters autonomous mode."""
32 self.timer.restart()
33
34 def autonomous_periodic(self):
35 """This function is called periodically during autonomous."""
36
37 # Drive for two seconds
38 if self.timer.get() < 2.0:
39 # Drive forwards half velocity, make sure to turn input squaring off
40 self.robot_drive.arcade_drive(0.5, 0, square_inputs=False)
41 else:
42 self.robot_drive.arcade_drive(0, 0) # Stop robot
43
44 def teleop_init(self):
45 """This function is called once each time the robot enters teleoperated mode."""
46
47 def teleop_periodic(self):
48 """This function is called periodically during teleoperated mode."""
49 self.robot_drive.arcade_drive(
50 -self.controller.get_left_y(), -self.controller.get_right_x()
51 )
52
53 def utility_init(self):
54 """This function is called once each time the robot enters utility mode."""
55
56 def utility_periodic(self):
57 """This function is called periodically during utility mode."""
Now let’s look at various parts of the code.
Imports/Includes¶
1import org.wpilib.drive.DifferentialDrive;
2import org.wpilib.drivers.motor.PWMSparkMax;
3import org.wpilib.driverstation.Gamepad;
4import org.wpilib.framework.TimedRobot;
5import org.wpilib.system.Timer;
5#include "wpi/drive/DifferentialDrive.hpp"
6#include "wpi/drivers/motor/PWMSparkMax.hpp"
7#include "wpi/driverstation/Gamepad.hpp"
8#include "wpi/framework/TimedRobot.hpp"
9#include "wpi/system/Timer.hpp"
8import wpilib
import org.wpilib.framework.TimedRobot;
import org.wpilib.system.Timer;
import org.wpilib.driverstation.Gamepad;
import org.wpilib.drive.DifferentialDrive;
import com.ctre.phoenix6.hardware.TalonFX;
#include "wpi/framework/TimedRobot.hpp"
#include "wpi/system/Timer.hpp"
#include "wpi/driverstation/Gamepad.hpp"
#include "wpi/drive/DifferentialDrive.hpp"
#include "ctre/phoenix6/TalonFX.hpp"
import wpilib # Used to get the joysticks
from wpilib import DifferentialDrive # Used for the DifferentialDrive class
import phoenix6 # CTRE library
import com.revrobotics.CANSparkMax;
import com.revrobotics.CANSparkLowLevel.MotorType;
import org.wpilib.framework.TimedRobot;
import org.wpilib.system.Timer;
import org.wpilib.driverstation.Gamepad;
import org.wpilib.drive.DifferentialDrive;
#include "wpi/framework/TimedRobot.hpp"
#include "wpi/system/Timer.hpp"
#include "wpi/driverstation/Gamepad.hpp"
#include "wpi/drive/DifferentialDrive.hpp"
#include "wpi/hardware/motor/PWMSparkMax.hpp"
#include "rev/CANSparkMax.h"
import wpilib # Used to get the joysticks and DifferentialDrive class
import rev # REV library
import org.wpilib.framework.TimedRobot;
import org.wpilib.system.Timer;
import org.wpilib.driverstation.Gamepad;
import org.wpilib.drive.DifferentialDrive;
import com.ctre.phoenix.motorcontrol.can.WPI_TalonSRX;
#include "wpi/framework/TimedRobot.hpp"
#include "wpi/system/Timer.hpp"
#include "wpi/driverstation/Gamepad.hpp"
#include "wpi/drive/DifferentialDrive.hpp"
#include "ctre/phoenix/motorcontrol/can/WPI_TalonSRX.h"
import wpilib # Used to get the joysticks
from wpilib import DifferentialDrive # Used for the DifferentialDrive class
import phoenix5 # Phoenix5 library
Our code needs to reference the components of WPILib that are used. In C++ this is accomplished using #include statements; in Java and Python it is done with import statements. The program references classes for Gamepad (for driving), PWMSparkMax / TalonFX / CANSparkMax / WPI_TalonSRX (for controlling motors), TimedRobot (the base class used for the example), Timer (used for autonomous), and DifferentialDrive (for connecting the Gamepad to the motors).
Note
The Gamepad class is used with the 2027 FIRST Driver Station. If
you are using the NI Driver Station, use the NiDsXboxController class
instead. The pinned Python PWM example above still shows
NiDsXboxController; replace it with wpilib.Gamepad(0) when following
this guide with the 2027 Driver Station.
Defining the variables for our sample robot¶
18public class Robot extends TimedRobot {
19 private final PWMSparkMax leftDrive = new PWMSparkMax(0);
20 private final PWMSparkMax rightDrive = new PWMSparkMax(1);
21 private final DifferentialDrive robotDrive =
22 new DifferentialDrive(leftDrive::setThrottle, rightDrive::setThrottle);
23 private final Gamepad controller = new Gamepad(0);
24 private final Timer timer = new Timer();
46 private:
47 // Robot drive system
48 wpi::PWMSparkMax left{0};
49 wpi::PWMSparkMax right{1};
50 wpi::DifferentialDrive robotDrive{
51 [&](double output) { left.SetThrottle(output); },
52 [&](double output) { right.SetThrottle(output); }};
53
54 wpi::Gamepad controller{0};
55 wpi::Timer timer;
12class MyRobot(wpilib.TimedRobot):
13 def __init__(self):
14 """
15 This function is called upon program startup and
16 should be used for any initialization code.
17 """
18 super().__init__()
19 self.left_drive = wpilib_drivers.PWMSparkMax(0)
20 self.right_drive = wpilib_drivers.PWMSparkMax(1)
21 self.robot_drive = wpilib.DifferentialDrive(self.left_drive, self.right_drive)
22 self.controller = wpilib.Gamepad(0)
23 self.timer = wpilib.Timer()
24
25 # We need to invert one side of the drivetrain so that positive voltages
26 # result in both sides moving forward. Depending on how your robot's
27 # gearbox is constructed, you might have to invert the left side instead.
28 self.right_drive.set_inverted(True)
29
public class Robot extends TimedRobot {
private final TalonFX leftDrive = new TalonFX(1);
private final TalonFX rightDrive = new TalonFX(2);
private final DifferentialDrive robotDrive =
new DifferentialDrive(leftDrive::set, rightDrive::set);
private final Gamepad controller = new Gamepad(0);
private final Timer timer = new Timer();
private:
// Robot drive system
ctre::phoenix6::hardware::TalonFX left{1};
ctre::phoenix6::hardware::TalonFX right{2};
wpi::DifferentialDrive robotDrive{
[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
wpi::Gamepad controller{0};
wpi::Timer timer;
class MyRobot(wpilib.TimedRobot):
def __init__(self):
"""
This function is called upon program startup and
should be used for any initialization code.
"""
super().__init__()
self.left_drive = phoenix6.hardware.TalonFX(1)
self.right_drive = phoenix6.hardware.TalonFX(2)
self.robot_drive = DifferentialDrive(
self.left_drive, self.right_drive
)
self.controller = wpilib.Gamepad(0)
self.timer = wpilib.Timer()
# We need to invert one side of the drivetrain so that positive voltages
# result in both sides moving forward. Depending on how your robot's
# gearbox is constructed, you might have to invert the left side instead.
self.right_drive.set_inverted(True)
public class Robot extends TimedRobot {
private final CANSparkMax leftDrive = new CANSparkMax(1, MotorType.kBrushless);
private final CANSparkMax rightDrive = new CANSparkMax(2, MotorType.kBrushless);
private final DifferentialDrive robotDrive =
new DifferentialDrive(leftDrive::set, rightDrive::set);
private final Gamepad controller = new Gamepad(0);
private final Timer timer = new Timer();
private:
// Robot drive system
rev::CANSparkMax left{1, rev::CANSparkMax::MotorType::kBrushless};
rev::CANSparkMax right{2, rev::CANSparkMax::MotorType::kBrushless};
wpi::DifferentialDrive robotDrive{
[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
wpi::Gamepad controller{0};
wpi::Timer timer;
12class MyRobot(wpilib.TimedRobot):
13 def __init__(self):
14 super().__init__()
15 """
16 This function is called upon program startup and
17 should be used for any initialization code.
18 """
19 self.leftDrive = rev.SparkMax(0, 1, rev.SparkMax.MotorType.kBrushless)
20 self.rightDrive = rev.SparkMax(0, 2, rev.SparkMax.MotorType.kBrushless)
21 self.robotDrive = wpilib.DifferentialDrive(self.leftDrive, self.rightDrive)
22 self.controller = wpilib.Gamepad(0)
23 self.timer = wpilib.Timer()
24
25 # We need to invert one side of the drivetrain so that positive voltages
26 # result in both sides moving forward. Depending on how your robot's
27 # gearbox is constructed, you might have to invert the left side instead.
28 self.rightDrive.setInverted(True)
public class Robot extends TimedRobot {
private final WPI_TalonSRX leftDrive = new WPI_TalonSRX(1);
private final WPI_TalonSRX rightDrive = new WPI_TalonSRX(2);
private final DifferentialDrive robotDrive = new DifferentialDrive(leftDrive1::set, rightDrive2::set);
private final Gamepad controller = new Gamepad(0);
private final Timer timer = new Timer();
private:
// Robot drive system
ctre::phoenix::motorcontrol::can::WPI_TalonSRX left{1};
ctre::phoenix::motorcontrol::can::WPI_TalonSRX right{2};
wpi::DifferentialDrive robotDrive{
[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
wpi::Gamepad controller{0};
wpi::Timer timer;
13class MyRobot(wpilib.TimedRobot):
14 def robotInit(self):
15 """
16 This function is called upon program startup and
17 should be used for any initialization code.
18 """
19 self.leftDrive = phoenix5.WPI_TalonFX(1)
20 self.rightDrive = phoenix5.WPI_TalonFX(2)
21 self.robotDrive = wpilib.drive.DifferentialDrive(
22 self.leftDrive, self.rightDrive
23 )
24 self.controller = wpilib.XboxController(0)
25 self.timer = wpilib.Timer()
26
27 # We need to invert one side of the drivetrain so that positive voltages
28 # result in both sides moving forward. Depending on how your robot's
29 # gearbox is constructed, you might have to invert the left side instead.
30 self.rightDrive.setInverted(True)
The sample robot uses an Xbox controller (or another gamepad) on USB port 0
for arcade drive and two motors on PWM ports 0 and 1. The vendor examples use
CAN IDs 1 and 2. Here we create DifferentialDrive (robotDrive),
Gamepad (controller), and Timer (timer) objects. This code:
Defines the variables as members of the Robot class.
Initializes each object once instead of recreating it periodically.
Note
The variable initializations for C++ are in the private section at the bottom of the program. This means they are private to the class (Robot).
Robot Initialization¶
27 public Robot() {
28 // We need to invert one side of the drivetrain so that positive voltages
29 // result in both sides moving forward. Depending on how your robot's
30 // gearbox is constructed, you might have to invert the left side instead.
31 rightDrive.setInverted(true);
32 }
13 Robot() {
14 // We need to invert one side of the drivetrain so that positive voltages
15 // result in both sides moving forward. Depending on how your robot's
16 // gearbox is constructed, you might have to invert the left side instead.
17 right.SetInverted(true);
18 robotDrive.SetExpiration(100_ms);
19 timer.Start();
20 }
12 def __init__(self):
13 """
14 This function is called upon program startup and
15 should be used for any initialization code.
16 """
17 super().__init__()
18 # We need to invert one side of the drivetrain so that positive voltages
19 # result in both sides moving forward. Depending on how your robot's
20 # gearbox is constructed, you might have to invert the left side instead.
21 self.right_drive.set_inverted(True)
The Robot constructor for our sample program inverts the right side of the drivetrain. Depending on your drive setup, you might need to invert the left side instead.
Simple Autonomous Example¶
34 /** This function is run once each time the robot enters autonomous mode. */
35 @Override
36 public void autonomousInit() {
37 timer.restart();
38 }
39
40 /** This function is called periodically during autonomous. */
41 @Override
42 public void autonomousPeriodic() {
43 // Drive for 2 seconds
44 if (timer.get() < 2.0) {
45 // Drive forwards half velocity, make sure to turn input squaring off
46 robotDrive.arcadeDrive(0.5, 0.0, false);
47 } else {
48 robotDrive.arcadeDrive(0.0, 0.0, false); // stop robot
49 }
50 }
22 void AutonomousInit() override { timer.Restart(); }
23
24 void AutonomousPeriodic() override {
25 // Drive for 2 seconds
26 if (timer.Get() < 2_s) {
27 // Drive forwards half velocity, make sure to turn input squaring off
28 robotDrive.ArcadeDrive(0.5, 0.0, false);
29 } else {
30 // Stop robot
31 robotDrive.ArcadeDrive(0.0, 0.0, false);
32 }
33 }
30 def autonomous_init(self):
31 """This function is run once each time the robot enters autonomous mode."""
32 self.timer.restart()
33
34 def autonomous_periodic(self):
35 """This function is called periodically during autonomous."""
36
37 # Drive for two seconds
38 if self.timer.get() < 2.0:
39 # Drive forwards half velocity, make sure to turn input squaring off
40 self.robot_drive.arcade_drive(0.5, 0, square_inputs=False)
41 else:
42 self.robot_drive.arcade_drive(0, 0) # Stop robot
The AutonomousInit method is run once each time the robot transitions to autonomous from another mode. In this program, we restart the Timer in this method.
AutonomousPeriodic is run once every period while the robot is in autonomous mode. In the TimedRobot class the period is a fixed time, which defaults to 20ms. In this example, the periodic code checks if the timer is less than 2 seconds and if so, drives forward at half speed using the ArcadeDrive method of the DifferentialDrive class. If more than 2 seconds has elapsed, the code stops the robot drive.
Joystick Control for Teleoperation¶
52 /** This function is called once each time the robot enters teleoperated mode. */
53 @Override
54 public void teleopInit() {}
55
56 /** This function is called periodically during teleoperated mode. */
57 @Override
58 public void teleopPeriodic() {
59 robotDrive.arcadeDrive(-controller.getLeftY(), -controller.getRightX());
60 }
35 void TeleopInit() override {}
36
37 void TeleopPeriodic() override {
38 // Drive with arcade style (use right stick to steer)
39 robotDrive.ArcadeDrive(-controller.GetLeftY(), controller.GetRightX());
40 }
44 def teleop_init(self):
45 """This function is called once each time the robot enters teleoperated mode."""
46
47 def teleop_periodic(self):
48 """This function is called periodically during teleoperated mode."""
49 self.robot_drive.arcade_drive(
50 -self.controller.get_left_y(), -self.controller.get_right_x()
51 )
Like in Autonomous, the Teleop mode has a TeleopInit and TeleopPeriodic function. In this example we don’t have anything to do in TeleopInit, it is provided for illustration purposes only. In TeleopPeriodic, the code uses the ArcadeDrive method to map the Y-axis of the left thumbstick of the Gamepad to forward/back motion of the drive motors and the X-axis to turning motion.
Utility Mode¶
62 /** This function is called once each time the robot enters utility mode. */
63 @Override
64 public void utilityInit() {}
65
66 /** This function is called periodically during utility mode. */
67 @Override
68 public void utilityPeriodic() {}
42 void UtilityInit() override {}
43
44 void UtilityPeriodic() override {}
53 def utility_init(self):
54 """This function is called once each time the robot enters utility mode."""
55
56 def utility_periodic(self):
57 """This function is called periodically during utility mode."""
Utility Mode is used for testing robot functionality or running other code that shouldn’t be run in a match. Similar to TeleopInit, the UtilityInit and UtilityPeriodic methods are provided here for illustrative purposes only.
Deploying the Project to a Robot¶
Before deploying, save the program and check that:
The project’s team number matches Systemcore and the Driver Station.
Motor ports or CAN IDs match the wired devices.
The required vendor libraries are installed for a CAN example.
The controller is assigned to the port used by the example.
Connect the computer using the USB or robot-network path verified in Step 3. Keep the robot disabled, then use the command for your language below.
In Visual Studio Code, click the WPILib logo in the top right to launch the WPILib Command Palette. Select Deploy Robot Code to deploy the code to the robot.
Note
The run button in VS Code’s debug view is not used to run robot code. Instead, use the Deploy Robot Code command as described above. The debug view’s run button is used for running and debugging code on the local machine in simulation, which is not applicable for robot code that runs on Systemcore.
For more detailed instructions, see Deploy Java/C++ code.
In the terminal, run the following command to deploy the code to the robot:
py -3 -m robotpy deploy
python3 -m robotpy deploy
python3 -m robotpy deploy
For more detailed instructions, see Deploy Python code.
Expected result: the terminal reports deployment success, and Driver Station shows both robot communication and robot code. If either is missing, read the deploy output and resolve the first error before continuing.
Leave the robot disabled. Continue to Running Your Test Program for the controller checks and first drive test.
✓ Your drivetrain program is deployed.
Continue to the safety checks and first-enable procedure before running the motors.