mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[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:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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() {}
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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); }};
|
||||
};
|
||||
|
||||
@@ -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() {}
|
||||
};
|
||||
|
||||
@@ -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() {}
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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};
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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};
|
||||
};
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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() {}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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() {}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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() {}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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() {}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user