Introduction to Kinematics and The ChassisVelocities Class¶
Note
Kinematics and odometry uses a common coordinate system. You may wish to reference the Coordinate System section for details.
What is kinematics?¶
The kinematics suite contains classes for differential drive, swerve drive, and mecanum drive kinematics and odometry. The kinematics classes help convert between a universal ChassisVelocities (Java, C++, Python) object, containing linear and angular velocities for a robot to usable velocities for each individual type of drivetrain i.e. left and right wheel velocities for a differential drive, four wheel velocities for a mecanum drive, or individual module states (velocity and angle) for a swerve drive.
What is odometry?¶
Odometry involves using sensors on the robot to create an estimate of the position of the robot on the field. In FRC, these sensors are typically several encoders (the exact number depends on the drive type) and a gyroscope to measure robot angle. The odometry classes utilize the kinematics classes along with periodic user inputs about velocities (and angles in the case of swerve) to create an estimate of the robot’s location on the field.
The ChassisVelocities Class¶
The ChassisVelocities object is essential to the new WPILib kinematics and odometry suite. The ChassisVelocities object represents the velocities of a robot chassis. This struct has three components:
vx: The velocity of the robot in the x (forward) direction.vy: The velocity of the robot in the y (sideways) direction. (Positive values mean the robot is moving to the left).omega: The angular velocity of the robot in radians per second.
Note
A non-holonomic drivetrain (i.e. a drivetrain that cannot move sideways, ex: a differential drive) will have a vy component of zero because of its inability to move sideways.
Constructing a ChassisVelocities object¶
The constructor for the ChassisVelocities object is very straightforward, accepting three arguments for vx, vy, and omega. In Java and Python, vx and vy must be in meters per second. In C++, the units library may be used to provide a linear velocity using any linear velocity unit.
// The robot is moving at 3 meters per second forward, 2 meters
// per second to the right, and rotating at half a rotation per
// second counterclockwise.
var velocities = new ChassisVelocities(3.0, -2.0, Math.PI);
// The robot is moving at 3 meters per second forward, 2 meters
// per second to the right, and rotating at half a rotation per
// second counterclockwise.
wpi::math::ChassisVelocities velocities{3.0_mps, -2.0_mps,
units::radians_per_second_t(std::numbers::pi)};
import math
from wpimath import ChassisVelocities
# The robot is moving at 3 meters per second forward, 2 meters
# per second to the right, and rotating at half a rotation per
# second counterclockwise.
velocities = ChassisVelocities(3.0, -2.0, math.pi)
Creating a Robot-Relative ChassisVelocities Object from Field-Relative Velocities¶
The toRobotRelative (Java / Python) / ToRobotRelative (C++) method can be used to generate a robot-relative ChassisVelocities object from a field-relative ChassisVelocities object. This method accepts the robot angle and creates a new Robot-Relative ChassisVelocities object. This is useful for implementing field-oriented controls for a swerve or mecanum drive robot.
// The desired field relative velocity here is 2 meters per second
// toward the opponent's alliance station wall, and 2 meters per
// second toward the left field boundary. The desired rotation
// is a quarter of a rotation per second counterclockwise. The current
// robot angle is 45 degrees.
ChassisVelocities velocities = new ChassisVelocities(2.0, 2.0, Math.PI / 2.0);
velocities = velocities.toRobotRelative(Rotation2d.fromDegrees(45.0));
// The desired field relative velocity here is 2 meters per second
// toward the opponent's alliance station wall, and 2 meters per
// second toward the left field boundary. The desired rotation
// is a quarter of a rotation per second counterclockwise. The current
// robot angle is 45 degrees.
wpi::math::ChassisVelocities velocities{2_mps, 2_mps,
units::radians_per_second_t(std::numbers::pi / 2.0)};
velocities = wpi::ChassisVelocities::ToRobotRelative(Rotation2d(45_deg));
import math
from wpimath import ChassisVelocities, Rotation2d
# The desired field relative velocity here is 2 meters per second
# toward the opponent's alliance station wall, and 2 meters per
# second toward the left field boundary. The desired rotation
# is a quarter of a rotation per second counterclockwise. The current
# robot angle is 45 degrees.
velocities = ChassisVelocities(2.0, 2.0, math.pi / 2.0)
velocities = velocities.toRobotRelative(Rotation2d.fromDegrees(45.0))
Note
The angular velocity is not explicitly stated to be “relative to the field” because the angular velocity is the same as measured from a field perspective or a robot perspective.