Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/swerve drive support #25

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
e2e4ac8
add swerve drive motors to actuator interface
danielbrownmsm Dec 24, 2022
4d65374
add swerve drive absolute steering encoders to sensor interface
danielbrownmsm Dec 24, 2022
e8767c6
create swerve drive hardware interface per #11
danielbrownmsm Dec 24, 2022
b5f4cb8
created swerve drive IO per #11
danielbrownmsm Dec 24, 2022
8cc8137
fixes bug with drive config from last commit
danielbrownmsm Dec 24, 2022
3244231
adds swerve drive parameters to the parameters.toml file per #11
danielbrownmsm Dec 27, 2022
60a2d43
add swerve drive to RobotContainer per #11
danielbrownmsm Dec 27, 2022
3b0fe4f
add swerve drive to RobotContainer header per #11
danielbrownmsm Dec 27, 2022
e8fe72e
created SwerveModule classes, need to be fleshed out
danielbrownmsm Dec 31, 2022
696c850
finised adding WPILib swerve support to SwerveDrive subsystem
danielbrownmsm Dec 31, 2022
a5846dd
fixes swerve drive initialization in RobotContainer
danielbrownmsm Dec 31, 2022
b1e56d1
fixes swerve drive subsystem constructor
danielbrownmsm Dec 31, 2022
688361a
instantiates swerve drive kinematics and swerve drive odometry
danielbrownmsm Dec 31, 2022
24e7e39
Merge branch 'master' into feat/swerve-drive-support
danielbrownmsm Dec 31, 2022
32f9628
remove ServeModule class as it was never written and it turns out we …
danielbrownmsm Dec 31, 2022
9cc17d2
Merge branch 'feat/swerve-drive-support' of https://github.com/Team-O…
danielbrownmsm Dec 31, 2022
f43a456
added swerve drive PID constants
danielbrownmsm Jan 2, 2023
ded7317
fixed SwerveDrive.h default constructors, added PID controllers
danielbrownmsm Jan 2, 2023
076b762
created actual swerve I/O motor outputs
danielbrownmsm Jan 2, 2023
a0aad18
added drive and steer PID controllers, fleshed out TeleOpDrive method
danielbrownmsm Jan 2, 2023
9db4fa1
created swerve module class
danielbrownmsm Jan 3, 2023
06b330d
fix swerve module not actually having a way to set its physical location
danielbrownmsm Jan 3, 2023
5b66c7b
added velocity readings to swerve software interface
danielbrownmsm Jan 3, 2023
20f607e
fix destructor
danielbrownmsm Jan 3, 2023
219fa28
set outputs in sw_interface
danielbrownmsm Jan 3, 2023
1ee7e1e
added absolute encoders to hardware interface
danielbrownmsm Jan 4, 2023
a120dd9
created teleop and auto commands for the swerve drive
danielbrownmsm Jan 4, 2023
2a95107
add steering absolute encoders to swerve drive i/o. ticket: #11
danielbrownmsm Jan 4, 2023
b6f1e0b
fix swerve module constructor
danielbrownmsm Jan 4, 2023
2088ee6
added swerve drive shuffleboard values to the UI class
danielbrownmsm Jan 4, 2023
f98b32b
make AutoSwerveCommand use Pose2d instead of a Translation2d and a Ro…
danielbrownmsm Jan 6, 2023
5982eec
add SetPID methods to SwerveModule
danielbrownmsm Jan 6, 2023
7e782da
add a bunch of auto methods and variables and an enum to SwerveDrive …
danielbrownmsm Jan 6, 2023
71159af
remove tele-op input cubing, add strafe_power and fix it
danielbrownmsm Jan 6, 2023
e2b7042
add shuffleboard, SwerveModule class usage, and a bunch of auton suff…
danielbrownmsm Jan 6, 2023
8b61304
made code build
danielbrownmsm Jan 6, 2023
02cab8d
imported into beta-7
danielbrownmsm Jan 6, 2023
5675e2d
Merge remote-tracking branch 'FRC-2022-CPP/master' into feat/swerve-d…
danielbrownmsm Jan 6, 2023
0f84f34
fix shuffleboard changing to pointers because WPILib
danielbrownmsm Jan 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/main/cpp/RobotContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,21 @@ RobotContainer::RobotContainer() {
drivetrain_ = std::make_shared<Drivetrain>(drivetrain_sw_.get());
VOKC_CALL(drivetrain_->Init());


// == swerve drive ==
std::shared_ptr<SwerveDriveHardwareInterface> swerve_drive_hw;
VOKC_CALL(SetupSwerveDriveInterface(hardware_, &swerve_drive_hw));

// Initialize the software interface
swerve_drive_sw_ = std::make_shared<SwerveDriveSoftwareInterface>();

// Link SwerveDriveIO to hardware / software
swerve_drive_io_ = std::make_shared<SwerveDriveIO>(swerve_drive_hw.get(), swerve_drive_sw_.get());

// Link intake software to the I/O
swerve_drive_ = std::make_shared<SwerveDrive>(swerve_drive_sw_.get());


// == intake ==
std::shared_ptr<IntakeHardwareInterface> intake_hw;
VOKC_CALL(SetupIntakeInterface(hardware_, &intake_hw));
Expand Down
167 changes: 167 additions & 0 deletions src/main/cpp/SwerveModule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@

#include "SwerveModule.h"

bool SwerveModule::Init(Location loc) {
// PID Controller stuff
// drive PID gains
double drive_kP = RobotParams::GetParam("swerve.drive_pid.kP", 0.0);
double drive_kI = RobotParams::GetParam("swerve.drive_pid.kI", 0.001);
double drive_kD = RobotParams::GetParam("swerve.drive_pid.kD", 0.0001);

// steer PID gains
double steer_kP = RobotParams::GetParam("swerve.steer_pid.kP", 0.0);
double steer_kI = RobotParams::GetParam("swerve.steer_pid.kI", 0.001);
double steer_kD = RobotParams::GetParam("swerve.steer_pid.kD", 0.0001);

// create our PIDs
drive_pid = frc::PIDController(drive_kP, drive_kI, drive_kD);
steer_pid = frc::PIDController(steer_kP, steer_kI, steer_kD);


// create a default swerve module state with no speed or angle
state = frc::SwerveModuleState(units::meters_per_second_t(0.0), frc::Rotation2d());

// create a default swerve module position with no distance traveled or angle
pos = frc::SwerveModulePosition(units::meter_t(0.0), frc::Rotation2d());

this->location = loc;

// physical location on the robot
double x_disp = RobotParams::GetParam("swerve.x_disp", 0.3); // in meters
double y_disp = RobotParams::GetParam("swerve.y_disp", 0.3); // in meters

// based on where it needs to be
switch(loc) {
case Location::LEFT_FRONT:
// we only have this to pass it into the kinematics object, because WPILib needs it
// positive x is to the front of the robot, positive y is to the left of the robot
// this should match the code in the docs pretty well, I think
trans = frc::Translation2d(units::meter_t(x_disp), units::meter_t(y_disp));
break;
case Location::LEFT_BACK:
trans = frc::Translation2d(units::meter_t(-x_disp), units::meter_t(y_disp));
break;
case Location::RIGHT_FRONT:
trans = frc::Translation2d(frc::Translation2d(units::meter_t(x_disp), units::meter_t(-y_disp)));
break;
case Location::RIGHT_BACK:
trans = frc::Translation2d(frc::Translation2d(units::meter_t(-x_disp), units::meter_t(-y_disp)));
break;
default:
// we shouldn't have reached here, so throw an error
return false;
}

// reset subsystem to initial state
this->Reset();

// Init passed succesffully, return true
return true;
}

bool SwerveModule::Reset() {
// reset PIDs
this->drive_pid.Reset();
this->steer_pid.Reset();

//TODO reset sensor readings
//TODO reset WPILib kinematics stuff
return true;
}

bool SwerveModule::GetLocationOnRobot(frc::Translation2d *trans) {
// OKC_CHECK(this->trans != nullptr);

*trans = this->trans;

return true;
}

bool SwerveModule::GetSwerveModulePosition(frc::SwerveModulePosition *pos) {
// OKC_CHECK(this->pos != nullptr);

*pos = this->pos;

return true;
}

bool SwerveModule::GetSwerveModuleState(frc::SwerveModuleState *state) {
// OKC_CHECK(this->state != nullptr);

*state = this->state;

return true;
}

bool SwerveModule::SetDesiredState(frc::SwerveModuleState state) {
// OKC_CHECK(this->state != nullptr);

this->state = state;

return true;
}

bool SwerveModule::GetDriveOutput(double *output) {
//TODO check for null pointers

// set setpoint
this->drive_pid.SetSetpoint(this->state.speed.value());

// calculate output
*output = this->drive_pid.Calculate(this->drive_enc_vel);

return true;
}

bool SwerveModule::GetSteerOutput(double *output) {
// TODO check for null pointers

// optimize angle
this->state = frc::SwerveModuleState::Optimize(this->state, frc::Rotation2d(units::degree_t(this->pos.angle.Degrees())));

// set setpoint
this->steer_pid.SetSetpoint(this->state.angle.Degrees().value());

*output = this->steer_pid.Calculate(this->steer_enc_vel);

return true;
}

bool SwerveModule::SetDrivePID(double kP, double kI, double kD) {
//TODO null pointer checks
//OKC_CHECK(this->drive_pid != nullptr);

this->drive_pid.SetPID(kP, kI, kD);

return true;
}

bool SwerveModule::SetSteerPID(double kP, double kI, double kD) {
//TODO null pointer checks
//OKC_CHECK(this->steer_pid != nullptr);

this->steer_pid.SetPID(kP, kI, kD);

return true;
}


bool SwerveModule::Update(double drive_enc, double steer_enc, double drive_vel, double steer_vel) {
// update the SwerveModulePosition with the given sensor readings

// 6.75:1 L2 gear ratio
// wheel is 4 inch diamete wheel
drive_enc = drive_enc / 6.75 * 3.14159265358979323846264338327950288419716939937510582097494459230781 * 4;

// steering gear ratio of 12.8:1
//TODO fix steer encoder readings (like, converting from raw voltage value or whatever to this)
steer_enc = steer_enc / 12.8;

this->pos = frc::SwerveModulePosition(units::meter_t(drive_enc), frc::Rotation2d(units::degree_t(steer_enc)));

// velocity readings
this->drive_enc_vel = drive_vel;
this->steer_enc_vel = steer_vel;

return true;
}
46 changes: 46 additions & 0 deletions src/main/cpp/commands/swerve/AutoSwerveCommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@

#include "commands/swerve/AutoSwerveCommand.h"

AutoSwerveCommand::AutoSwerveCommand(std::shared_ptr<SwerveDrive> swerve, frc::Pose2d f_pos) {
swerve_ = swerve;
end_pos = f_pos;

if (swerve_ != nullptr) {
this->AddRequirements(swerve_.get());
}
}

void AutoSwerveCommand::Initialize() {
VOKC_CHECK(swerve_ != nullptr);

VOKC_CALL(swerve_->ResetDriveEncoders());
VOKC_CALL(swerve_->ResetSteerEncoders());
VOKC_CALL(swerve_->ResetPIDs());
}

void AutoSwerveCommand::Execute() {
VOKC_CHECK(swerve_ != nullptr);

VOKC_CALL(swerve_->TranslateAuto(end_pos));
}

void AutoSwerveCommand::End(bool executed) {
return;
}

bool AutoSwerveCommand::IsFinished() {
// if the swerve subsystem doesn't exist
if (swerve_ == nullptr) {
return true; // then don't try to do anything on it because it will fail
}

bool *at;

// if the swerve drive is at its setpoint
if (swerve_->AtSetpoint(at)) {
return true; // end the command
}

// otherwise, continue
return false;
}
35 changes: 35 additions & 0 deletions src/main/cpp/commands/swerve/TeleOpSwerveCommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

#include "commands/swerve/TeleOpSwerveCommand.h"

TeleOpSwerveCommand::TeleOpSwerveCommand(std::shared_ptr<SwerveDrive> swerve, std::shared_ptr<frc::Joystick> gamepad) {
swerve_ = swerve;
gamepad_ = gamepad;

if (swerve_ != nullptr) {
this->AddRequirements(swerve_.get());
}
}

void TeleOpSwerveCommand::Initialize() {
VOKC_CHECK(swerve_ != nullptr);
}

void TeleOpSwerveCommand::Execute() {
VOKC_CHECK(swerve_ != nullptr);
VOKC_CHECK(gamepad_ != nullptr);

double drive_power = -this->gamepad_->GetRawAxis(1);
double strafe_power = this->gamepad_->GetRawAxis(2);
double turn_power = this->gamepad_->GetRawAxis(3);

VOKC_CALL(swerve_->TeleOpDrive(drive_power, strafe_power, turn_power));
}

void TeleOpSwerveCommand::End(bool interrupted) {
// do nothing lol
}

bool TeleOpSwerveCommand::IsFinished() {
// this command should never end, unless it is interrupted by another
return false;
}
34 changes: 34 additions & 0 deletions src/main/cpp/hardware/HardwareInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,40 @@ bool SetupDrivetrainInterface(
return true;
}

bool SetupSwerveDriveInterface(
std::unique_ptr<HardwareInterface> &hardware,
std::shared_ptr<SwerveDriveHardwareInterface> *interface) {
OKC_CHECK(interface != nullptr);
OKC_CHECK(hardware->actuators != nullptr);
OKC_CHECK(hardware->sensors != nullptr);

// Get actuators interface for swerve drive.
std::unique_ptr<ActuatorInterface> &actuators = hardware->actuators;
std::unique_ptr<SensorInterface> &sensors = hardware->sensors;

// set up swerve drive interface.
SwerveDriveHardwareInterface swerve_drive_interface = {
actuators->left_front_drive_motor.get(),
actuators->left_back_drive_motor.get(),
actuators->right_front_drive_motor.get(),
actuators->right_back_drive_motor.get(),
actuators->left_front_steer_motor.get(),
actuators->left_back_steer_motor.get(),
actuators->right_front_steer_motor.get(),
actuators->right_back_steer_motor.get(),

sensors->ahrs.get(),

sensors->left_front_steer_encoder.get(),
sensors->left_back_steer_encoder.get(),
sensors->right_front_steer_encoder.get(),
sensors->right_back_steer_encoder.get(),
};

// set the output interface
*interface = std::make_shared<SwerveDriveHardwareInterface>(swerve_drive_interface);
}

bool SetupIntakeInterface(std::unique_ptr<HardwareInterface> &hardware,
std::shared_ptr<IntakeHardwareInterface> *interface) {
OKC_CHECK(interface != nullptr);
Expand Down
Loading