[wpilib] Add functional interface equivalents to MotorController (#6053)

This does not deprecate any current functionality, but prepares the way for future deprecation.

The drive classes now accept void(double) functions, which makes them more flexible.

The C++ API ended up a bit more verbose, but the Java API is really concise with method references, which is >80% of our userbase. For example:

`DifferentialDrive drive = new DifferentialDrive(m_leftMotor::set, m_rightMotor::set);`

Lambdas can be passed to interoperate with vendor motor controller APIs that don't have e.g., set(double), so CTRE doesn't have to maintain their WPI_ classes anymore.

MotorControllerGroup was replaced with PWMMotorController.addFollower() for PWM motor controllers. Users of CAN motor controllers should use their vendor's follower functionality.
This commit is contained in:
Tyler Veness
2024-01-01 13:37:51 -08:00
committed by GitHub
parent 8aca706217
commit e7c9f27683
132 changed files with 1159 additions and 697 deletions

View File

@@ -16,11 +16,21 @@
using namespace frc;
WPI_IGNORE_DEPRECATED
DifferentialDrive::DifferentialDrive(MotorController& leftMotor,
MotorController& rightMotor)
: m_leftMotor(&leftMotor), m_rightMotor(&rightMotor) {
wpi::SendableRegistry::AddChild(this, m_leftMotor);
wpi::SendableRegistry::AddChild(this, m_rightMotor);
: DifferentialDrive{[&](double output) { leftMotor.Set(output); },
[&](double output) { rightMotor.Set(output); }} {
wpi::SendableRegistry::AddChild(this, &leftMotor);
wpi::SendableRegistry::AddChild(this, &rightMotor);
}
WPI_UNIGNORE_DEPRECATED
DifferentialDrive::DifferentialDrive(std::function<void(double)> leftMotor,
std::function<void(double)> rightMotor)
: m_leftMotor{std::move(leftMotor)}, m_rightMotor{std::move(rightMotor)} {
static int instances = 0;
++instances;
wpi::SendableRegistry::AddLW(this, "DifferentialDrive", instances);
@@ -40,8 +50,11 @@ void DifferentialDrive::ArcadeDrive(double xSpeed, double zRotation,
auto [left, right] = ArcadeDriveIK(xSpeed, zRotation, squareInputs);
m_leftMotor->Set(left * m_maxOutput);
m_rightMotor->Set(right * m_maxOutput);
m_leftOutput = left * m_maxOutput;
m_rightOutput = right * m_maxOutput;
m_leftMotor(m_leftOutput);
m_rightMotor(m_rightOutput);
Feed();
}
@@ -60,8 +73,11 @@ void DifferentialDrive::CurvatureDrive(double xSpeed, double zRotation,
auto [left, right] = CurvatureDriveIK(xSpeed, zRotation, allowTurnInPlace);
m_leftMotor->Set(left * m_maxOutput);
m_rightMotor->Set(right * m_maxOutput);
m_leftOutput = left * m_maxOutput;
m_rightOutput = right * m_maxOutput;
m_leftMotor(m_leftOutput);
m_rightMotor(m_rightOutput);
Feed();
}
@@ -80,8 +96,11 @@ void DifferentialDrive::TankDrive(double leftSpeed, double rightSpeed,
auto [left, right] = TankDriveIK(leftSpeed, rightSpeed, squareInputs);
m_leftMotor->Set(left * m_maxOutput);
m_rightMotor->Set(right * m_maxOutput);
m_leftOutput = left * m_maxOutput;
m_rightOutput = right * m_maxOutput;
m_leftMotor(m_leftOutput);
m_rightMotor(m_rightOutput);
Feed();
}
@@ -157,8 +176,12 @@ DifferentialDrive::WheelSpeeds DifferentialDrive::TankDriveIK(
}
void DifferentialDrive::StopMotor() {
m_leftMotor->StopMotor();
m_rightMotor->StopMotor();
m_leftOutput = 0.0;
m_rightOutput = 0.0;
m_leftMotor(0.0);
m_rightMotor(0.0);
Feed();
}
@@ -171,9 +194,7 @@ void DifferentialDrive::InitSendable(wpi::SendableBuilder& builder) {
builder.SetActuator(true);
builder.SetSafeState([=, this] { StopMotor(); });
builder.AddDoubleProperty(
"Left Motor Speed", [=, this] { return m_leftMotor->Get(); },
[=, this](double value) { m_leftMotor->Set(value); });
"Left Motor Speed", [&] { return m_leftOutput; }, m_leftMotor);
builder.AddDoubleProperty(
"Right Motor Speed", [=, this] { return m_rightMotor->Get(); },
[=, this](double value) { m_rightMotor->Set(value); });
"Right Motor Speed", [&] { return m_rightOutput; }, m_rightMotor);
}

View File

@@ -16,18 +16,32 @@
using namespace frc;
WPI_IGNORE_DEPRECATED
MecanumDrive::MecanumDrive(MotorController& frontLeftMotor,
MotorController& rearLeftMotor,
MotorController& frontRightMotor,
MotorController& rearRightMotor)
: m_frontLeftMotor(&frontLeftMotor),
m_rearLeftMotor(&rearLeftMotor),
m_frontRightMotor(&frontRightMotor),
m_rearRightMotor(&rearRightMotor) {
wpi::SendableRegistry::AddChild(this, m_frontLeftMotor);
wpi::SendableRegistry::AddChild(this, m_rearLeftMotor);
wpi::SendableRegistry::AddChild(this, m_frontRightMotor);
wpi::SendableRegistry::AddChild(this, m_rearRightMotor);
: MecanumDrive{[&](double output) { frontLeftMotor.Set(output); },
[&](double output) { rearLeftMotor.Set(output); },
[&](double output) { frontRightMotor.Set(output); },
[&](double output) { rearRightMotor.Set(output); }} {
wpi::SendableRegistry::AddChild(this, &frontLeftMotor);
wpi::SendableRegistry::AddChild(this, &rearLeftMotor);
wpi::SendableRegistry::AddChild(this, &frontRightMotor);
wpi::SendableRegistry::AddChild(this, &rearRightMotor);
}
WPI_UNIGNORE_DEPRECATED
MecanumDrive::MecanumDrive(std::function<void(double)> frontLeftMotor,
std::function<void(double)> rearLeftMotor,
std::function<void(double)> frontRightMotor,
std::function<void(double)> rearRightMotor)
: m_frontLeftMotor{std::move(frontLeftMotor)},
m_rearLeftMotor{std::move(rearLeftMotor)},
m_frontRightMotor{std::move(frontRightMotor)},
m_rearRightMotor{std::move(rearRightMotor)} {
static int instances = 0;
++instances;
wpi::SendableRegistry::AddLW(this, "MecanumDrive", instances);
@@ -47,10 +61,15 @@ void MecanumDrive::DriveCartesian(double xSpeed, double ySpeed,
auto [frontLeft, frontRight, rearLeft, rearRight] =
DriveCartesianIK(xSpeed, ySpeed, zRotation, gyroAngle);
m_frontLeftMotor->Set(frontLeft * m_maxOutput);
m_frontRightMotor->Set(frontRight * m_maxOutput);
m_rearLeftMotor->Set(rearLeft * m_maxOutput);
m_rearRightMotor->Set(rearRight * m_maxOutput);
m_frontLeftOutput = frontLeft * m_maxOutput;
m_rearLeftOutput = rearLeft * m_maxOutput;
m_frontRightOutput = frontRight * m_maxOutput;
m_rearRightOutput = rearRight * m_maxOutput;
m_frontLeftMotor(m_frontLeftOutput);
m_frontRightMotor(m_frontRightOutput);
m_rearLeftMotor(m_rearLeftOutput);
m_rearRightMotor(m_rearRightOutput);
Feed();
}
@@ -68,10 +87,16 @@ void MecanumDrive::DrivePolar(double magnitude, Rotation2d angle,
}
void MecanumDrive::StopMotor() {
m_frontLeftMotor->StopMotor();
m_frontRightMotor->StopMotor();
m_rearLeftMotor->StopMotor();
m_rearRightMotor->StopMotor();
m_frontLeftOutput = 0.0;
m_frontRightOutput = 0.0;
m_rearLeftOutput = 0.0;
m_rearRightOutput = 0.0;
m_frontLeftMotor(0.0);
m_frontRightMotor(0.0);
m_rearLeftMotor(0.0);
m_rearRightMotor(0.0);
Feed();
}
@@ -108,15 +133,15 @@ void MecanumDrive::InitSendable(wpi::SendableBuilder& builder) {
builder.SetActuator(true);
builder.SetSafeState([=, this] { StopMotor(); });
builder.AddDoubleProperty(
"Front Left Motor Speed", [=, this] { return m_frontLeftMotor->Get(); },
[=, this](double value) { m_frontLeftMotor->Set(value); });
"Front Left Motor Speed", [&] { return m_frontLeftOutput; },
m_frontLeftMotor);
builder.AddDoubleProperty(
"Front Right Motor Speed", [=, this] { return m_frontRightMotor->Get(); },
[=, this](double value) { m_frontRightMotor->Set(value); });
"Front Right Motor Speed", [&] { return m_frontRightOutput; },
m_frontRightMotor);
builder.AddDoubleProperty(
"Rear Left Motor Speed", [=, this] { return m_rearLeftMotor->Get(); },
[=, this](double value) { m_rearLeftMotor->Set(value); });
"Rear Left Motor Speed", [&] { return m_rearLeftOutput; },
m_rearLeftMotor);
builder.AddDoubleProperty(
"Rear Right Motor Speed", [=, this] { return m_rearRightMotor->Get(); },
[=, this](double value) { m_rearRightMotor->Set(value); });
"Rear Right Motor Speed", [&] { return m_rearRightOutput; },
m_rearRightMotor);
}

View File

@@ -12,6 +12,8 @@ using namespace frc;
// Can't use a delegated constructor here because of an MSVC bug.
// https://developercommunity.visualstudio.com/content/problem/583/compiler-bug-with-delegating-a-constructor.html
WPI_IGNORE_DEPRECATED
MotorControllerGroup::MotorControllerGroup(
std::vector<std::reference_wrapper<MotorController>>&& motorControllers)
: m_motorControllers(std::move(motorControllers)) {
@@ -74,3 +76,5 @@ void MotorControllerGroup::InitSendable(wpi::SendableBuilder& builder) {
"Value", [=, this] { return Get(); },
[=, this](double value) { Set(value); });
}
WPI_UNIGNORE_DEPRECATED

View File

@@ -11,6 +11,8 @@
using namespace frc;
WPI_IGNORE_DEPRECATED
NidecBrushless::NidecBrushless(int pwmChannel, int dioChannel)
: m_dio(dioChannel), m_pwm(pwmChannel) {
wpi::SendableRegistry::AddChild(this, &m_dio);
@@ -26,6 +28,8 @@ NidecBrushless::NidecBrushless(int pwmChannel, int dioChannel)
wpi::SendableRegistry::AddLW(this, "Nidec Brushless", pwmChannel);
}
WPI_UNIGNORE_DEPRECATED
void NidecBrushless::Set(double speed) {
if (!m_disabled) {
m_speed = speed;

View File

@@ -8,13 +8,31 @@
#include <wpi/sendable/SendableBuilder.h>
#include <wpi/sendable/SendableRegistry.h>
#include "frc/RobotController.h"
using namespace frc;
void PWMMotorController::Set(double speed) {
m_pwm.SetSpeed(m_isInverted ? -speed : speed);
if (m_isInverted) {
speed = -speed;
}
m_pwm.SetSpeed(speed);
for (auto& follower : m_nonowningFollowers) {
follower->Set(speed);
}
for (auto& follower : m_owningFollowers) {
follower->Set(speed);
}
Feed();
}
void PWMMotorController::SetVoltage(units::volt_t output) {
// NOLINTNEXTLINE(bugprone-integer-division)
Set(output / RobotController::GetBatteryVoltage());
}
double PWMMotorController::Get() const {
return m_pwm.GetSpeed() * (m_isInverted ? -1.0 : 1.0);
}
@@ -48,11 +66,19 @@ void PWMMotorController::EnableDeadbandElimination(bool eliminateDeadband) {
m_pwm.EnableDeadbandElimination(eliminateDeadband);
}
void PWMMotorController::AddFollower(PWMMotorController& follower) {
m_nonowningFollowers.emplace_back(&follower);
}
WPI_IGNORE_DEPRECATED
PWMMotorController::PWMMotorController(std::string_view name, int channel)
: m_pwm(channel, false) {
wpi::SendableRegistry::AddLW(this, name, channel);
}
WPI_UNIGNORE_DEPRECATED
void PWMMotorController::InitSendable(wpi::SendableBuilder& builder) {
builder.SetSmartDashboardType("Motor Controller");
builder.SetActuator(true);

View File

@@ -4,8 +4,10 @@
#pragma once
#include <functional>
#include <string>
#include <wpi/deprecated.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
@@ -20,43 +22,9 @@ class MotorController;
* the Kit of Parts drive base, "tank drive", or West Coast Drive.
*
* These drive bases typically have drop-center / skid-steer with two or more
* wheels per side (e.g., 6WD or 8WD). This class takes a MotorController per
* side. For four and six motor drivetrains, construct and pass in
* MotorControllerGroup instances as follows.
*
* Four motor drivetrain:
* @code{.cpp}
* class Robot {
* public:
* frc::PWMVictorSPX m_frontLeft{1};
* frc::PWMVictorSPX m_rearLeft{2};
* frc::MotorControllerGroup m_left{m_frontLeft, m_rearLeft};
*
* frc::PWMVictorSPX m_frontRight{3};
* frc::PWMVictorSPX m_rearRight{4};
* frc::MotorControllerGroup m_right{m_frontRight, m_rearRight};
*
* frc::DifferentialDrive m_drive{m_left, m_right};
* };
* @endcode
*
* Six motor drivetrain:
* @code{.cpp}
* class Robot {
* public:
* frc::PWMVictorSPX m_frontLeft{1};
* frc::PWMVictorSPX m_midLeft{2};
* frc::PWMVictorSPX m_rearLeft{3};
* frc::MotorControllerGroup m_left{m_frontLeft, m_midLeft, m_rearLeft};
*
* frc::PWMVictorSPX m_frontRight{4};
* frc::PWMVictorSPX m_midRight{5};
* frc::PWMVictorSPX m_rearRight{6};
* frc::MotorControllerGroup m_right{m_frontRight, m_midRight, m_rearRight};
*
* frc::DifferentialDrive m_drive{m_left, m_right};
* };
* @endcode
* wheels per side (e.g., 6WD or 8WD). This class takes a setter per side. For
* four and six motor drivetrains, use CAN motor controller followers or
* PWMMotorController::AddFollower().
*
* A differential drive robot has left and right wheels separated by an
* arbitrary width.
@@ -101,13 +69,33 @@ class DifferentialDrive : public RobotDriveBase,
double right = 0.0;
};
WPI_IGNORE_DEPRECATED
/**
* Construct a DifferentialDrive.
*
* To pass multiple motors per side, use CAN motor controller followers or
* PWMSpeedController::AddFollower(). If a motor needs to be inverted, do so
* before passing it in.
*
* @param leftMotor Left motor.
* @param rightMotor Right motor.
*/
DifferentialDrive(MotorController& leftMotor, MotorController& rightMotor);
WPI_UNIGNORE_DEPRECATED
/**
* Construct a DifferentialDrive.
*
* To pass multiple motors per side, use a MotorControllerGroup. If a motor
* needs to be inverted, do so before passing it in.
*
* @param leftMotor Left motor setter.
* @param rightMotor Right motor setter.
*/
DifferentialDrive(MotorController& leftMotor, MotorController& rightMotor);
DifferentialDrive(std::function<void(double)> leftMotor,
std::function<void(double)> rightMotor);
~DifferentialDrive() override = default;
@@ -210,8 +198,12 @@ class DifferentialDrive : public RobotDriveBase,
void InitSendable(wpi::SendableBuilder& builder) override;
private:
MotorController* m_leftMotor;
MotorController* m_rightMotor;
std::function<void(double)> m_leftMotor;
std::function<void(double)> m_rightMotor;
// Used for Sendable property getters
double m_leftOutput = 0.0;
double m_rightOutput = 0.0;
};
} // namespace frc

View File

@@ -4,10 +4,12 @@
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <units/angle.h>
#include <wpi/deprecated.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
@@ -69,15 +71,39 @@ class MecanumDrive : public RobotDriveBase,
double rearRight = 0.0;
};
WPI_IGNORE_DEPRECATED
/**
* Construct a MecanumDrive.
*
* If a motor needs to be inverted, do so before passing it in.
*
* @param frontLeftMotor Front-left motor.
* @param rearLeftMotor Rear-left motor.
* @param frontRightMotor Front-right motor.
* @param rearRightMotor Rear-right motor.
*/
MecanumDrive(MotorController& frontLeftMotor, MotorController& rearLeftMotor,
MotorController& frontRightMotor,
MotorController& rearRightMotor);
WPI_UNIGNORE_DEPRECATED
/**
* Construct a MecanumDrive.
*
* If a motor needs to be inverted, do so before passing it in.
*
* @param frontLeftMotor Front-left motor setter.
* @param rearLeftMotor Rear-left motor setter.
* @param frontRightMotor Front-right motor setter.
* @param rearRightMotor Rear-right motor setter.
*/
MecanumDrive(std::function<void(double)> frontLeftMotor,
std::function<void(double)> rearLeftMotor,
std::function<void(double)> frontRightMotor,
std::function<void(double)> rearRightMotor);
~MecanumDrive() override = default;
MecanumDrive(MecanumDrive&&) = default;
@@ -141,10 +167,16 @@ class MecanumDrive : public RobotDriveBase,
void InitSendable(wpi::SendableBuilder& builder) override;
private:
MotorController* m_frontLeftMotor;
MotorController* m_rearLeftMotor;
MotorController* m_frontRightMotor;
MotorController* m_rearRightMotor;
std::function<void(double)> m_frontLeftMotor;
std::function<void(double)> m_rearLeftMotor;
std::function<void(double)> m_frontRightMotor;
std::function<void(double)> m_rearRightMotor;
// Used for Sendable property getters
double m_frontLeftOutput = 0.0;
double m_rearLeftOutput = 0.0;
double m_frontRightOutput = 0.0;
double m_rearRightOutput = 0.0;
bool reported = false;
};

View File

@@ -7,19 +7,25 @@
#include <functional>
#include <vector>
#include <wpi/deprecated.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
#include "frc/motorcontrol/MotorController.h"
WPI_IGNORE_DEPRECATED
namespace frc {
/**
* Allows multiple MotorController objects to be linked together.
*/
class MotorControllerGroup : public wpi::Sendable,
public MotorController,
public wpi::SendableHelper<MotorControllerGroup> {
class [[deprecated(
"Use CAN motor controller followers or "
"PWMMotorController::AddFollower()")]] MotorControllerGroup
: public wpi::Sendable,
public MotorController,
public wpi::SendableHelper<MotorControllerGroup> {
public:
template <class... MotorControllers>
explicit MotorControllerGroup(MotorController& motorController,
@@ -50,3 +56,5 @@ class MotorControllerGroup : public wpi::Sendable,
} // namespace frc
#include "frc/motorcontrol/MotorControllerGroup.inc"
WPI_UNIGNORE_DEPRECATED

View File

@@ -6,6 +6,7 @@
#include <string>
#include <wpi/deprecated.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
@@ -16,6 +17,8 @@
namespace frc {
WPI_IGNORE_DEPRECATED
/**
* Nidec Brushless Motor.
*/
@@ -95,4 +98,6 @@ class NidecBrushless : public MotorController,
double m_speed = 0.0;
};
WPI_UNIGNORE_DEPRECATED
} // namespace frc

View File

@@ -4,9 +4,16 @@
#pragma once
#include <concepts>
#include <memory>
#include <string>
#include <string_view>
#include <type_traits>
#include <utility>
#include <vector>
#include <units/voltage.h>
#include <wpi/deprecated.h>
#include <wpi/sendable/Sendable.h>
#include <wpi/sendable/SendableHelper.h>
@@ -17,6 +24,8 @@
namespace frc {
class DMA;
WPI_IGNORE_DEPRECATED
/**
* Common base class for all PWM Motor Controllers.
*/
@@ -40,6 +49,20 @@ class PWMMotorController : public MotorController,
*/
void Set(double value) override;
/**
* Sets the voltage output of the PWMMotorController. Compensates for
* the current bus voltage to ensure that the desired voltage is output even
* if the battery voltage is below 12V - highly useful when the voltage
* outputs are "meaningful" (e.g. they come from a feedforward calculation).
*
* <p>NOTE: This function *must* be called regularly in order for voltage
* compensation to work properly - unlike the ordinary set function, it is not
* "set it and forget it."
*
* @param output The voltage to output.
*/
void SetVoltage(units::volt_t output) override;
/**
* Get the recently set value of the PWM. This value is affected by the
* inversion property. If you want the value that is sent directly to the
@@ -71,6 +94,24 @@ class PWMMotorController : public MotorController,
*/
void EnableDeadbandElimination(bool eliminateDeadband);
/**
* Make the given PWM motor controller follow the output of this one.
*
* @param follower The motor controller follower.
*/
void AddFollower(PWMMotorController& follower);
/**
* Make the given PWM motor controller follow the output of this one.
*
* @param follower The motor controller follower.
*/
template <std::derived_from<PWMMotorController> T>
void AddFollower(T&& follower) {
m_owningFollowers.emplace_back(
std::make_unique<std::decay_t<T>>(std::forward<T>(follower)));
}
protected:
/**
* Constructor for a PWM Motor %Controller connected via PWM.
@@ -87,8 +128,12 @@ class PWMMotorController : public MotorController,
private:
bool m_isInverted = false;
std::vector<PWMMotorController*> m_nonowningFollowers;
std::vector<std::unique_ptr<PWMMotorController>> m_owningFollowers;
PWM* GetPwm() { return &m_pwm; }
};
WPI_UNIGNORE_DEPRECATED
} // namespace frc

View File

@@ -5,7 +5,7 @@
#include <gtest/gtest.h>
#include "frc/drive/DifferentialDrive.h"
#include "motorcontrol/MockMotorController.h"
#include "motorcontrol/MockPWMMotorController.h"
TEST(DifferentialDriveTest, ArcadeDriveIK) {
// Forward
@@ -240,9 +240,10 @@ TEST(DifferentialDriveTest, TankDriveIKSquared) {
}
TEST(DifferentialDriveTest, ArcadeDrive) {
frc::MockMotorController left;
frc::MockMotorController right;
frc::DifferentialDrive drive{left, right};
frc::MockPWMMotorController left;
frc::MockPWMMotorController right;
frc::DifferentialDrive drive{[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
drive.SetDeadband(0.0);
// Forward
@@ -277,9 +278,10 @@ TEST(DifferentialDriveTest, ArcadeDrive) {
}
TEST(DifferentialDriveTest, ArcadeDriveSquared) {
frc::MockMotorController left;
frc::MockMotorController right;
frc::DifferentialDrive drive{left, right};
frc::MockPWMMotorController left;
frc::MockPWMMotorController right;
frc::DifferentialDrive drive{[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
drive.SetDeadband(0.0);
// Forward
@@ -314,9 +316,10 @@ TEST(DifferentialDriveTest, ArcadeDriveSquared) {
}
TEST(DifferentialDriveTest, CurvatureDrive) {
frc::MockMotorController left;
frc::MockMotorController right;
frc::DifferentialDrive drive{left, right};
frc::MockPWMMotorController left;
frc::MockPWMMotorController right;
frc::DifferentialDrive drive{[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
drive.SetDeadband(0.0);
// Forward
@@ -351,9 +354,10 @@ TEST(DifferentialDriveTest, CurvatureDrive) {
}
TEST(DifferentialDriveTest, CurvatureDriveTurnInPlace) {
frc::MockMotorController left;
frc::MockMotorController right;
frc::DifferentialDrive drive{left, right};
frc::MockPWMMotorController left;
frc::MockPWMMotorController right;
frc::DifferentialDrive drive{[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
drive.SetDeadband(0.0);
// Forward
@@ -388,9 +392,10 @@ TEST(DifferentialDriveTest, CurvatureDriveTurnInPlace) {
}
TEST(DifferentialDriveTest, TankDrive) {
frc::MockMotorController left;
frc::MockMotorController right;
frc::DifferentialDrive drive{left, right};
frc::MockPWMMotorController left;
frc::MockPWMMotorController right;
frc::DifferentialDrive drive{[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
drive.SetDeadband(0.0);
// Forward
@@ -425,9 +430,10 @@ TEST(DifferentialDriveTest, TankDrive) {
}
TEST(DifferentialDriveTest, TankDriveSquared) {
frc::MockMotorController left;
frc::MockMotorController right;
frc::DifferentialDrive drive{left, right};
frc::MockPWMMotorController left;
frc::MockPWMMotorController right;
frc::DifferentialDrive drive{[&](double output) { left.Set(output); },
[&](double output) { right.Set(output); }};
drive.SetDeadband(0.0);
// Forward

View File

@@ -5,7 +5,7 @@
#include <gtest/gtest.h>
#include "frc/drive/MecanumDrive.h"
#include "motorcontrol/MockMotorController.h"
#include "motorcontrol/MockPWMMotorController.h"
TEST(MecanumDriveTest, CartesianIK) {
// Forward
@@ -82,11 +82,14 @@ TEST(MecanumDriveTest, CartesianIKGyro90CW) {
}
TEST(MecanumDriveTest, Cartesian) {
frc::MockMotorController fl;
frc::MockMotorController rl;
frc::MockMotorController fr;
frc::MockMotorController rr;
frc::MecanumDrive drive{fl, rl, fr, rr};
frc::MockPWMMotorController fl;
frc::MockPWMMotorController rl;
frc::MockPWMMotorController fr;
frc::MockPWMMotorController rr;
frc::MecanumDrive drive{[&](double output) { fl.Set(output); },
[&](double output) { rl.Set(output); },
[&](double output) { fr.Set(output); },
[&](double output) { rr.Set(output); }};
drive.SetDeadband(0.0);
// Forward
@@ -126,11 +129,14 @@ TEST(MecanumDriveTest, Cartesian) {
}
TEST(MecanumDriveTest, CartesianGyro90CW) {
frc::MockMotorController fl;
frc::MockMotorController fr;
frc::MockMotorController rl;
frc::MockMotorController rr;
frc::MecanumDrive drive{fl, rl, fr, rr};
frc::MockPWMMotorController fl;
frc::MockPWMMotorController rl;
frc::MockPWMMotorController fr;
frc::MockPWMMotorController rr;
frc::MecanumDrive drive{[&](double output) { fl.Set(output); },
[&](double output) { rl.Set(output); },
[&](double output) { fr.Set(output); },
[&](double output) { rr.Set(output); }};
drive.SetDeadband(0.0);
// Forward in global frame; left in robot frame
@@ -170,11 +176,14 @@ TEST(MecanumDriveTest, CartesianGyro90CW) {
}
TEST(MecanumDriveTest, Polar) {
frc::MockMotorController fl;
frc::MockMotorController fr;
frc::MockMotorController rl;
frc::MockMotorController rr;
frc::MecanumDrive drive{fl, rl, fr, rr};
frc::MockPWMMotorController fl;
frc::MockPWMMotorController rl;
frc::MockPWMMotorController fr;
frc::MockPWMMotorController rr;
frc::MecanumDrive drive{[&](double output) { fl.Set(output); },
[&](double output) { rl.Set(output); },
[&](double output) { fr.Set(output); },
[&](double output) { rr.Set(output); }};
drive.SetDeadband(0.0);
// Forward

View File

@@ -0,0 +1,31 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "motorcontrol/MockPWMMotorController.h"
using namespace frc;
void MockPWMMotorController::Set(double speed) {
m_speed = m_isInverted ? -speed : speed;
}
double MockPWMMotorController::Get() const {
return m_speed;
}
void MockPWMMotorController::SetInverted(bool isInverted) {
m_isInverted = isInverted;
}
bool MockPWMMotorController::GetInverted() const {
return m_isInverted;
}
void MockPWMMotorController::Disable() {
m_speed = 0;
}
void MockPWMMotorController::StopMotor() {
Disable();
}

View File

@@ -8,6 +8,7 @@
#include <vector>
#include <gtest/gtest.h>
#include <wpi/deprecated.h>
#include "motorcontrol/MockMotorController.h"
@@ -32,6 +33,8 @@ std::ostream& operator<<(std::ostream& os,
return os;
}
WPI_IGNORE_DEPRECATED
/**
* A fixture used for MotorControllerGroup testing.
*/
@@ -124,3 +127,5 @@ TEST_P(MotorControllerGroupTest, StopMotor) {
INSTANTIATE_TEST_SUITE_P(Tests, MotorControllerGroupTest,
testing::Values(TEST_ONE, TEST_TWO, TEST_THREE));
WPI_UNIGNORE_DEPRECATED

View File

@@ -4,10 +4,14 @@
#pragma once
#include <wpi/deprecated.h>
#include "frc/motorcontrol/MotorController.h"
namespace frc {
WPI_IGNORE_DEPRECATED
class MockMotorController : public MotorController {
public:
void Set(double speed) override;
@@ -22,4 +26,6 @@ class MockMotorController : public MotorController {
bool m_isInverted = false;
};
WPI_UNIGNORE_DEPRECATED
} // namespace frc

View File

@@ -0,0 +1,23 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
namespace frc {
class MockPWMMotorController {
public:
void Set(double speed);
double Get() const;
void SetInverted(bool isInverted);
bool GetInverted() const;
void Disable();
void StopMotor();
private:
double m_speed = 0.0;
bool m_isInverted = false;
};
} // namespace frc

View File

@@ -14,10 +14,17 @@
class Robot : public frc::TimedRobot {
frc::PWMSparkMax m_leftMotor{0};
frc::PWMSparkMax m_rightMotor{1};
frc::DifferentialDrive m_robotDrive{m_leftMotor, m_rightMotor};
frc::DifferentialDrive m_robotDrive{
[&](double output) { m_leftMotor.Set(output); },
[&](double output) { m_rightMotor.Set(output); }};
frc::Joystick m_stick{0};
public:
Robot() {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_leftMotor);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_rightMotor);
}
void RobotInit() override {
// 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

View File

@@ -14,10 +14,17 @@
class Robot : public frc::TimedRobot {
frc::PWMSparkMax m_leftMotor{0};
frc::PWMSparkMax m_rightMotor{1};
frc::DifferentialDrive m_robotDrive{m_leftMotor, m_rightMotor};
frc::DifferentialDrive m_robotDrive{
[&](double output) { m_leftMotor.Set(output); },
[&](double output) { m_rightMotor.Set(output); }};
frc::XboxController m_driverController{0};
public:
Robot() {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_leftMotor);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_rightMotor);
}
void RobotInit() override {
// 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

View File

@@ -13,13 +13,20 @@ DriveSubsystem::DriveSubsystem()
m_right2{kRightMotor2Port},
m_leftEncoder{kLeftEncoderPorts[0], kLeftEncoderPorts[1]},
m_rightEncoder{kRightEncoderPorts[0], kRightEncoderPorts[1]} {
wpi::SendableRegistry::AddChild(&m_drive, &m_left1);
wpi::SendableRegistry::AddChild(&m_drive, &m_right1);
m_left1.AddFollower(m_left2);
m_right1.AddFollower(m_right2);
// Set the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);
m_rightEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);
// 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.
m_rightMotors.SetInverted(true);
m_right1.SetInverted(true);
}
void DriveSubsystem::Periodic() {

View File

@@ -6,7 +6,6 @@
#include <frc/Encoder.h>
#include <frc/drive/DifferentialDrive.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/SubsystemBase.h>
@@ -75,14 +74,9 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_right1;
frc::PWMSparkMax m_right2;
// The motors on the left side of the drive
frc::MotorControllerGroup m_leftMotors{m_left1, m_left2};
// The motors on the right side of the drive
frc::MotorControllerGroup m_rightMotors{m_right1, m_right2};
// The robot's drive
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{[&](double output) { m_left1.Set(output); },
[&](double output) { m_right1.Set(output); }};
// The left-side drive encoder
frc::Encoder m_leftEncoder;

View File

@@ -13,13 +13,20 @@ DriveSubsystem::DriveSubsystem()
m_right2{kRightMotor2Port},
m_leftEncoder{kLeftEncoderPorts[0], kLeftEncoderPorts[1]},
m_rightEncoder{kRightEncoderPorts[0], kRightEncoderPorts[1]} {
wpi::SendableRegistry::AddChild(&m_drive, &m_left1);
wpi::SendableRegistry::AddChild(&m_drive, &m_right1);
m_left1.AddFollower(m_left2);
m_right1.AddFollower(m_right2);
// Set the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);
m_rightEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);
// 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.
m_rightMotors.SetInverted(true);
m_right1.SetInverted(true);
}
void DriveSubsystem::Periodic() {

View File

@@ -4,15 +4,13 @@
#pragma once
#include <frc/motorcontrol/MotorController.h>
/**
* A simplified stub class that simulates the API of a common "smart" motor
* controller.
*
* <p>Has no actual functionality.
*/
class ExampleSmartMotorController : public frc::MotorController {
class ExampleSmartMotorController {
public:
enum PIDMode { kPosition, kVelocity, kMovementWitchcraft };
@@ -68,15 +66,15 @@ class ExampleSmartMotorController : public frc::MotorController {
*/
void ResetEncoder() {}
void Set(double speed) override {}
void Set(double speed) {}
double Get() const override { return 0; }
double Get() const { return 0; }
void SetInverted(bool isInverted) override {}
void SetInverted(bool isInverted) {}
bool GetInverted() const override { return false; }
bool GetInverted() const { return false; }
void Disable() override {}
void Disable() {}
void StopMotor() override {}
void StopMotor() {}
};

View File

@@ -8,7 +8,6 @@
#include <frc/Encoder.h>
#include <frc/drive/DifferentialDrive.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/Commands.h>
#include <frc2/command/SubsystemBase.h>
@@ -73,14 +72,9 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_right1;
frc::PWMSparkMax m_right2;
// The motors on the left side of the drive
frc::MotorControllerGroup m_leftMotors{m_left1, m_left2};
// The motors on the right side of the drive
frc::MotorControllerGroup m_rightMotors{m_right1, m_right2};
// The robot's drive
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{[&](double output) { m_left1.Set(output); },
[&](double output) { m_right1.Set(output); }};
// The left-side drive encoder
frc::Encoder m_leftEncoder;

View File

@@ -12,8 +12,8 @@ void Drivetrain::SetSpeeds(const frc::DifferentialDriveWheelSpeeds& speeds) {
const double rightOutput = m_rightPIDController.Calculate(
m_rightEncoder.GetRate(), speeds.right.value());
m_leftGroup.SetVoltage(units::volt_t{leftOutput} + leftFeedforward);
m_rightGroup.SetVoltage(units::volt_t{rightOutput} + rightFeedforward);
m_leftLeader.SetVoltage(units::volt_t{leftOutput} + leftFeedforward);
m_rightLeader.SetVoltage(units::volt_t{rightOutput} + rightFeedforward);
}
void Drivetrain::Drive(units::meters_per_second_t xSpeed,

View File

@@ -12,7 +12,6 @@
#include <frc/controller/SimpleMotorFeedforward.h>
#include <frc/kinematics/DifferentialDriveKinematics.h>
#include <frc/kinematics/DifferentialDriveOdometry.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <units/angle.h>
#include <units/angular_velocity.h>
@@ -25,10 +24,13 @@
class Drivetrain {
public:
Drivetrain() {
m_leftLeader.AddFollower(m_leftFollower);
m_rightLeader.AddFollower(m_rightFollower);
// 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.
m_rightGroup.SetInverted(true);
m_rightLeader.SetInverted(true);
m_gyro.Reset();
// Set the distance per pulse for the drive encoders. We can simply use the
@@ -63,9 +65,6 @@ class Drivetrain {
frc::PWMSparkMax m_rightLeader{3};
frc::PWMSparkMax m_rightFollower{4};
frc::MotorControllerGroup m_leftGroup{m_leftLeader, m_leftFollower};
frc::MotorControllerGroup m_rightGroup{m_rightLeader, m_rightFollower};
frc::Encoder m_leftEncoder{0, 1};
frc::Encoder m_rightEncoder{2, 3};

View File

@@ -7,10 +7,13 @@
#include "ExampleGlobalMeasurementSensor.h"
Drivetrain::Drivetrain() {
m_leftLeader.AddFollower(m_leftFollower);
m_rightLeader.AddFollower(m_rightFollower);
// 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.
m_rightGroup.SetInverted(true);
m_rightLeader.SetInverted(true);
m_gyro.Reset();
@@ -37,8 +40,8 @@ void Drivetrain::SetSpeeds(const frc::DifferentialDriveWheelSpeeds& speeds) {
const double rightOutput = m_rightPIDController.Calculate(
m_rightEncoder.GetRate(), speeds.right.value());
m_leftGroup.SetVoltage(units::volt_t{leftOutput} + leftFeedforward);
m_rightGroup.SetVoltage(units::volt_t{rightOutput} + rightFeedforward);
m_leftLeader.SetVoltage(units::volt_t{leftOutput} + leftFeedforward);
m_rightLeader.SetVoltage(units::volt_t{rightOutput} + rightFeedforward);
}
void Drivetrain::Drive(units::meters_per_second_t xSpeed,
@@ -110,9 +113,9 @@ void Drivetrain::SimulationPeriodic() {
// To update our simulation, we set motor voltage inputs, update the
// simulation, and write the simulated positions and velocities to our
// simulated encoder and gyro.
m_drivetrainSimulator.SetInputs(units::volt_t{m_leftGroup.Get()} *
m_drivetrainSimulator.SetInputs(units::volt_t{m_leftLeader.Get()} *
frc::RobotController::GetInputVoltage(),
units::volt_t{m_rightGroup.Get()} *
units::volt_t{m_rightLeader.Get()} *
frc::RobotController::GetInputVoltage());
m_drivetrainSimulator.Update(20_ms);

View File

@@ -21,7 +21,6 @@
#include <frc/geometry/Quaternion.h>
#include <frc/geometry/Transform3d.h>
#include <frc/kinematics/DifferentialDriveKinematics.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc/simulation/AnalogGyroSim.h>
#include <frc/simulation/DifferentialDrivetrainSim.h>
@@ -140,9 +139,6 @@ class Drivetrain {
frc::PWMSparkMax m_rightLeader{3};
frc::PWMSparkMax m_rightFollower{4};
frc::MotorControllerGroup m_leftGroup{m_leftLeader, m_leftFollower};
frc::MotorControllerGroup m_rightGroup{m_rightLeader, m_rightFollower};
frc::Encoder m_leftEncoder{0, 1};
frc::Encoder m_rightEncoder{2, 3};

View File

@@ -12,16 +12,14 @@ DriveSubsystem::DriveSubsystem()
m_rightLeader{kRightMotor1Port},
m_rightFollower{kRightMotor2Port},
m_feedforward{ks, kv, ka} {
wpi::SendableRegistry::AddChild(&m_drive, &m_leftLeader);
wpi::SendableRegistry::AddChild(&m_drive, &m_rightLeader);
// 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.
m_rightLeader.SetInverted(true);
// You might need to not do this depending on the specific motor controller
// that you are using -- contact the respective vendor's documentation for
// more details.
m_rightFollower.SetInverted(true);
m_leftFollower.Follow(m_leftLeader);
m_rightFollower.Follow(m_rightLeader);

View File

@@ -4,15 +4,13 @@
#pragma once
#include <frc/motorcontrol/MotorController.h>
/**
* A simplified stub class that simulates the API of a common "smart" motor
* controller.
*
* <p>Has no actual functionality.
*/
class ExampleSmartMotorController : public frc::MotorController {
class ExampleSmartMotorController {
public:
enum PIDMode { kPosition, kVelocity, kMovementWitchcraft };
@@ -68,17 +66,17 @@ class ExampleSmartMotorController : public frc::MotorController {
*/
void ResetEncoder() {}
void Set(double speed) override { m_value = speed; }
void Set(double speed) { m_value = speed; }
double Get() const override { return m_value; }
double Get() const { return m_value; }
void SetInverted(bool isInverted) override {}
void SetInverted(bool isInverted) {}
bool GetInverted() const override { return false; }
bool GetInverted() const { return false; }
void Disable() override {}
void Disable() {}
void StopMotor() override {}
void StopMotor() {}
private:
double m_value = 0.0;

View File

@@ -83,5 +83,7 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::SimpleMotorFeedforward<units::meters> m_feedforward;
// The robot's drive
frc::DifferentialDrive m_drive{m_leftLeader, m_rightLeader};
frc::DifferentialDrive m_drive{
[&](double output) { m_leftLeader.Set(output); },
[&](double output) { m_rightLeader.Set(output); }};
};

View File

@@ -4,15 +4,13 @@
#pragma once
#include <frc/motorcontrol/MotorController.h>
/**
* A simplified stub class that simulates the API of a common "smart" motor
* controller.
*
* <p>Has no actual functionality.
*/
class ExampleSmartMotorController : public frc::MotorController {
class ExampleSmartMotorController {
public:
enum PIDMode { kPosition, kVelocity, kMovementWitchcraft };
@@ -68,15 +66,15 @@ class ExampleSmartMotorController : public frc::MotorController {
*/
void ResetEncoder() {}
void Set(double speed) override {}
void Set(double speed) {}
double Get() const override { return 0; }
double Get() const { return 0; }
void SetInverted(bool isInverted) override {}
void SetInverted(bool isInverted) {}
bool GetInverted() const override { return false; }
bool GetInverted() const { return false; }
void Disable() override {}
void Disable() {}
void StopMotor() override {}
void StopMotor() {}
};

View File

@@ -4,15 +4,13 @@
#pragma once
#include <frc/motorcontrol/MotorController.h>
/**
* A simplified stub class that simulates the API of a common "smart" motor
* controller.
*
* <p>Has no actual functionality.
*/
class ExampleSmartMotorController : public frc::MotorController {
class ExampleSmartMotorController {
public:
enum PIDMode { kPosition, kVelocity, kMovementWitchcraft };
@@ -68,15 +66,15 @@ class ExampleSmartMotorController : public frc::MotorController {
*/
void ResetEncoder() {}
void Set(double speed) override {}
void Set(double speed) {}
double Get() const override { return 0; }
double Get() const { return 0; }
void SetInverted(bool isInverted) override {}
void SetInverted(bool isInverted) {}
bool GetInverted() const override { return false; }
bool GetInverted() const { return false; }
void Disable() override {}
void Disable() {}
void StopMotor() override {}
void StopMotor() {}
};

View File

@@ -13,10 +13,16 @@ DriveSubsystem::DriveSubsystem()
m_right2{kRightMotor2Port},
m_leftEncoder{kLeftEncoderPorts[0], kLeftEncoderPorts[1]},
m_rightEncoder{kRightEncoderPorts[0], kRightEncoderPorts[1]} {
wpi::SendableRegistry::AddChild(&m_drive, &m_left1);
wpi::SendableRegistry::AddChild(&m_drive, &m_right1);
m_left1.AddFollower(m_left2);
m_right1.AddFollower(m_right2);
// 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.
m_leftMotors.SetInverted(true);
m_left1.SetInverted(true);
// Set the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);

View File

@@ -6,7 +6,6 @@
#include <frc/Encoder.h>
#include <frc/drive/DifferentialDrive.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/SubsystemBase.h>
@@ -75,14 +74,9 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_right1;
frc::PWMSparkMax m_right2;
// The motors on the left side of the drive
frc::MotorControllerGroup m_leftMotors{m_left1, m_left2};
// The motors on the right side of the drive
frc::MotorControllerGroup m_rightMotors{m_right1, m_right2};
// The robot's drive
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{[&](double output) { m_left1.Set(output); },
[&](double output) { m_right1.Set(output); }};
// The left-side drive encoder
frc::Encoder m_leftEncoder;

View File

@@ -11,10 +11,16 @@
#include <units/length.h>
Drivetrain::Drivetrain() {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_frontLeft);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_frontRight);
m_frontLeft.AddFollower(m_rearLeft);
m_frontRight.AddFollower(m_rearRight);
// 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.
m_right.SetInverted(true);
m_frontRight.SetInverted(true);
// Encoders may measure differently in the real world and in
// simulation. In this example the robot moves 0.042 barleycorns

View File

@@ -8,7 +8,6 @@
#include <frc/AnalogInput.h>
#include <frc/Encoder.h>
#include <frc/drive/DifferentialDrive.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/SubsystemBase.h>
@@ -66,13 +65,13 @@ class Drivetrain : public frc2::SubsystemBase {
private:
frc::PWMSparkMax m_frontLeft{1};
frc::PWMSparkMax m_rearLeft{2};
frc::MotorControllerGroup m_left{m_frontLeft, m_rearLeft};
frc::PWMSparkMax m_frontRight{3};
frc::PWMSparkMax m_rearRight{4};
frc::MotorControllerGroup m_right{m_frontRight, m_rearRight};
frc::DifferentialDrive m_robotDrive{m_left, m_right};
frc::DifferentialDrive m_robotDrive{
[&](double output) { m_frontLeft.Set(output); },
[&](double output) { m_frontRight.Set(output); }};
frc::Encoder m_leftEncoder{1, 2};
frc::Encoder m_rightEncoder{3, 4};

View File

@@ -11,6 +11,9 @@
class Robot : public frc::TimedRobot {
public:
Robot() {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_left);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_right);
// 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.
@@ -48,7 +51,9 @@ class Robot : public frc::TimedRobot {
// Robot drive system
frc::PWMSparkMax m_left{0};
frc::PWMSparkMax m_right{1};
frc::DifferentialDrive m_robotDrive{m_left, m_right};
frc::DifferentialDrive m_robotDrive{
[&](double output) { m_left.Set(output); },
[&](double output) { m_right.Set(output); }};
frc::XboxController m_controller{0};
frc::Timer m_timer;

View File

@@ -17,6 +17,11 @@
*/
class Robot : public frc::TimedRobot {
public:
Robot() {
wpi::SendableRegistry::AddChild(&m_drive, &m_left);
wpi::SendableRegistry::AddChild(&m_drive, &m_right);
}
void RobotInit() override {
m_gyro.SetSensitivity(kVoltsPerDegreePerSecond);
// We need to invert one side of the drivetrain so that positive voltages
@@ -50,7 +55,8 @@ class Robot : public frc::TimedRobot {
frc::PWMSparkMax m_left{kLeftMotorPort};
frc::PWMSparkMax m_right{kRightMotorPort};
frc::DifferentialDrive m_drive{m_left, m_right};
frc::DifferentialDrive m_drive{[&](double output) { m_left.Set(output); },
[&](double output) { m_right.Set(output); }};
frc::AnalogGyro m_gyro{kGyroPort};
frc::Joystick m_joystick{kJoystickPort};

View File

@@ -13,10 +13,16 @@ DriveSubsystem::DriveSubsystem()
m_right2{kRightMotor2Port},
m_leftEncoder{kLeftEncoderPorts[0], kLeftEncoderPorts[1]},
m_rightEncoder{kRightEncoderPorts[0], kRightEncoderPorts[1]} {
wpi::SendableRegistry::AddChild(&m_drive, &m_left1);
wpi::SendableRegistry::AddChild(&m_drive, &m_right1);
m_left1.AddFollower(m_left2);
m_right1.AddFollower(m_right2);
// 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.
m_rightMotors.SetInverted(true);
m_right1.SetInverted(true);
// Set the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);

View File

@@ -7,7 +7,6 @@
#include <frc/ADXRS450_Gyro.h>
#include <frc/Encoder.h>
#include <frc/drive/DifferentialDrive.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/SubsystemBase.h>
#include <units/angle.h>
@@ -91,14 +90,9 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_right1;
frc::PWMSparkMax m_right2;
// The motors on the left side of the drive
frc::MotorControllerGroup m_leftMotors{m_left1, m_left2};
// The motors on the right side of the drive
frc::MotorControllerGroup m_rightMotors{m_right1, m_right2};
// The robot's drive
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{[&](double output) { m_left1.Set(output); },
[&](double output) { m_right1.Set(output); }};
// The left-side drive encoder
frc::Encoder m_leftEncoder;

View File

@@ -16,6 +16,11 @@
class Robot : public frc::TimedRobot {
public:
void RobotInit() override {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_frontLeft);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_rearLeft);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_frontRight);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_rearRight);
// Invert the right side motors. You may need to change or remove this to
// match your robot.
m_frontRight.SetInverted(true);
@@ -48,8 +53,11 @@ class Robot : public frc::TimedRobot {
frc::PWMSparkMax m_rearLeft{kRearLeftMotorPort};
frc::PWMSparkMax m_frontRight{kFrontRightMotorPort};
frc::PWMSparkMax m_rearRight{kRearRightMotorPort};
frc::MecanumDrive m_robotDrive{m_frontLeft, m_rearLeft, m_frontRight,
m_rearRight};
frc::MecanumDrive m_robotDrive{
[&](double output) { m_frontLeft.Set(output); },
[&](double output) { m_rearLeft.Set(output); },
[&](double output) { m_frontRight.Set(output); },
[&](double output) { m_rearRight.Set(output); }};
frc::AnalogGyro m_gyro{kGyroPort};
frc::Joystick m_joystick{kJoystickPort};

View File

@@ -15,10 +15,16 @@ DriveSubsystem::DriveSubsystem()
m_right2{kRightMotor2Port},
m_leftEncoder{kLeftEncoderPorts[0], kLeftEncoderPorts[1]},
m_rightEncoder{kRightEncoderPorts[0], kRightEncoderPorts[1]} {
wpi::SendableRegistry::AddChild(&m_drive, &m_left1);
wpi::SendableRegistry::AddChild(&m_drive, &m_right1);
m_left1.AddFollower(m_left2);
m_right1.AddFollower(m_right2);
// 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.
m_rightMotors.SetInverted(true);
m_right1.SetInverted(true);
// Set the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);

View File

@@ -6,7 +6,6 @@
#include <frc/Encoder.h>
#include <frc/drive/DifferentialDrive.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/SubsystemBase.h>
@@ -63,14 +62,9 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_right1;
frc::PWMSparkMax m_right2;
// The motors on the left side of the drive
frc::MotorControllerGroup m_leftMotors{m_left1, m_left2};
// The motors on the right side of the drive
frc::MotorControllerGroup m_rightMotors{m_right1, m_right2};
// The robot's drive
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{[&](double output) { m_left1.Set(output); },
[&](double output) { m_right1.Set(output); }};
// The left-side drive encoder
frc::Encoder m_leftEncoder;

View File

@@ -15,10 +15,16 @@ DriveSubsystem::DriveSubsystem()
m_right2{kRightMotor2Port},
m_leftEncoder{kLeftEncoderPorts[0], kLeftEncoderPorts[1]},
m_rightEncoder{kRightEncoderPorts[0], kRightEncoderPorts[1]} {
wpi::SendableRegistry::AddChild(&m_drive, &m_left1);
wpi::SendableRegistry::AddChild(&m_drive, &m_right1);
m_left1.AddFollower(m_left2);
m_right1.AddFollower(m_right2);
// 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.
m_rightMotors.SetInverted(true);
m_right1.SetInverted(true);
// Set the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);

View File

@@ -6,7 +6,6 @@
#include <frc/Encoder.h>
#include <frc/drive/DifferentialDrive.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/SubsystemBase.h>
@@ -63,14 +62,9 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_right1;
frc::PWMSparkMax m_right2;
// The motors on the left side of the drive
frc::MotorControllerGroup m_leftMotors{m_left1, m_left2};
// The motors on the right side of the drive
frc::MotorControllerGroup m_rightMotors{m_right1, m_right2};
// The robot's drive
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{[&](double output) { m_left1.Set(output); },
[&](double output) { m_right1.Set(output); }};
// The left-side drive encoder
frc::Encoder m_leftEncoder;

View File

@@ -30,6 +30,11 @@ DriveSubsystem::DriveSubsystem()
m_odometry{kDriveKinematics, m_gyro.GetRotation2d(),
getCurrentWheelDistances(), frc::Pose2d{}} {
wpi::SendableRegistry::AddChild(&m_drive, &m_frontLeft);
wpi::SendableRegistry::AddChild(&m_drive, &m_rearLeft);
wpi::SendableRegistry::AddChild(&m_drive, &m_frontRight);
wpi::SendableRegistry::AddChild(&m_drive, &m_rearRight);
// Set the distance per pulse for the encoders
m_frontLeftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);
m_rearLeftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);

View File

@@ -148,7 +148,10 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_rearRight;
// The robot's drive
frc::MecanumDrive m_drive{m_frontLeft, m_rearLeft, m_frontRight, m_rearRight};
frc::MecanumDrive m_drive{[&](double output) { m_frontLeft.Set(output); },
[&](double output) { m_rearLeft.Set(output); },
[&](double output) { m_frontRight.Set(output); },
[&](double output) { m_rearRight.Set(output); }};
// The front-left-side drive encoder
frc::Encoder m_frontLeftEncoder;

View File

@@ -14,6 +14,11 @@
class Robot : public frc::TimedRobot {
public:
void RobotInit() override {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_frontLeft);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_rearLeft);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_frontRight);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_rearRight);
// Invert the right side motors. You may need to change or remove this to
// match your robot.
m_frontRight.SetInverted(true);
@@ -40,8 +45,11 @@ class Robot : public frc::TimedRobot {
frc::PWMSparkMax m_rearLeft{kRearLeftChannel};
frc::PWMSparkMax m_frontRight{kFrontRightChannel};
frc::PWMSparkMax m_rearRight{kRearRightChannel};
frc::MecanumDrive m_robotDrive{m_frontLeft, m_rearLeft, m_frontRight,
m_rearRight};
frc::MecanumDrive m_robotDrive{
[&](double output) { m_frontLeft.Set(output); },
[&](double output) { m_rearLeft.Set(output); },
[&](double output) { m_frontRight.Set(output); },
[&](double output) { m_rearRight.Set(output); }};
frc::Joystick m_stick{kJoystickChannel};
};

View File

@@ -17,10 +17,16 @@ DriveSubsystem::DriveSubsystem()
m_leftEncoder{kLeftEncoderPorts[0], kLeftEncoderPorts[1]},
m_rightEncoder{kRightEncoderPorts[0], kRightEncoderPorts[1]},
m_odometry{m_gyro.GetRotation2d(), units::meter_t{0}, units::meter_t{0}} {
wpi::SendableRegistry::AddChild(&m_drive, &m_left1);
wpi::SendableRegistry::AddChild(&m_drive, &m_right1);
m_left1.AddFollower(m_left2);
m_right1.AddFollower(m_right2);
// 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.
m_rightMotors.SetInverted(true);
m_right1.SetInverted(true);
// Set the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse.value());
@@ -41,8 +47,8 @@ void DriveSubsystem::ArcadeDrive(double fwd, double rot) {
}
void DriveSubsystem::TankDriveVolts(units::volt_t left, units::volt_t right) {
m_leftMotors.SetVoltage(left);
m_rightMotors.SetVoltage(right);
m_left1.SetVoltage(left);
m_right1.SetVoltage(right);
m_drive.Feed();
}

View File

@@ -9,7 +9,6 @@
#include <frc/drive/DifferentialDrive.h>
#include <frc/geometry/Pose2d.h>
#include <frc/kinematics/DifferentialDriveOdometry.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/SubsystemBase.h>
#include <units/voltage.h>
@@ -122,14 +121,9 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_right1;
frc::PWMSparkMax m_right2;
// The motors on the left side of the drive
frc::MotorControllerGroup m_leftMotors{m_left1, m_left2};
// The motors on the right side of the drive
frc::MotorControllerGroup m_rightMotors{m_right1, m_right2};
// The robot's drive
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{[&](double output) { m_left1.Set(output); },
[&](double output) { m_right1.Set(output); }};
// The left-side drive encoder
frc::Encoder m_leftEncoder;

View File

@@ -12,8 +12,8 @@ void Drivetrain::SetSpeeds(const frc::DifferentialDriveWheelSpeeds& speeds) {
const double rightOutput = m_rightPIDController.Calculate(
m_rightEncoder.GetRate(), speeds.right.value());
m_leftGroup.SetVoltage(units::volt_t{leftOutput} + leftFeedforward);
m_rightGroup.SetVoltage(units::volt_t{rightOutput} + rightFeedforward);
m_leftLeader.SetVoltage(units::volt_t{leftOutput} + leftFeedforward);
m_rightLeader.SetVoltage(units::volt_t{rightOutput} + rightFeedforward);
}
void Drivetrain::Drive(units::meters_per_second_t xSpeed,

View File

@@ -12,7 +12,6 @@
#include <frc/controller/SimpleMotorFeedforward.h>
#include <frc/kinematics/DifferentialDriveKinematics.h>
#include <frc/kinematics/DifferentialDriveOdometry.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <units/angular_velocity.h>
#include <units/length.h>
@@ -25,10 +24,13 @@ class Drivetrain {
Drivetrain() {
m_gyro.Reset();
m_leftLeader.AddFollower(m_leftFollower);
m_rightLeader.AddFollower(m_rightFollower);
// 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.
m_rightGroup.SetInverted(true);
m_rightLeader.SetInverted(true);
// Set the distance per pulse for the drive encoders. We can simply use the
// distance traveled for one rotation of the wheel divided by the encoder
@@ -64,9 +66,6 @@ class Drivetrain {
frc::PWMSparkMax m_rightLeader{3};
frc::PWMSparkMax m_rightFollower{4};
frc::MotorControllerGroup m_leftGroup{m_leftLeader, m_leftFollower};
frc::MotorControllerGroup m_rightGroup{m_rightLeader, m_rightFollower};
frc::Encoder m_leftEncoder{0, 1};
frc::Encoder m_rightEncoder{2, 3};

View File

@@ -9,10 +9,16 @@
#include <frc2/command/Commands.h>
Drive::Drive() {
wpi::SendableRegistry::AddChild(&m_drive, &m_leftLeader);
wpi::SendableRegistry::AddChild(&m_drive, &m_rightLeader);
m_leftLeader.AddFollower(m_leftFollower);
m_rightLeader.AddFollower(m_rightFollower);
// 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.
m_rightMotors.SetInverted(true);
m_rightLeader.SetInverted(true);
// Sets the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(DriveConstants::kEncoderDistancePerPulse);

View File

@@ -8,7 +8,6 @@
#include <frc/Encoder.h>
#include <frc/drive/DifferentialDrive.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc2/command/CommandPtr.h>
#include <frc2/command/SubsystemBase.h>
@@ -45,10 +44,9 @@ class Drive : public frc2::SubsystemBase {
frc::PWMSparkMax m_rightLeader{DriveConstants::kRightMotor1Port};
frc::PWMSparkMax m_rightFollower{DriveConstants::kRightMotor2Port};
frc::MotorControllerGroup m_leftMotors{m_leftLeader, m_leftFollower};
frc::MotorControllerGroup m_rightMotors{m_rightLeader, m_rightFollower};
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{
[&](double output) { m_leftLeader.Set(output); },
[&](double output) { m_rightLeader.Set(output); }};
frc::Encoder m_leftEncoder{DriveConstants::kLeftEncoderPorts[0],
DriveConstants::kLeftEncoderPorts[1],

View File

@@ -15,6 +15,9 @@ using namespace DriveConstants;
// The Romi has onboard encoders that are hardcoded
// to use DIO pins 4/5 and 6/7 for the left and right
Drivetrain::Drivetrain() {
wpi::SendableRegistry::AddChild(&m_drive, &m_leftMotor);
wpi::SendableRegistry::AddChild(&m_drive, &m_rightMotor);
// 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.

View File

@@ -114,7 +114,9 @@ class Drivetrain : public frc2::SubsystemBase {
frc::Encoder m_leftEncoder{4, 5};
frc::Encoder m_rightEncoder{6, 7};
frc::DifferentialDrive m_drive{m_leftMotor, m_rightMotor};
frc::DifferentialDrive m_drive{
[&](double output) { m_leftMotor.Set(output); },
[&](double output) { m_rightMotor.Set(output); }};
frc::RomiGyro m_gyro;
frc::BuiltInAccelerometer m_accelerometer;

View File

@@ -30,6 +30,9 @@
class Robot : public frc::TimedRobot {
public:
void RobotInit() override {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_left);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_right);
// Add a widget titled 'Max Speed' with a number slider.
m_maxSpeed = frc::Shuffleboard::GetTab("Configuration")
.Add("Max Speed", 1)
@@ -65,7 +68,9 @@ class Robot : public frc::TimedRobot {
frc::PWMSparkMax m_right{1};
frc::PWMSparkMax m_elevatorMotor{2};
frc::DifferentialDrive m_robotDrive{m_left, m_right};
frc::DifferentialDrive m_robotDrive{
[&](double output) { m_left.Set(output); },
[&](double output) { m_right.Set(output); }};
frc::Joystick m_stick{0};

View File

@@ -14,8 +14,8 @@ void Drivetrain::SetSpeeds(const frc::DifferentialDriveWheelSpeeds& speeds) {
double rightOutput = m_rightPIDController.Calculate(m_rightEncoder.GetRate(),
speeds.right.value());
m_leftGroup.SetVoltage(units::volt_t{leftOutput} + leftFeedforward);
m_rightGroup.SetVoltage(units::volt_t{rightOutput} + rightFeedforward);
m_leftLeader.SetVoltage(units::volt_t{leftOutput} + leftFeedforward);
m_rightLeader.SetVoltage(units::volt_t{rightOutput} + rightFeedforward);
}
void Drivetrain::Drive(units::meters_per_second_t xSpeed,
@@ -43,9 +43,9 @@ void Drivetrain::SimulationPeriodic() {
// simulation, and write the simulated positions and velocities to our
// simulated encoder and gyro. We negate the right side so that positive
// voltages make the right side move forward.
m_drivetrainSimulator.SetInputs(units::volt_t{m_leftGroup.Get()} *
m_drivetrainSimulator.SetInputs(units::volt_t{m_leftLeader.Get()} *
frc::RobotController::GetInputVoltage(),
units::volt_t{m_rightGroup.Get()} *
units::volt_t{m_rightLeader.Get()} *
frc::RobotController::GetInputVoltage());
m_drivetrainSimulator.Update(20_ms);

View File

@@ -12,7 +12,6 @@
#include <frc/controller/SimpleMotorFeedforward.h>
#include <frc/kinematics/DifferentialDriveKinematics.h>
#include <frc/kinematics/DifferentialDriveOdometry.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc/simulation/AnalogGyroSim.h>
#include <frc/simulation/DifferentialDrivetrainSim.h>
@@ -33,10 +32,13 @@ class Drivetrain {
Drivetrain() {
m_gyro.Reset();
m_leftLeader.AddFollower(m_leftFollower);
m_rightLeader.AddFollower(m_rightFollower);
// 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.
m_rightGroup.SetInverted(true);
m_rightLeader.SetInverted(true);
// Set the distance per pulse for the drive encoders. We can simply use the
// distance traveled for one rotation of the wheel divided by the encoder
@@ -49,7 +51,7 @@ class Drivetrain {
m_leftEncoder.Reset();
m_rightEncoder.Reset();
m_rightGroup.SetInverted(true);
m_rightLeader.SetInverted(true);
frc::SmartDashboard::PutData("Field", &m_fieldSim);
}
@@ -80,9 +82,6 @@ class Drivetrain {
frc::PWMSparkMax m_rightLeader{3};
frc::PWMSparkMax m_rightFollower{4};
frc::MotorControllerGroup m_leftGroup{m_leftLeader, m_leftFollower};
frc::MotorControllerGroup m_rightGroup{m_rightLeader, m_rightFollower};
frc::Encoder m_leftEncoder{0, 1};
frc::Encoder m_rightEncoder{2, 3};

View File

@@ -14,10 +14,16 @@
using namespace DriveConstants;
DriveSubsystem::DriveSubsystem() {
wpi::SendableRegistry::AddChild(&m_drive, &m_left1);
wpi::SendableRegistry::AddChild(&m_drive, &m_right1);
m_left1.AddFollower(m_left2);
m_right1.AddFollower(m_right2);
// 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.
m_rightMotors.SetInverted(true);
m_right1.SetInverted(true);
// Set the distance per pulse for the encoders
m_leftEncoder.SetDistancePerPulse(kEncoderDistancePerPulse);
@@ -40,10 +46,9 @@ void DriveSubsystem::SimulationPeriodic() {
// simulation, and write the simulated positions and velocities to our
// simulated encoder and gyro. We negate the right side so that positive
// voltages make the right side move forward.
m_drivetrainSimulator.SetInputs(units::volt_t{m_leftMotors.Get()} *
frc::RobotController::GetInputVoltage(),
units::volt_t{m_rightMotors.Get()} *
frc::RobotController::GetInputVoltage());
m_drivetrainSimulator.SetInputs(
units::volt_t{m_left1.Get()} * frc::RobotController::GetInputVoltage(),
units::volt_t{m_right1.Get()} * frc::RobotController::GetInputVoltage());
m_drivetrainSimulator.Update(20_ms);
m_leftEncoderSim.SetDistance(m_drivetrainSimulator.GetLeftPosition().value());
@@ -63,8 +68,8 @@ void DriveSubsystem::ArcadeDrive(double fwd, double rot) {
}
void DriveSubsystem::TankDriveVolts(units::volt_t left, units::volt_t right) {
m_leftMotors.SetVoltage(left);
m_rightMotors.SetVoltage(right);
m_left1.SetVoltage(left);
m_right1.SetVoltage(right);
m_drive.Feed();
}

View File

@@ -9,7 +9,6 @@
#include <frc/drive/DifferentialDrive.h>
#include <frc/geometry/Pose2d.h>
#include <frc/kinematics/DifferentialDriveOdometry.h>
#include <frc/motorcontrol/MotorControllerGroup.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <frc/simulation/ADXRS450_GyroSim.h>
#include <frc/simulation/DifferentialDrivetrainSim.h>
@@ -133,14 +132,9 @@ class DriveSubsystem : public frc2::SubsystemBase {
frc::PWMSparkMax m_right1{DriveConstants::kRightMotor1Port};
frc::PWMSparkMax m_right2{DriveConstants::kRightMotor2Port};
// The motors on the left side of the drive
frc::MotorControllerGroup m_leftMotors{m_left1, m_left2};
// The motors on the right side of the drive
frc::MotorControllerGroup m_rightMotors{m_right1, m_right2};
// The robot's drive
frc::DifferentialDrive m_drive{m_leftMotors, m_rightMotors};
frc::DifferentialDrive m_drive{[&](double output) { m_left1.Set(output); },
[&](double output) { m_right1.Set(output); }};
// The left-side drive encoder
frc::Encoder m_leftEncoder{DriveConstants::kLeftEncoderPorts[0],

View File

@@ -14,12 +14,17 @@
class Robot : public frc::TimedRobot {
frc::PWMSparkMax m_leftMotor{0};
frc::PWMSparkMax m_rightMotor{1};
frc::DifferentialDrive m_robotDrive{m_leftMotor, m_rightMotor};
frc::DifferentialDrive m_robotDrive{
[&](double output) { m_leftMotor.Set(output); },
[&](double output) { m_rightMotor.Set(output); }};
frc::Joystick m_leftStick{0};
frc::Joystick m_rightStick{1};
public:
void RobotInit() override {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_leftMotor);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_rightMotor);
// 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.

View File

@@ -14,11 +14,16 @@
class Robot : public frc::TimedRobot {
frc::PWMSparkMax m_leftMotor{0};
frc::PWMSparkMax m_rightMotor{1};
frc::DifferentialDrive m_robotDrive{m_leftMotor, m_rightMotor};
frc::DifferentialDrive m_robotDrive{
[&](double output) { m_leftMotor.Set(output); },
[&](double output) { m_rightMotor.Set(output); }};
frc::XboxController m_driverController{0};
public:
void RobotInit() override {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_leftMotor);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_rightMotor);
// 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.

View File

@@ -4,6 +4,11 @@
#include "Robot.h"
Robot::Robot() {
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_left);
wpi::SendableRegistry::AddChild(&m_robotDrive, &m_right);
}
void Robot::AutonomousInit() {
// Set setpoint of the pid controller
m_pidController.SetSetpoint(kHoldDistance.value());

View File

@@ -18,6 +18,7 @@
*/
class Robot : public frc::TimedRobot {
public:
Robot();
void AutonomousInit() override;
void AutonomousPeriodic() override;
@@ -44,6 +45,8 @@ class Robot : public frc::TimedRobot {
frc::Ultrasonic m_ultrasonic{kUltrasonicPingPort, kUltrasonicEchoPort};
frc::PWMSparkMax m_left{kLeftMotorPort};
frc::PWMSparkMax m_right{kRightMotorPort};
frc::DifferentialDrive m_robotDrive{m_left, m_right};
frc::DifferentialDrive m_robotDrive{
[&](double output) { m_left.Set(output); },
[&](double output) { m_right.Set(output); }};
frc::PIDController m_pidController{kP, kI, kD};
};

View File

@@ -15,6 +15,9 @@ using namespace DriveConstants;
// The XRP has onboard encoders that are hardcoded
// to use DIO pins 4/5 and 6/7 for the left and right
Drivetrain::Drivetrain() {
wpi::SendableRegistry::AddChild(&m_drive, &m_leftMotor);
wpi::SendableRegistry::AddChild(&m_drive, &m_rightMotor);
// 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.

View File

@@ -118,7 +118,9 @@ class Drivetrain : public frc2::SubsystemBase {
frc::Encoder m_leftEncoder{4, 5};
frc::Encoder m_rightEncoder{6, 7};
frc::DifferentialDrive m_drive{m_leftMotor, m_rightMotor};
frc::DifferentialDrive m_drive{
[&](double output) { m_leftMotor.Set(output); },
[&](double output) { m_rightMotor.Set(output); }};
frc::XRPGyro m_gyro;
frc::BuiltInAccelerometer m_accelerometer;

View File

@@ -6,6 +6,7 @@
#include <gtest/gtest.h>
#include <units/time.h>
#include <wpi/deprecated.h>
#include "TestBench.h"
#include "frc/Encoder.h"
@@ -37,6 +38,8 @@ std::ostream& operator<<(std::ostream& os, MotorEncoderTestType const& type) {
static constexpr auto kMotorTime = 0.5_s;
WPI_IGNORE_DEPRECATED
/**
* A fixture that includes a PWM motor controller and an encoder connected to
* the same motor.
@@ -197,3 +200,5 @@ TEST_P(MotorEncoderTest, Reset) {
INSTANTIATE_TEST_SUITE_P(Tests, MotorEncoderTest,
testing::Values(TEST_VICTOR, TEST_JAGUAR, TEST_TALON));
WPI_UNIGNORE_DEPRECATED

View File

@@ -4,6 +4,7 @@
#include <gtest/gtest.h>
#include <units/time.h>
#include <wpi/deprecated.h>
#include "TestBench.h"
#include "frc/Encoder.h"
@@ -32,6 +33,9 @@ std::ostream& operator<<(std::ostream& os, MotorInvertingTestType const& type) {
return os;
}
WPI_IGNORE_DEPRECATED
class MotorInvertingTest
: public testing::TestWithParam<MotorInvertingTestType> {
protected:
@@ -153,3 +157,5 @@ TEST_P(MotorInvertingTest, InvertingSwitchingNegToPos) {
INSTANTIATE_TEST_SUITE_P(Tests, MotorInvertingTest,
testing::Values(TEST_VICTOR, TEST_JAGUAR, TEST_TALON));
WPI_UNIGNORE_DEPRECATED

View File

@@ -14,49 +14,16 @@ import edu.wpi.first.util.sendable.Sendable;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
import java.util.function.DoubleConsumer;
/**
* A class for driving differential drive/skid-steer drive platforms such as the Kit of Parts drive
* base, "tank drive", or West Coast Drive.
*
* <p>These drive bases typically have drop-center / skid-steer with two or more wheels per side
* (e.g., 6WD or 8WD). This class takes a MotorController per side. For four and six motor
* drivetrains, construct and pass in {@link
* edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup} instances as follows.
*
* <p>Four motor drivetrain:
*
* <pre><code>
* public class Robot {
* MotorController m_frontLeft = new PWMVictorSPX(1);
* MotorController m_rearLeft = new PWMVictorSPX(2);
* MotorControllerGroup m_left = new MotorControllerGroup(m_frontLeft, m_rearLeft);
*
* MotorController m_frontRight = new PWMVictorSPX(3);
* MotorController m_rearRight = new PWMVictorSPX(4);
* MotorControllerGroup m_right = new MotorControllerGroup(m_frontRight, m_rearRight);
*
* DifferentialDrive m_drive = new DifferentialDrive(m_left, m_right);
* }
* </code></pre>
*
* <p>Six motor drivetrain:
*
* <pre><code>
* public class Robot {
* MotorController m_frontLeft = new PWMVictorSPX(1);
* MotorController m_midLeft = new PWMVictorSPX(2);
* MotorController m_rearLeft = new PWMVictorSPX(3);
* MotorControllerGroup m_left = new MotorControllerGroup(m_frontLeft, m_midLeft, m_rearLeft);
*
* MotorController m_frontRight = new PWMVictorSPX(4);
* MotorController m_midRight = new PWMVictorSPX(5);
* MotorController m_rearRight = new PWMVictorSPX(6);
* MotorControllerGroup m_right = new MotorControllerGroup(m_frontRight, m_midRight, m_rearRight);
*
* DifferentialDrive m_drive = new DifferentialDrive(m_left, m_right);
* }
* </code></pre>
* (e.g., 6WD or 8WD). This class takes a setter per side. For four and six motor drivetrains, use
* CAN motor controller followers or {@link
* edu.wpi.first.wpilibj.motorcontrol.PWMMotorController#addFollower(PWMMotorController)}.
*
* <p>A differential drive robot has left and right wheels separated by an arbitrary width.
*
@@ -88,8 +55,12 @@ import edu.wpi.first.wpilibj.motorcontrol.MotorController;
public class DifferentialDrive extends RobotDriveBase implements Sendable, AutoCloseable {
private static int instances;
private final MotorController m_leftMotor;
private final MotorController m_rightMotor;
private final DoubleConsumer m_leftMotor;
private final DoubleConsumer m_rightMotor;
// Used for Sendable property getters
private double m_leftOutput;
private double m_rightOutput;
private boolean m_reported;
@@ -128,15 +99,30 @@ public class DifferentialDrive extends RobotDriveBase implements Sendable, AutoC
* @param leftMotor Left motor.
* @param rightMotor Right motor.
*/
@SuppressWarnings("this-escape")
@SuppressWarnings({"removal", "this-escape"})
public DifferentialDrive(MotorController leftMotor, MotorController rightMotor) {
this((double output) -> leftMotor.set(output), (double output) -> rightMotor.set(output));
SendableRegistry.addChild(this, leftMotor);
SendableRegistry.addChild(this, rightMotor);
}
/**
* Construct a DifferentialDrive.
*
* <p>To pass multiple motors per side, use CAN motor controller followers or {@link
* edu.wpi.first.wpilibj.motorcontrol.PWMMotorController#addFollower(PWMMotorController)}. If a
* motor needs to be inverted, do so before passing it in.
*
* @param leftMotor Left motor setter.
* @param rightMotor Right motor setter.
*/
@SuppressWarnings("this-escape")
public DifferentialDrive(DoubleConsumer leftMotor, DoubleConsumer rightMotor) {
requireNonNullParam(leftMotor, "leftMotor", "DifferentialDrive");
requireNonNullParam(rightMotor, "rightMotor", "DifferentialDrive");
m_leftMotor = leftMotor;
m_rightMotor = rightMotor;
SendableRegistry.addChild(this, m_leftMotor);
SendableRegistry.addChild(this, m_rightMotor);
instances++;
SendableRegistry.addLW(this, "DifferentialDrive", instances);
}
@@ -178,8 +164,11 @@ public class DifferentialDrive extends RobotDriveBase implements Sendable, AutoC
var speeds = arcadeDriveIK(xSpeed, zRotation, squareInputs);
m_leftMotor.set(speeds.left * m_maxOutput);
m_rightMotor.set(speeds.right * m_maxOutput);
m_leftOutput = speeds.left * m_maxOutput;
m_rightOutput = speeds.right * m_maxOutput;
m_leftMotor.accept(m_leftOutput);
m_rightMotor.accept(m_rightOutput);
feed();
}
@@ -207,8 +196,11 @@ public class DifferentialDrive extends RobotDriveBase implements Sendable, AutoC
var speeds = curvatureDriveIK(xSpeed, zRotation, allowTurnInPlace);
m_leftMotor.set(speeds.left * m_maxOutput);
m_rightMotor.set(speeds.right * m_maxOutput);
m_leftOutput = speeds.left * m_maxOutput;
m_rightOutput = speeds.right * m_maxOutput;
m_leftMotor.accept(m_leftOutput);
m_rightMotor.accept(m_rightOutput);
feed();
}
@@ -245,8 +237,11 @@ public class DifferentialDrive extends RobotDriveBase implements Sendable, AutoC
var speeds = tankDriveIK(leftSpeed, rightSpeed, squareInputs);
m_leftMotor.set(speeds.left * m_maxOutput);
m_rightMotor.set(speeds.right * m_maxOutput);
m_leftOutput = speeds.left * m_maxOutput;
m_rightOutput = speeds.right * m_maxOutput;
m_leftMotor.accept(m_leftOutput);
m_rightMotor.accept(m_rightOutput);
feed();
}
@@ -351,8 +346,12 @@ public class DifferentialDrive extends RobotDriveBase implements Sendable, AutoC
@Override
public void stopMotor() {
m_leftMotor.stopMotor();
m_rightMotor.stopMotor();
m_leftOutput = 0.0;
m_rightOutput = 0.0;
m_leftMotor.accept(0.0);
m_rightMotor.accept(0.0);
feed();
}
@@ -366,7 +365,7 @@ public class DifferentialDrive extends RobotDriveBase implements Sendable, AutoC
builder.setSmartDashboardType("DifferentialDrive");
builder.setActuator(true);
builder.setSafeState(this::stopMotor);
builder.addDoubleProperty("Left Motor Speed", m_leftMotor::get, m_leftMotor::set);
builder.addDoubleProperty("Right Motor Speed", m_rightMotor::get, m_rightMotor::set);
builder.addDoubleProperty("Left Motor Speed", () -> m_leftOutput, m_leftMotor::accept);
builder.addDoubleProperty("Right Motor Speed", () -> m_rightOutput, m_rightMotor::accept);
}
}

View File

@@ -16,6 +16,7 @@ import edu.wpi.first.util.sendable.Sendable;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
import java.util.function.DoubleConsumer;
/**
* A class for driving Mecanum drive platforms.
@@ -56,10 +57,16 @@ import edu.wpi.first.wpilibj.motorcontrol.MotorController;
public class MecanumDrive extends RobotDriveBase implements Sendable, AutoCloseable {
private static int instances;
private final MotorController m_frontLeftMotor;
private final MotorController m_rearLeftMotor;
private final MotorController m_frontRightMotor;
private final MotorController m_rearRightMotor;
private final DoubleConsumer m_frontLeftMotor;
private final DoubleConsumer m_rearLeftMotor;
private final DoubleConsumer m_frontRightMotor;
private final DoubleConsumer m_rearRightMotor;
// Used for Sendable property getters
private double m_frontLeftOutput;
private double m_rearLeftOutput;
private double m_frontRightOutput;
private double m_rearRightOutput;
private boolean m_reported;
@@ -104,12 +111,39 @@ public class MecanumDrive extends RobotDriveBase implements Sendable, AutoClosea
* @param frontRightMotor The motor on the front-right corner.
* @param rearRightMotor The motor on the rear-right corner.
*/
@SuppressWarnings("this-escape")
@SuppressWarnings({"removal", "this-escape"})
public MecanumDrive(
MotorController frontLeftMotor,
MotorController rearLeftMotor,
MotorController frontRightMotor,
MotorController rearRightMotor) {
this(
(double output) -> frontLeftMotor.set(output),
(double output) -> rearLeftMotor.set(output),
(double output) -> frontRightMotor.set(output),
(double output) -> rearRightMotor.set(output));
SendableRegistry.addChild(this, frontLeftMotor);
SendableRegistry.addChild(this, rearLeftMotor);
SendableRegistry.addChild(this, frontRightMotor);
SendableRegistry.addChild(this, rearRightMotor);
}
/**
* Construct a MecanumDrive.
*
* <p>If a motor needs to be inverted, do so before passing it in.
*
* @param frontLeftMotor The setter for the motor on the front-left corner.
* @param rearLeftMotor The setter for the motor on the rear-left corner.
* @param frontRightMotor The setter for the motor on the front-right corner.
* @param rearRightMotor The setter for the motor on the rear-right corner.
*/
@SuppressWarnings("this-escape")
public MecanumDrive(
DoubleConsumer frontLeftMotor,
DoubleConsumer rearLeftMotor,
DoubleConsumer frontRightMotor,
DoubleConsumer rearRightMotor) {
requireNonNullParam(frontLeftMotor, "frontLeftMotor", "MecanumDrive");
requireNonNullParam(rearLeftMotor, "rearLeftMotor", "MecanumDrive");
requireNonNullParam(frontRightMotor, "frontRightMotor", "MecanumDrive");
@@ -119,10 +153,6 @@ public class MecanumDrive extends RobotDriveBase implements Sendable, AutoClosea
m_rearLeftMotor = rearLeftMotor;
m_frontRightMotor = frontRightMotor;
m_rearRightMotor = rearRightMotor;
SendableRegistry.addChild(this, m_frontLeftMotor);
SendableRegistry.addChild(this, m_rearLeftMotor);
SendableRegistry.addChild(this, m_frontRightMotor);
SendableRegistry.addChild(this, m_rearRightMotor);
instances++;
SendableRegistry.addLW(this, "MecanumDrive", instances);
}
@@ -172,10 +202,15 @@ public class MecanumDrive extends RobotDriveBase implements Sendable, AutoClosea
var speeds = driveCartesianIK(xSpeed, ySpeed, zRotation, gyroAngle);
m_frontLeftMotor.set(speeds.frontLeft * m_maxOutput);
m_frontRightMotor.set(speeds.frontRight * m_maxOutput);
m_rearLeftMotor.set(speeds.rearLeft * m_maxOutput);
m_rearRightMotor.set(speeds.rearRight * m_maxOutput);
m_frontLeftOutput = speeds.frontLeft * m_maxOutput;
m_rearLeftOutput = speeds.rearLeft * m_maxOutput;
m_frontRightOutput = speeds.frontRight * m_maxOutput;
m_rearRightOutput = speeds.rearRight * m_maxOutput;
m_frontLeftMotor.accept(m_frontLeftOutput);
m_frontRightMotor.accept(m_frontRightOutput);
m_rearLeftMotor.accept(m_rearLeftOutput);
m_rearRightMotor.accept(m_rearRightOutput);
feed();
}
@@ -256,10 +291,16 @@ public class MecanumDrive extends RobotDriveBase implements Sendable, AutoClosea
@Override
public void stopMotor() {
m_frontLeftMotor.stopMotor();
m_frontRightMotor.stopMotor();
m_rearLeftMotor.stopMotor();
m_rearRightMotor.stopMotor();
m_frontLeftOutput = 0.0;
m_frontRightOutput = 0.0;
m_rearLeftOutput = 0.0;
m_rearRightOutput = 0.0;
m_frontLeftMotor.accept(0.0);
m_frontRightMotor.accept(0.0);
m_rearLeftMotor.accept(0.0);
m_rearRightMotor.accept(0.0);
feed();
}
@@ -274,11 +315,12 @@ public class MecanumDrive extends RobotDriveBase implements Sendable, AutoClosea
builder.setActuator(true);
builder.setSafeState(this::stopMotor);
builder.addDoubleProperty(
"Front Left Motor Speed", m_frontLeftMotor::get, m_frontLeftMotor::set);
"Front Left Motor Speed", () -> m_frontLeftOutput, m_frontLeftMotor::accept);
builder.addDoubleProperty(
"Front Right Motor Speed", m_frontRightMotor::get, m_frontRightMotor::set);
builder.addDoubleProperty("Rear Left Motor Speed", m_rearLeftMotor::get, m_rearLeftMotor::set);
"Front Right Motor Speed", () -> m_frontRightOutput, m_frontRightMotor::accept);
builder.addDoubleProperty(
"Rear Right Motor Speed", m_rearRightMotor::get, m_rearRightMotor::set);
"Rear Left Motor Speed", () -> m_rearLeftOutput, m_rearLeftMotor::accept);
builder.addDoubleProperty(
"Rear Right Motor Speed", () -> m_rearRightOutput, m_rearRightMotor::accept);
}
}

View File

@@ -9,7 +9,14 @@ import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
import java.util.Arrays;
/** Allows multiple {@link MotorController} objects to be linked together. */
/**
* Allows multiple {@link MotorController} objects to be linked together.
*
* @deprecated Use CAN motor controller followers or {@link
* PWMMotorController#addFollower(PWMMotorController)}.
*/
@SuppressWarnings("removal")
@Deprecated(forRemoval = true, since = "2024")
public class MotorControllerGroup implements MotorController, Sendable, AutoCloseable {
private boolean m_isInverted;
private final MotorController[] m_motorControllers;

View File

@@ -14,6 +14,7 @@ import edu.wpi.first.wpilibj.MotorSafety;
import edu.wpi.first.wpilibj.PWM;
/** Nidec Brushless Motor. */
@SuppressWarnings("removal")
public class NidecBrushless extends MotorSafety
implements MotorController, Sendable, AutoCloseable {
private boolean m_isInverted;

View File

@@ -9,11 +9,14 @@ import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.MotorSafety;
import edu.wpi.first.wpilibj.PWM;
import java.util.ArrayList;
/** Common base class for all PWM Motor Controllers. */
@SuppressWarnings("removal")
public abstract class PWMMotorController extends MotorSafety
implements MotorController, Sendable, AutoCloseable {
private boolean m_isInverted;
private final ArrayList<PWMMotorController> m_followers = new ArrayList<>();
protected PWM m_pwm;
/**
@@ -46,7 +49,15 @@ public abstract class PWMMotorController extends MotorSafety
*/
@Override
public void set(double speed) {
m_pwm.setSpeed(m_isInverted ? -speed : speed);
if (m_isInverted) {
speed = -speed;
}
m_pwm.setSpeed(speed);
for (var follower : m_followers) {
follower.set(speed);
}
feed();
}
@@ -117,6 +128,15 @@ public abstract class PWMMotorController extends MotorSafety
m_pwm.enableDeadbandElimination(eliminateDeadband);
}
/**
* Make the given PWM motor controller follow the output of this one.
*
* @param follower The motor controller follower.
*/
public void addFollower(PWMMotorController follower) {
m_followers.add(follower);
}
@Override
public void initSendable(SendableBuilder builder) {
builder.setSmartDashboardType("Motor Controller");

View File

@@ -6,7 +6,7 @@ package edu.wpi.first.wpilibj.drive;
import static org.junit.jupiter.api.Assertions.assertEquals;
import edu.wpi.first.wpilibj.motorcontrol.MockMotorController;
import edu.wpi.first.wpilibj.motorcontrol.MockPWMMotorController;
import org.junit.jupiter.api.Test;
class DifferentialDriveTest {
@@ -250,9 +250,9 @@ class DifferentialDriveTest {
@Test
void testArcadeDrive() {
var left = new MockMotorController();
var right = new MockMotorController();
var drive = new DifferentialDrive(left, right);
var left = new MockPWMMotorController();
var right = new MockPWMMotorController();
var drive = new DifferentialDrive(left::set, right::set);
drive.setDeadband(0.0);
// Forward
@@ -288,9 +288,9 @@ class DifferentialDriveTest {
@Test
void testArcadeDriveSquared() {
var left = new MockMotorController();
var right = new MockMotorController();
var drive = new DifferentialDrive(left, right);
var left = new MockPWMMotorController();
var right = new MockPWMMotorController();
var drive = new DifferentialDrive(left::set, right::set);
drive.setDeadband(0.0);
// Forward
@@ -326,9 +326,9 @@ class DifferentialDriveTest {
@Test
void testCurvatureDrive() {
var left = new MockMotorController();
var right = new MockMotorController();
var drive = new DifferentialDrive(left, right);
var left = new MockPWMMotorController();
var right = new MockPWMMotorController();
var drive = new DifferentialDrive(left::set, right::set);
drive.setDeadband(0.0);
// Forward
@@ -364,9 +364,9 @@ class DifferentialDriveTest {
@Test
void testCurvatureDriveTurnInPlace() {
var left = new MockMotorController();
var right = new MockMotorController();
var drive = new DifferentialDrive(left, right);
var left = new MockPWMMotorController();
var right = new MockPWMMotorController();
var drive = new DifferentialDrive(left::set, right::set);
drive.setDeadband(0.0);
// Forward
@@ -402,9 +402,9 @@ class DifferentialDriveTest {
@Test
void testTankDrive() {
var left = new MockMotorController();
var right = new MockMotorController();
var drive = new DifferentialDrive(left, right);
var left = new MockPWMMotorController();
var right = new MockPWMMotorController();
var drive = new DifferentialDrive(left::set, right::set);
drive.setDeadband(0.0);
// Forward
@@ -440,9 +440,9 @@ class DifferentialDriveTest {
@Test
void testTankDriveSquared() {
var left = new MockMotorController();
var right = new MockMotorController();
var drive = new DifferentialDrive(left, right);
var left = new MockPWMMotorController();
var right = new MockPWMMotorController();
var drive = new DifferentialDrive(left::set, right::set);
drive.setDeadband(0.0);
// Forward

View File

@@ -7,7 +7,7 @@ package edu.wpi.first.wpilibj.drive;
import static org.junit.jupiter.api.Assertions.assertEquals;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.wpilibj.motorcontrol.MockMotorController;
import edu.wpi.first.wpilibj.motorcontrol.MockPWMMotorController;
import org.junit.jupiter.api.Test;
class MecanumDriveTest {
@@ -89,11 +89,11 @@ class MecanumDriveTest {
@Test
void testCartesian() {
var fl = new MockMotorController();
var fr = new MockMotorController();
var rl = new MockMotorController();
var rr = new MockMotorController();
var drive = new MecanumDrive(fl, rl, fr, rr);
var fl = new MockPWMMotorController();
var rl = new MockPWMMotorController();
var fr = new MockPWMMotorController();
var rr = new MockPWMMotorController();
var drive = new MecanumDrive(fl::set, rl::set, fr::set, rr::set);
drive.setDeadband(0.0);
// Forward
@@ -134,11 +134,11 @@ class MecanumDriveTest {
@Test
void testCartesianGyro90CW() {
var fl = new MockMotorController();
var fr = new MockMotorController();
var rl = new MockMotorController();
var rr = new MockMotorController();
var drive = new MecanumDrive(fl, rl, fr, rr);
var fl = new MockPWMMotorController();
var rl = new MockPWMMotorController();
var fr = new MockPWMMotorController();
var rr = new MockPWMMotorController();
var drive = new MecanumDrive(fl::set, rl::set, fr::set, rr::set);
drive.setDeadband(0.0);
// Forward in global frame; left in robot frame
@@ -179,11 +179,11 @@ class MecanumDriveTest {
@Test
void testPolar() {
var fl = new MockMotorController();
var fr = new MockMotorController();
var rl = new MockMotorController();
var rr = new MockMotorController();
var drive = new MecanumDrive(fl, rl, fr, rr);
var fl = new MockPWMMotorController();
var rl = new MockPWMMotorController();
var fr = new MockPWMMotorController();
var rr = new MockPWMMotorController();
var drive = new MecanumDrive(fl::set, rl::set, fr::set, rr::set);
drive.setDeadband(0.0);
// Forward

View File

@@ -4,6 +4,7 @@
package edu.wpi.first.wpilibj.motorcontrol;
@SuppressWarnings("removal")
public class MockMotorController implements MotorController {
private double m_speed;
private boolean m_isInverted;

View File

@@ -4,36 +4,30 @@
package edu.wpi.first.wpilibj.motorcontrol;
public class MockMotorController implements MotorController {
public class MockPWMMotorController {
private double m_speed;
private boolean m_isInverted;
@Override
public void set(double speed) {
m_speed = m_isInverted ? -speed : speed;
}
@Override
public double get() {
return m_speed;
}
@Override
public void setInverted(boolean isInverted) {
m_isInverted = isInverted;
}
@Override
public boolean getInverted() {
return m_isInverted;
}
@Override
public void disable() {
m_speed = 0;
}
@Override
public void stopMotor() {
disable();
}

View File

@@ -15,6 +15,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@SuppressWarnings("removal")
class MotorControllerGroupTest {
private static Stream<Arguments> motorControllerArguments() {
return IntStream.of(1, 2, 3)

View File

@@ -4,6 +4,7 @@
package edu.wpi.first.wpilibj.examples.arcadedrive;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
@@ -16,9 +17,15 @@ import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
public class Robot extends TimedRobot {
private final PWMSparkMax m_leftMotor = new PWMSparkMax(0);
private final PWMSparkMax m_rightMotor = new PWMSparkMax(1);
private final DifferentialDrive m_robotDrive = new DifferentialDrive(m_leftMotor, m_rightMotor);
private final DifferentialDrive m_robotDrive =
new DifferentialDrive(m_leftMotor::set, m_rightMotor::set);
private final Joystick m_stick = new Joystick(0);
public Robot() {
SendableRegistry.addChild(m_robotDrive, m_leftMotor);
SendableRegistry.addChild(m_robotDrive, m_rightMotor);
}
@Override
public void robotInit() {
// We need to invert one side of the drivetrain so that positive voltages

View File

@@ -4,6 +4,7 @@
package edu.wpi.first.wpilibj.examples.arcadedrivexboxcontroller;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.XboxController;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
@@ -16,9 +17,15 @@ import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
public class Robot extends TimedRobot {
private final PWMSparkMax m_leftMotor = new PWMSparkMax(0);
private final PWMSparkMax m_rightMotor = new PWMSparkMax(1);
private final DifferentialDrive m_robotDrive = new DifferentialDrive(m_leftMotor, m_rightMotor);
private final DifferentialDrive m_robotDrive =
new DifferentialDrive(m_leftMotor::set, m_rightMotor::set);
private final XboxController m_driverController = new XboxController(0);
public Robot() {
SendableRegistry.addChild(m_robotDrive, m_leftMotor);
SendableRegistry.addChild(m_robotDrive, m_rightMotor);
}
@Override
public void robotInit() {
// We need to invert one side of the drivetrain so that positive voltages

View File

@@ -4,28 +4,25 @@
package edu.wpi.first.wpilibj.examples.armbot.subsystems;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.examples.armbot.Constants.DriveConstants;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class DriveSubsystem extends SubsystemBase {
// The motors on the left side of the drive.
private final MotorControllerGroup m_leftMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kLeftMotor1Port),
new PWMSparkMax(DriveConstants.kLeftMotor2Port));
private final PWMSparkMax m_leftLeader = new PWMSparkMax(DriveConstants.kLeftMotor1Port);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(DriveConstants.kLeftMotor2Port);
// The motors on the right side of the drive.
private final MotorControllerGroup m_rightMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kRightMotor1Port),
new PWMSparkMax(DriveConstants.kRightMotor2Port));
private final PWMSparkMax m_rightLeader = new PWMSparkMax(DriveConstants.kRightMotor1Port);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(DriveConstants.kRightMotor2Port);
// The robot's drive
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftMotors, m_rightMotors);
private final DifferentialDrive m_drive =
new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);
// The left-side drive encoder
private final Encoder m_leftEncoder =
@@ -43,14 +40,20 @@ public class DriveSubsystem extends SubsystemBase {
/** Creates a new DriveSubsystem. */
public DriveSubsystem() {
SendableRegistry.addChild(m_drive, m_leftLeader);
SendableRegistry.addChild(m_drive, m_rightLeader);
// Sets the distance per pulse for the encoders
m_leftEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);
m_rightEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightMotors.setInverted(true);
m_rightLeader.setInverted(true);
}
/**

View File

@@ -4,14 +4,12 @@
package edu.wpi.first.wpilibj.examples.armbotoffboard;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
/**
* A simplified stub class that simulates the API of a common "smart" motor controller.
*
* <p>Has no actual functionality.
*/
public class ExampleSmartMotorController implements MotorController {
public class ExampleSmartMotorController {
public enum PIDMode {
kPosition,
kVelocity,
@@ -72,25 +70,19 @@ public class ExampleSmartMotorController implements MotorController {
/** Resets the encoder to zero distance. */
public void resetEncoder() {}
@Override
public void set(double speed) {}
@Override
public double get() {
return 0;
}
@Override
public void setInverted(boolean isInverted) {}
@Override
public boolean getInverted() {
return false;
}
@Override
public void disable() {}
@Override
public void stopMotor() {}
}

View File

@@ -4,10 +4,10 @@
package edu.wpi.first.wpilibj.examples.armbotoffboard.subsystems;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.examples.armbotoffboard.Constants.DriveConstants;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.Commands;
@@ -16,19 +16,16 @@ import java.util.function.DoubleSupplier;
public class DriveSubsystem extends SubsystemBase {
// The motors on the left side of the drive.
private final MotorControllerGroup m_leftMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kLeftMotor1Port),
new PWMSparkMax(DriveConstants.kLeftMotor2Port));
private final PWMSparkMax m_leftLeader = new PWMSparkMax(DriveConstants.kLeftMotor1Port);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(DriveConstants.kLeftMotor2Port);
// The motors on the right side of the drive.
private final MotorControllerGroup m_rightMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kRightMotor1Port),
new PWMSparkMax(DriveConstants.kRightMotor2Port));
private final PWMSparkMax m_rightLeader = new PWMSparkMax(DriveConstants.kRightMotor1Port);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(DriveConstants.kRightMotor2Port);
// The robot's drive
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftMotors, m_rightMotors);
private final DifferentialDrive m_drive =
new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);
// The left-side drive encoder
private final Encoder m_leftEncoder =
@@ -46,14 +43,20 @@ public class DriveSubsystem extends SubsystemBase {
/** Creates a new DriveSubsystem. */
public DriveSubsystem() {
SendableRegistry.addChild(m_drive, m_leftLeader);
SendableRegistry.addChild(m_drive, m_rightLeader);
// Sets the distance per pulse for the encoders
m_leftEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);
m_rightEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightMotors.setInverted(true);
m_rightLeader.setInverted(true);
}
/**

View File

@@ -12,8 +12,6 @@ import edu.wpi.first.math.kinematics.DifferentialDriveOdometry;
import edu.wpi.first.math.kinematics.DifferentialDriveWheelSpeeds;
import edu.wpi.first.wpilibj.AnalogGyro;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
/** Represents a differential drive style drivetrain. */
@@ -25,19 +23,14 @@ public class Drivetrain {
private static final double kWheelRadius = 0.0508; // meters
private static final int kEncoderResolution = 4096;
private final MotorController m_leftLeader = new PWMSparkMax(1);
private final MotorController m_leftFollower = new PWMSparkMax(2);
private final MotorController m_rightLeader = new PWMSparkMax(3);
private final MotorController m_rightFollower = new PWMSparkMax(4);
private final PWMSparkMax m_leftLeader = new PWMSparkMax(1);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(2);
private final PWMSparkMax m_rightLeader = new PWMSparkMax(3);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(4);
private final Encoder m_leftEncoder = new Encoder(0, 1);
private final Encoder m_rightEncoder = new Encoder(2, 3);
private final MotorControllerGroup m_leftGroup =
new MotorControllerGroup(m_leftLeader, m_leftFollower);
private final MotorControllerGroup m_rightGroup =
new MotorControllerGroup(m_rightLeader, m_rightFollower);
private final AnalogGyro m_gyro = new AnalogGyro(0);
private final PIDController m_leftPIDController = new PIDController(1, 0, 0);
@@ -58,10 +51,13 @@ public class Drivetrain {
public Drivetrain() {
m_gyro.reset();
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightGroup.setInverted(true);
m_rightLeader.setInverted(true);
// Set the distance per pulse for the drive encoders. We can simply use the
// distance traveled for one rotation of the wheel divided by the encoder
@@ -90,8 +86,8 @@ public class Drivetrain {
m_leftPIDController.calculate(m_leftEncoder.getRate(), speeds.leftMetersPerSecond);
final double rightOutput =
m_rightPIDController.calculate(m_rightEncoder.getRate(), speeds.rightMetersPerSecond);
m_leftGroup.setVoltage(leftOutput + leftFeedforward);
m_rightGroup.setVoltage(rightOutput + rightFeedforward);
m_leftLeader.setVoltage(leftOutput + leftFeedforward);
m_rightLeader.setVoltage(rightOutput + rightFeedforward);
}
/**

View File

@@ -30,8 +30,6 @@ import edu.wpi.first.wpilibj.AnalogGyro;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.RobotController;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj.simulation.AnalogGyroSim;
import edu.wpi.first.wpilibj.simulation.DifferentialDrivetrainSim;
@@ -48,19 +46,14 @@ public class Drivetrain {
private static final double kWheelRadius = 0.0508; // meters
private static final int kEncoderResolution = 4096;
private final MotorController m_leftLeader = new PWMSparkMax(1);
private final MotorController m_leftFollower = new PWMSparkMax(2);
private final MotorController m_rightLeader = new PWMSparkMax(3);
private final MotorController m_rightFollower = new PWMSparkMax(4);
private final PWMSparkMax m_leftLeader = new PWMSparkMax(1);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(2);
private final PWMSparkMax m_rightLeader = new PWMSparkMax(3);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(4);
private final Encoder m_leftEncoder = new Encoder(0, 1);
private final Encoder m_rightEncoder = new Encoder(2, 3);
private final MotorControllerGroup m_leftGroup =
new MotorControllerGroup(m_leftLeader, m_leftFollower);
private final MotorControllerGroup m_rightGroup =
new MotorControllerGroup(m_rightLeader, m_rightFollower);
private final AnalogGyro m_gyro = new AnalogGyro(0);
private final PIDController m_leftPIDController = new PIDController(1, 0, 0);
@@ -113,10 +106,13 @@ public class Drivetrain {
public Drivetrain(DoubleArrayTopic cameraToObjectTopic) {
m_gyro.reset();
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightGroup.setInverted(true);
m_rightLeader.setInverted(true);
// Set the distance per pulse for the drive encoders. We can simply use the
// distance traveled for one rotation of the wheel divided by the encoder
@@ -148,8 +144,8 @@ public class Drivetrain {
m_leftPIDController.calculate(m_leftEncoder.getRate(), speeds.leftMetersPerSecond);
final double rightOutput =
m_rightPIDController.calculate(m_rightEncoder.getRate(), speeds.rightMetersPerSecond);
m_leftGroup.setVoltage(leftOutput + leftFeedforward);
m_rightGroup.setVoltage(rightOutput + rightFeedforward);
m_leftLeader.setVoltage(leftOutput + leftFeedforward);
m_rightLeader.setVoltage(rightOutput + rightFeedforward);
}
/**
@@ -251,8 +247,8 @@ public class Drivetrain {
// simulation, and write the simulated positions and velocities to our
// simulated encoder and gyro.
m_drivetrainSimulator.setInputs(
m_leftGroup.get() * RobotController.getInputVoltage(),
m_rightGroup.get() * RobotController.getInputVoltage());
m_leftLeader.get() * RobotController.getInputVoltage(),
m_rightLeader.get() * RobotController.getInputVoltage());
m_drivetrainSimulator.update(0.02);
m_leftEncoderSim.setDistance(m_drivetrainSimulator.getLeftPositionMeters());

View File

@@ -4,14 +4,12 @@
package edu.wpi.first.wpilibj.examples.drivedistanceoffboard;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
/**
* A simplified stub class that simulates the API of a common "smart" motor controller.
*
* <p>Has no actual functionality.
*/
public class ExampleSmartMotorController implements MotorController {
public class ExampleSmartMotorController {
public enum PIDMode {
kPosition,
kVelocity,
@@ -74,27 +72,21 @@ public class ExampleSmartMotorController implements MotorController {
/** Resets the encoder to zero distance. */
public void resetEncoder() {}
@Override
public void set(double speed) {
m_value = speed;
}
@Override
public double get() {
return m_value;
}
@Override
public void setInverted(boolean isInverted) {}
@Override
public boolean getInverted() {
return false;
}
@Override
public void disable() {}
@Override
public void stopMotor() {}
}

View File

@@ -6,6 +6,7 @@ package edu.wpi.first.wpilibj.examples.drivedistanceoffboard.subsystems;
import edu.wpi.first.math.controller.SimpleMotorFeedforward;
import edu.wpi.first.math.trajectory.TrapezoidProfile;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.examples.drivedistanceoffboard.Constants.DriveConstants;
import edu.wpi.first.wpilibj.examples.drivedistanceoffboard.ExampleSmartMotorController;
@@ -34,20 +35,19 @@ public class DriveSubsystem extends SubsystemBase {
DriveConstants.kaVoltSecondsSquaredPerMeter);
// The robot's drive
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftLeader, m_rightLeader);
private final DifferentialDrive m_drive =
new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);
/** Creates a new DriveSubsystem. */
public DriveSubsystem() {
SendableRegistry.addChild(m_drive, m_leftLeader);
SendableRegistry.addChild(m_drive, m_rightLeader);
// 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.
m_rightLeader.setInverted(true);
// You might need to not do this depending on the specific motor controller
// that you are using -- contact the respective vendor's documentation for
// more details.
m_rightFollower.setInverted(true);
m_leftFollower.follow(m_leftLeader);
m_rightFollower.follow(m_rightLeader);

View File

@@ -4,14 +4,12 @@
package edu.wpi.first.wpilibj.examples.elevatorexponentialprofile;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
/**
* A simplified stub class that simulates the API of a common "smart" motor controller.
*
* <p>Has no actual functionality.
*/
public class ExampleSmartMotorController implements MotorController {
public class ExampleSmartMotorController {
public enum PIDMode {
kPosition,
kVelocity,
@@ -72,25 +70,19 @@ public class ExampleSmartMotorController implements MotorController {
/** Resets the encoder to zero distance. */
public void resetEncoder() {}
@Override
public void set(double speed) {}
@Override
public double get() {
return 0;
}
@Override
public void setInverted(boolean isInverted) {}
@Override
public boolean getInverted() {
return false;
}
@Override
public void disable() {}
@Override
public void stopMotor() {}
}

View File

@@ -10,7 +10,6 @@ import edu.wpi.first.math.trajectory.TrapezoidProfile;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
@SuppressWarnings("PMD.RedundantFieldInitializer")
@@ -27,7 +26,7 @@ public class Robot extends TimedRobot {
private final Joystick m_joystick = new Joystick(1);
private final Encoder m_encoder = new Encoder(1, 2);
private final MotorController m_motor = new PWMSparkMax(1);
private final PWMSparkMax m_motor = new PWMSparkMax(1);
// Create a PID controller whose setpoint's change is subject to maximum
// velocity and acceleration constraints.

View File

@@ -4,14 +4,12 @@
package edu.wpi.first.wpilibj.examples.elevatortrapezoidprofile;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
/**
* A simplified stub class that simulates the API of a common "smart" motor controller.
*
* <p>Has no actual functionality.
*/
public class ExampleSmartMotorController implements MotorController {
public class ExampleSmartMotorController {
public enum PIDMode {
kPosition,
kVelocity,
@@ -72,25 +70,19 @@ public class ExampleSmartMotorController implements MotorController {
/** Resets the encoder to zero distance. */
public void resetEncoder() {}
@Override
public void set(double speed) {}
@Override
public double get() {
return 0;
}
@Override
public void setInverted(boolean isInverted) {}
@Override
public boolean getInverted() {
return false;
}
@Override
public void disable() {}
@Override
public void stopMotor() {}
}

View File

@@ -12,7 +12,6 @@ import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.Ultrasonic;
import edu.wpi.first.wpilibj.event.BooleanEvent;
import edu.wpi.first.wpilibj.event.EventLoop;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
public class Robot extends TimedRobot {
@@ -20,15 +19,15 @@ public class Robot extends TimedRobot {
public static final int TOLERANCE = 8; // rpm
public static final int KICKER_THRESHOLD = 15; // mm
private final MotorController m_shooter = new PWMSparkMax(0);
private final PWMSparkMax m_shooter = new PWMSparkMax(0);
private final Encoder m_shooterEncoder = new Encoder(0, 1);
private final PIDController m_controller = new PIDController(0.3, 0, 0);
private final SimpleMotorFeedforward m_ff = new SimpleMotorFeedforward(0.1, 0.065);
private final MotorController m_kicker = new PWMSparkMax(1);
private final PWMSparkMax m_kicker = new PWMSparkMax(1);
private final Ultrasonic m_kickerSensor = new Ultrasonic(2, 3);
private final MotorController m_intake = new PWMSparkMax(2);
private final PWMSparkMax m_intake = new PWMSparkMax(2);
private final EventLoop m_loop = new EventLoop();
private final Joystick m_joystick = new Joystick(0);

View File

@@ -4,28 +4,25 @@
package edu.wpi.first.wpilibj.examples.frisbeebot.subsystems;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.examples.frisbeebot.Constants.DriveConstants;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class DriveSubsystem extends SubsystemBase {
// The motors on the left side of the drive.
private final MotorControllerGroup m_leftMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kLeftMotor1Port),
new PWMSparkMax(DriveConstants.kLeftMotor2Port));
private final PWMSparkMax m_leftLeader = new PWMSparkMax(DriveConstants.kLeftMotor1Port);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(DriveConstants.kLeftMotor2Port);
// The motors on the right side of the drive.
private final MotorControllerGroup m_rightMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kRightMotor1Port),
new PWMSparkMax(DriveConstants.kRightMotor2Port));
private final PWMSparkMax m_rightLeader = new PWMSparkMax(DriveConstants.kRightMotor1Port);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(DriveConstants.kRightMotor2Port);
// The robot's drive
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftMotors, m_rightMotors);
private final DifferentialDrive m_drive =
new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);
// The left-side drive encoder
private final Encoder m_leftEncoder =
@@ -43,10 +40,16 @@ public class DriveSubsystem extends SubsystemBase {
/** Creates a new DriveSubsystem. */
public DriveSubsystem() {
SendableRegistry.addChild(m_drive, m_leftLeader);
SendableRegistry.addChild(m_drive, m_rightLeader);
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightMotors.setInverted(true);
m_rightLeader.setInverted(true);
// Sets the distance per pulse for the encoders
m_leftEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);

View File

@@ -4,34 +4,27 @@
package edu.wpi.first.wpilibj.examples.gearsbot.subsystems;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.AnalogGyro;
import edu.wpi.first.wpilibj.AnalogInput;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.examples.gearsbot.Constants.DriveConstants;
import edu.wpi.first.wpilibj.examples.gearsbot.Robot;
import edu.wpi.first.wpilibj.motorcontrol.MotorController;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class Drivetrain extends SubsystemBase {
/**
* The Drivetrain subsystem incorporates the sensors and actuators attached to the robots chassis.
* These include four drive motors, a left and right encoder and a gyro.
*/
private final MotorController m_leftMotor =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kLeftMotorPort1),
new PWMSparkMax(DriveConstants.kLeftMotorPort1));
// The Drivetrain subsystem incorporates the sensors and actuators attached to the robots chassis.
// These include four drive motors, a left and right encoder and a gyro.
private final PWMSparkMax m_leftLeader = new PWMSparkMax(DriveConstants.kLeftMotorPort1);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(DriveConstants.kLeftMotorPort2);
private final PWMSparkMax m_rightLeader = new PWMSparkMax(DriveConstants.kRightMotorPort1);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(DriveConstants.kRightMotorPort2);
private final MotorController m_rightMotor =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kRightMotorPort2),
new PWMSparkMax(DriveConstants.kLeftMotorPort2));
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftMotor, m_rightMotor);
private final DifferentialDrive m_drive =
new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);
private final Encoder m_leftEncoder =
new Encoder(
@@ -50,10 +43,16 @@ public class Drivetrain extends SubsystemBase {
public Drivetrain() {
super();
SendableRegistry.addChild(m_drive, m_leftLeader);
SendableRegistry.addChild(m_drive, m_rightLeader);
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightMotor.setInverted(true);
m_rightLeader.setInverted(true);
// Encoders may measure differently in the real world and in
// simulation. In this example the robot moves 0.042 barleycorns

View File

@@ -4,6 +4,7 @@
package edu.wpi.first.wpilibj.examples.gettingstarted;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.XboxController;
@@ -19,10 +20,16 @@ import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
public class Robot extends TimedRobot {
private final PWMSparkMax m_leftDrive = new PWMSparkMax(0);
private final PWMSparkMax m_rightDrive = new PWMSparkMax(1);
private final DifferentialDrive m_robotDrive = new DifferentialDrive(m_leftDrive, m_rightDrive);
private final DifferentialDrive m_robotDrive =
new DifferentialDrive(m_leftDrive::set, m_rightDrive::set);
private final XboxController m_controller = new XboxController(0);
private final Timer m_timer = new Timer();
public Robot() {
SendableRegistry.addChild(m_robotDrive, m_leftDrive);
SendableRegistry.addChild(m_robotDrive, m_rightDrive);
}
/**
* This function is run when the robot is first started up and should be used for any
* initialization code.

View File

@@ -4,6 +4,7 @@
package edu.wpi.first.wpilibj.examples.gyro;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.AnalogGyro;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.TimedRobot;
@@ -30,10 +31,16 @@ public class Robot extends TimedRobot {
private final PWMSparkMax m_leftDrive = new PWMSparkMax(kLeftMotorPort);
private final PWMSparkMax m_rightDrive = new PWMSparkMax(kRightMotorPort);
private final DifferentialDrive m_myRobot = new DifferentialDrive(m_leftDrive, m_rightDrive);
private final DifferentialDrive m_robotDrive =
new DifferentialDrive(m_leftDrive::set, m_rightDrive::set);
private final AnalogGyro m_gyro = new AnalogGyro(kGyroPort);
private final Joystick m_joystick = new Joystick(kJoystickPort);
public Robot() {
SendableRegistry.addChild(m_robotDrive, m_leftDrive);
SendableRegistry.addChild(m_robotDrive, m_rightDrive);
}
@Override
public void robotInit() {
m_gyro.setSensitivity(kVoltsPerDegreePerSecond);
@@ -50,6 +57,6 @@ public class Robot extends TimedRobot {
@Override
public void teleopPeriodic() {
double turningValue = (kAngleSetpoint - m_gyro.getAngle()) * kP;
m_myRobot.arcadeDrive(-m_joystick.getY(), -turningValue);
m_robotDrive.arcadeDrive(-m_joystick.getY(), -turningValue);
}
}

View File

@@ -4,29 +4,26 @@
package edu.wpi.first.wpilibj.examples.gyrodrivecommands.subsystems;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.ADXRS450_Gyro;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.examples.gyrodrivecommands.Constants.DriveConstants;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class DriveSubsystem extends SubsystemBase {
// The motors on the left side of the drive.
private final MotorControllerGroup m_leftMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kLeftMotor1Port),
new PWMSparkMax(DriveConstants.kLeftMotor2Port));
private final PWMSparkMax m_leftLeader = new PWMSparkMax(DriveConstants.kLeftMotor1Port);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(DriveConstants.kLeftMotor2Port);
// The motors on the right side of the drive.
private final MotorControllerGroup m_rightMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kRightMotor1Port),
new PWMSparkMax(DriveConstants.kRightMotor2Port));
private final PWMSparkMax m_rightLeader = new PWMSparkMax(DriveConstants.kRightMotor1Port);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(DriveConstants.kRightMotor2Port);
// The robot's drive
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftMotors, m_rightMotors);
private final DifferentialDrive m_drive =
new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);
// The left-side drive encoder
private final Encoder m_leftEncoder =
@@ -47,10 +44,16 @@ public class DriveSubsystem extends SubsystemBase {
/** Creates a new DriveSubsystem. */
public DriveSubsystem() {
SendableRegistry.addChild(m_drive, m_leftLeader);
SendableRegistry.addChild(m_drive, m_rightLeader);
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightMotors.setInverted(true);
m_rightLeader.setInverted(true);
// Sets the distance per pulse for the encoders
m_leftEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);

View File

@@ -4,6 +4,7 @@
package edu.wpi.first.wpilibj.examples.gyromecanum;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.AnalogGyro;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.TimedRobot;
@@ -37,12 +38,17 @@ public class Robot extends TimedRobot {
PWMSparkMax frontRight = new PWMSparkMax(kFrontRightChannel);
PWMSparkMax rearRight = new PWMSparkMax(kRearRightChannel);
SendableRegistry.addChild(m_robotDrive, frontLeft);
SendableRegistry.addChild(m_robotDrive, rearLeft);
SendableRegistry.addChild(m_robotDrive, frontRight);
SendableRegistry.addChild(m_robotDrive, rearRight);
// Invert the right side motors.
// You may need to change or remove this to match your robot.
frontRight.setInverted(true);
rearRight.setInverted(true);
m_robotDrive = new MecanumDrive(frontLeft, rearLeft, frontRight, rearRight);
m_robotDrive = new MecanumDrive(frontLeft::set, rearLeft::set, frontRight::set, rearRight::set);
m_gyro.setSensitivity(kVoltsPerDegreePerSecond);
}

View File

@@ -5,28 +5,25 @@
package edu.wpi.first.wpilibj.examples.hatchbotinlined.subsystems;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.examples.hatchbotinlined.Constants.DriveConstants;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class DriveSubsystem extends SubsystemBase {
// The motors on the left side of the drive.
private final MotorControllerGroup m_leftMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kLeftMotor1Port),
new PWMSparkMax(DriveConstants.kLeftMotor2Port));
private final PWMSparkMax m_leftLeader = new PWMSparkMax(DriveConstants.kLeftMotor1Port);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(DriveConstants.kLeftMotor2Port);
// The motors on the right side of the drive.
private final MotorControllerGroup m_rightMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kRightMotor1Port),
new PWMSparkMax(DriveConstants.kRightMotor2Port));
private final PWMSparkMax m_rightLeader = new PWMSparkMax(DriveConstants.kRightMotor1Port);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(DriveConstants.kRightMotor2Port);
// The robot's drive
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftMotors, m_rightMotors);
private final DifferentialDrive m_drive =
new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);
// The left-side drive encoder
private final Encoder m_leftEncoder =
@@ -44,10 +41,16 @@ public class DriveSubsystem extends SubsystemBase {
/** Creates a new DriveSubsystem. */
public DriveSubsystem() {
SendableRegistry.addChild(m_drive, m_leftLeader);
SendableRegistry.addChild(m_drive, m_rightLeader);
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightMotors.setInverted(true);
m_rightLeader.setInverted(true);
// Sets the distance per pulse for the encoders
m_leftEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);

View File

@@ -5,28 +5,25 @@
package edu.wpi.first.wpilibj.examples.hatchbottraditional.subsystems;
import edu.wpi.first.util.sendable.SendableBuilder;
import edu.wpi.first.util.sendable.SendableRegistry;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj.examples.hatchbottraditional.Constants.DriveConstants;
import edu.wpi.first.wpilibj.motorcontrol.MotorControllerGroup;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
public class DriveSubsystem extends SubsystemBase {
// The motors on the left side of the drive.
private final MotorControllerGroup m_leftMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kLeftMotor1Port),
new PWMSparkMax(DriveConstants.kLeftMotor2Port));
private final PWMSparkMax m_leftLeader = new PWMSparkMax(DriveConstants.kLeftMotor1Port);
private final PWMSparkMax m_leftFollower = new PWMSparkMax(DriveConstants.kLeftMotor2Port);
// The motors on the right side of the drive.
private final MotorControllerGroup m_rightMotors =
new MotorControllerGroup(
new PWMSparkMax(DriveConstants.kRightMotor1Port),
new PWMSparkMax(DriveConstants.kRightMotor2Port));
private final PWMSparkMax m_rightLeader = new PWMSparkMax(DriveConstants.kRightMotor1Port);
private final PWMSparkMax m_rightFollower = new PWMSparkMax(DriveConstants.kRightMotor2Port);
// The robot's drive
private final DifferentialDrive m_drive = new DifferentialDrive(m_leftMotors, m_rightMotors);
private final DifferentialDrive m_drive =
new DifferentialDrive(m_leftLeader::set, m_rightLeader::set);
// The left-side drive encoder
private final Encoder m_leftEncoder =
@@ -44,10 +41,16 @@ public class DriveSubsystem extends SubsystemBase {
/** Creates a new DriveSubsystem. */
public DriveSubsystem() {
SendableRegistry.addChild(m_drive, m_leftLeader);
SendableRegistry.addChild(m_drive, m_rightLeader);
m_leftLeader.addFollower(m_leftFollower);
m_rightLeader.addFollower(m_rightFollower);
// 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.
m_rightMotors.setInverted(true);
m_rightLeader.setInverted(true);
// Sets the distance per pulse for the encoders
m_leftEncoder.setDistancePerPulse(DriveConstants.kEncoderDistancePerPulse);

Some files were not shown because too many files have changed in this diff Show More