Skip to content

Commit

Permalink
Merge pull request #15 from REVrobotics/2025-update
Browse files Browse the repository at this point in the history
Update for 2025
  • Loading branch information
jfabellera authored Nov 16, 2024
2 parents 7272fcb + be301ff commit 345fb05
Show file tree
Hide file tree
Showing 22 changed files with 157 additions and 349 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,16 @@ out/
.fleet

# Simulation GUI and other tools window save file
networktables.json
simgui.json
*-window.json

# Simulation data log directory
logs/

# Folder that has CTRE Phoenix Sim device config storage
ctre_sim/

# clangd
/.cache
compile_commands.json
2 changes: 1 addition & 1 deletion .wpilib/wpilib_preferences.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"enableCppIntellisense": true,
"currentLanguage": "cpp",
"projectYear": "2024",
"projectYear": "2025beta",
"teamNumber": 2714
}
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# MAXSwerve C++ Template Changelog

## [2025.0] - 2024-11-15

- Updates project for 2025 FRC season
- Uses new SPARK configuration mechanism introduced in REVLib 2025
- Removes slew rate limiter since it is no longer needed with MAXSwerve 2.0 wheels

## [2024.0] - 2024-01-08

- Updates project for 2024 FRC season
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# MAXSwerve C++ Template v2024.0
# MAXSwerve C++ Template v2025.0

See [the online changelog](https://github.com/REVrobotics/MAXSwerve-Cpp-Template/blob/main/CHANGELOG.md) for information about updates to the template that may have been released since you created your project.

Expand All @@ -12,11 +12,11 @@ To get started, make sure you have calibrated the zero offsets for the absolute

## Prerequisites

* SPARK MAX Firmware v1.6.2 - Adds features that are required for swerve
* REVLib v2023.1.2 - Includes APIs for the new firmware features
* SPARK MAX Firmware v25.0.0
* REVLib v2025.0.0

## Configuration

It is possible that this project will not work for your robot right out of the box. Various things like the CAN IDs, PIDF gains, chassis configuration, etc. must be determined for your own robot!

These values can be adjusted in the `Constants.h` file.
These values can be adjusted in the `Configs.h` and `Constants.h` files.
2 changes: 1 addition & 1 deletion WPILib-License.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2009-2023 FIRST and other WPILib contributors
Copyright (c) 2009-2024 FIRST and other WPILib contributors
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
id "cpp"
id "google-test-test-suite"
id "edu.wpi.first.GradleRIO" version "2024.1.1"
id "edu.wpi.first.GradleRIO" version "2025.1.1-beta-1"
}

// Define my targets (RoboRIO) and artifacts (deployable files)
Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=permwrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
7 changes: 5 additions & 2 deletions gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
Expand Down Expand Up @@ -55,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
Expand Down Expand Up @@ -84,7 +86,8 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down
22 changes: 12 additions & 10 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
Expand Down Expand Up @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand All @@ -57,11 +59,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto execute

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2

goto fail

Expand Down
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pluginManagement {
repositories {
mavenLocal()
gradlePluginPortal()
String frcYear = '2024'
String frcYear = '2025'
File frcHome
if (OperatingSystem.current().isWindows()) {
String publicFolder = System.getenv('PUBLIC')
Expand Down
5 changes: 2 additions & 3 deletions src/main/cpp/RobotContainer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ RobotContainer::RobotContainer() {
m_driverController.GetLeftX(), OIConstants::kDriveDeadband)},
-units::radians_per_second_t{frc::ApplyDeadband(
m_driverController.GetRightX(), OIConstants::kDriveDeadband)},
true, true);
true);
},
{&m_drive}));
}
Expand Down Expand Up @@ -96,6 +96,5 @@ frc2::Command* RobotContainer::GetAutonomousCommand() {
return new frc2::SequentialCommandGroup(
std::move(swerveControllerCommand),
frc2::InstantCommand(
[this]() { m_drive.Drive(0_mps, 0_mps, 0_rad_per_s, false, false); },
{}));
[this]() { m_drive.Drive(0_mps, 0_mps, 0_rad_per_s, false); }, {}));
}
69 changes: 5 additions & 64 deletions src/main/cpp/subsystems/DriveSubsystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <units/velocity.h>

#include "Constants.h"
#include "utils/SwerveUtils.h"

using namespace DriveConstants;

Expand Down Expand Up @@ -40,73 +39,15 @@ void DriveSubsystem::Periodic() {

void DriveSubsystem::Drive(units::meters_per_second_t xSpeed,
units::meters_per_second_t ySpeed,
units::radians_per_second_t rot, bool fieldRelative,
bool rateLimit) {
double xSpeedCommanded;
double ySpeedCommanded;

if (rateLimit) {
// Convert XY to polar for rate limiting
double inputTranslationDir = atan2(ySpeed.value(), xSpeed.value());
double inputTranslationMag =
sqrt(pow(xSpeed.value(), 2) + pow(ySpeed.value(), 2));

// Calculate the direction slew rate based on an estimate of the lateral
// acceleration
double directionSlewRate;
if (m_currentTranslationMag != 0.0) {
directionSlewRate =
abs(DriveConstants::kDirectionSlewRate / m_currentTranslationMag);
} else {
directionSlewRate = 500.0; // some high number that means the slew rate
// is effectively instantaneous
}

double currentTime = wpi::Now() * 1e-6;
double elapsedTime = currentTime - m_prevTime;
double angleDif = SwerveUtils::AngleDifference(inputTranslationDir,
m_currentTranslationDir);
if (angleDif < 0.45 * std::numbers::pi) {
m_currentTranslationDir = SwerveUtils::StepTowardsCircular(
m_currentTranslationDir, inputTranslationDir,
directionSlewRate * elapsedTime);
m_currentTranslationMag = m_magLimiter.Calculate(inputTranslationMag);
} else if (angleDif > 0.85 * std::numbers::pi) {
if (m_currentTranslationMag >
1e-4) { // some small number to avoid floating-point errors with
// equality checking
// keep currentTranslationDir unchanged
m_currentTranslationMag = m_magLimiter.Calculate(0.0);
} else {
m_currentTranslationDir =
SwerveUtils::WrapAngle(m_currentTranslationDir + std::numbers::pi);
m_currentTranslationMag = m_magLimiter.Calculate(inputTranslationMag);
}
} else {
m_currentTranslationDir = SwerveUtils::StepTowardsCircular(
m_currentTranslationDir, inputTranslationDir,
directionSlewRate * elapsedTime);
m_currentTranslationMag = m_magLimiter.Calculate(0.0);
}
m_prevTime = currentTime;

xSpeedCommanded = m_currentTranslationMag * cos(m_currentTranslationDir);
ySpeedCommanded = m_currentTranslationMag * sin(m_currentTranslationDir);
m_currentRotation = m_rotLimiter.Calculate(rot.value());

} else {
xSpeedCommanded = xSpeed.value();
ySpeedCommanded = ySpeed.value();
m_currentRotation = rot.value();
}

units::radians_per_second_t rot,
bool fieldRelative) {
// Convert the commanded speeds into the correct units for the drivetrain
units::meters_per_second_t xSpeedDelivered =
xSpeedCommanded * DriveConstants::kMaxSpeed;
xSpeed.value() * DriveConstants::kMaxSpeed;
units::meters_per_second_t ySpeedDelivered =
ySpeedCommanded * DriveConstants::kMaxSpeed;
ySpeed.value() * DriveConstants::kMaxSpeed;
units::radians_per_second_t rotDelivered =
m_currentRotation * DriveConstants::kMaxAngularSpeed;
rot.value() * DriveConstants::kMaxAngularSpeed;

auto states = kDriveKinematics.ToSwerveModuleStates(
fieldRelative
Expand Down
99 changes: 21 additions & 78 deletions src/main/cpp/subsystems/MAXSwerveModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,78 +6,23 @@

#include <frc/geometry/Rotation2d.h>

#include <numbers>
#include "Configs.h"

#include "Constants.h"

using namespace ModuleConstants;
using namespace rev::spark;

MAXSwerveModule::MAXSwerveModule(const int drivingCANId, const int turningCANId,
const double chassisAngularOffset)
: m_drivingSparkMax(drivingCANId, rev::CANSparkMax::MotorType::kBrushless),
m_turningSparkMax(turningCANId, rev::CANSparkMax::MotorType::kBrushless) {
// Factory reset, so we get the SPARKS MAX to a known state before configuring
// them. This is useful in case a SPARK MAX is swapped out.
m_drivingSparkMax.RestoreFactoryDefaults();
m_turningSparkMax.RestoreFactoryDefaults();

// Apply position and velocity conversion factors for the driving encoder. The
// native units for position and velocity are rotations and RPM, respectively,
// but we want meters and meters per second to use with WPILib's swerve APIs.
m_drivingEncoder.SetPositionConversionFactor(kDrivingEncoderPositionFactor);
m_drivingEncoder.SetVelocityConversionFactor(kDrivingEncoderVelocityFactor);

// Apply position and velocity conversion factors for the turning encoder. We
// want these in radians and radians per second to use with WPILib's swerve
// APIs.
m_turningAbsoluteEncoder.SetPositionConversionFactor(
kTurningEncoderPositionFactor);
m_turningAbsoluteEncoder.SetVelocityConversionFactor(
kTurningEncoderVelocityFactor);

// Invert the turning encoder, since the output shaft rotates in the opposite
// direction of the steering motor in the MAXSwerve Module.
m_turningAbsoluteEncoder.SetInverted(kTurningEncoderInverted);

// Enable PID wrap around for the turning motor. This will allow the PID
// controller to go through 0 to get to the setpoint i.e. going from 350
// degrees to 10 degrees will go through 0 rather than the other direction
// which is a longer route.
m_turningPIDController.SetPositionPIDWrappingEnabled(true);
m_turningPIDController.SetPositionPIDWrappingMinInput(
kTurningEncoderPositionPIDMinInput.value());
m_turningPIDController.SetPositionPIDWrappingMaxInput(
kTurningEncoderPositionPIDMaxInput.value());

// Set the PID Controller to use the duty cycle encoder on the swerve
// module instead of the built in NEO550 encoder.
m_turningPIDController.SetFeedbackDevice(m_turningAbsoluteEncoder);

// Set the PID gains for the driving motor. Note these are example gains, and
// you may need to tune them for your own robot!
m_drivingPIDController.SetP(kDrivingP);
m_drivingPIDController.SetI(kDrivingI);
m_drivingPIDController.SetD(kDrivingD);
m_drivingPIDController.SetFF(kDrivingFF);
m_drivingPIDController.SetOutputRange(kDrivingMinOutput, kDrivingMaxOutput);

// Set the PID gains for the turning motor. Note these are example gains, and
// you may need to tune them for your own robot!
m_turningPIDController.SetP(kTurningP);
m_turningPIDController.SetI(kTurningI);
m_turningPIDController.SetD(kTurningD);
m_turningPIDController.SetFF(kTurningFF);
m_turningPIDController.SetOutputRange(kTurningMinOutput, kTurningMaxOutput);

m_drivingSparkMax.SetIdleMode(kDrivingMotorIdleMode);
m_turningSparkMax.SetIdleMode(kTurningMotorIdleMode);
m_drivingSparkMax.SetSmartCurrentLimit(kDrivingMotorCurrentLimit.value());
m_turningSparkMax.SetSmartCurrentLimit(kDrivingMotorCurrentLimit.value());

// Save the SPARK MAX configurations. If a SPARK MAX browns out during
// operation, it will maintain the above configurations.
m_drivingSparkMax.BurnFlash();
m_turningSparkMax.BurnFlash();
: m_drivingSpark(drivingCANId, SparkMax::MotorType::kBrushless),
m_turningSpark(turningCANId, SparkMax::MotorType::kBrushless) {
// Apply the respective configurations to the SPARKS. Reset parameters before
// applying the configuration to bring the SPARK to a known good state.
// Persist the settings to the SPARK to avoid losing them on a power cycle.
m_drivingSpark.Configure(Configs::MAXSwerveModule::DrivingConfig(),
SparkBase::ResetMode::kResetSafeParameters,
SparkBase::PersistMode::kPersistParameters);
m_turningSpark.Configure(Configs::MAXSwerveModule::TurningConfig(),
SparkBase::ResetMode::kResetSafeParameters,
SparkBase::PersistMode::kPersistParameters);

m_chassisAngularOffset = chassisAngularOffset;
m_desiredState.angle =
Expand Down Expand Up @@ -107,16 +52,14 @@ void MAXSwerveModule::SetDesiredState(
frc::Rotation2d(units::radian_t{m_chassisAngularOffset});

// Optimize the reference state to avoid spinning further than 90 degrees.
frc::SwerveModuleState optimizedDesiredState{frc::SwerveModuleState::Optimize(
correctedDesiredState, frc::Rotation2d(units::radian_t{
m_turningAbsoluteEncoder.GetPosition()}))};

// Command driving and turning SPARKS MAX towards their respective setpoints.
m_drivingPIDController.SetReference((double)optimizedDesiredState.speed,
rev::CANSparkMax::ControlType::kVelocity);
m_turningPIDController.SetReference(
optimizedDesiredState.angle.Radians().value(),
rev::CANSparkMax::ControlType::kPosition);
correctedDesiredState.Optimize(
frc::Rotation2d(units::radian_t{m_turningAbsoluteEncoder.GetPosition()}));

m_drivingClosedLoopController.SetReference(
(double)correctedDesiredState.speed, SparkMax::ControlType::kVelocity);
m_turningClosedLoopController.SetReference(
correctedDesiredState.angle.Radians().value(),
SparkMax::ControlType::kPosition);

m_desiredState = desiredState;
}
Expand Down
Loading

0 comments on commit 345fb05

Please sign in to comment.