Merge branch 'main' into 2027

This commit is contained in:
Peter Johnson
2025-11-01 09:39:08 -07:00
61 changed files with 455 additions and 941 deletions

View File

@@ -37,7 +37,7 @@ jobs:
build-mac:
name: "Mac"
runs-on: macos-14
runs-on: macOS-15
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }

View File

@@ -20,7 +20,7 @@ jobs:
name: Linux
container: wpilib/systemcore-cross-ubuntu:2027-24.04
flags: "--preset with-java-and-sccache -DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON"
- os: macOS-14
- os: macOS-15
name: macOS
container: ""
flags: "--preset with-sccache -DCMAKE_BUILD_TYPE=Release -DWITH_EXAMPLES=ON"
@@ -58,7 +58,7 @@ jobs:
uses: lukka/run-vcpkg@v11.5
with:
vcpkgDirectory: ${{ runner.workspace }}/vcpkg
vcpkgGitCommitId: 37c3e63a1306562f7f59c4c3c8892ddd50fdf992 # HEAD on 2024-02-24
vcpkgGitCommitId: 74e6536215718009aae747d86d84b78376bf9e09 # HEAD on 2025-10-17
- name: configure
run: cmake ${{ matrix.flags }}

View File

@@ -98,7 +98,7 @@ jobs:
build-options: "-PciReleaseOnly -Pbuildwinarm64 -Ponlywindowsarm64"
task: "copyAllOutputs"
outputs: "build/allOutputs"
- os: macOS-14
- os: macOS-15
artifact-name: macOS
architecture: aarch64
task: "build"
@@ -144,7 +144,7 @@ jobs:
if: matrix.os == 'windows-2022'
- name: Check disk free space pre-cleanup (macOS)
run: df -h .
if: matrix.os == 'macOS-14'
if: matrix.os == 'macOS-15'
- name: Cleanup disk space
# CodeQL: 5G
# go: 748M
@@ -153,10 +153,10 @@ jobs:
rm -rf /Users/runner/hostedtoolcache/CodeQL
rm -rf /Users/runner/hostedtoolcache/go
rm -rf /Users/runner/Library/Android
if: matrix.os == 'macOS-14'
if: matrix.os == 'macOS-15'
- name: Check disk free space post-cleanup (macOS)
run: df -h .
if: matrix.os == 'macOS-14'
if: matrix.os == 'macOS-15'
- name: Build with Gradle
run: ./gradlew ${{ matrix.task }} --build-cache -PbuildServer -PskipJavaFormat ${{ matrix.build-options }} ${{ env.EXTRA_GRADLE_ARGS }}
env:
@@ -172,7 +172,7 @@ jobs:
if: matrix.os == 'windows-2022'
- name: Check disk free space (macOS)
run: df -h .
if: matrix.os == 'macOS-14'
if: matrix.os == 'macOS-15'
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact-name }}

View File

@@ -36,7 +36,7 @@ jobs:
- name: Install wpiformat
run: |
python -m venv ${{ runner.temp }}/wpiformat
${{ runner.temp }}/wpiformat/bin/pip3 install wpiformat==2025.34
${{ runner.temp }}/wpiformat/bin/pip3 install wpiformat==2025.36
- name: Run
run: ${{ runner.temp }}/wpiformat/bin/wpiformat
- name: Check output
@@ -78,7 +78,7 @@ jobs:
- name: Install wpiformat
run: |
python -m venv ${{ runner.temp }}/wpiformat
${{ runner.temp }}/wpiformat/bin/pip3 install wpiformat==2025.34
${{ runner.temp }}/wpiformat/bin/pip3 install wpiformat==2025.36
- name: Create compile_commands.json
run: |
./gradlew generateCompileCommands -Ptoolchain-optional-roboRio

View File

@@ -97,7 +97,7 @@ jobs:
build-options: "-PciReleaseOnly -Pbuildwinarm64 -Ponlywindowsarm64"
task: "copyAllOutputs"
outputs: "build/allOutputs"
- os: macOS-14
- os: macOS-15
artifact-name: macOS
architecture: aarch64
task: "build"
@@ -137,7 +137,7 @@ jobs:
if: matrix.os == 'windows-2022'
- name: Check disk free space pre-cleanup (macOS)
run: df -h .
if: matrix.os == 'macOS-14'
if: matrix.os == 'macOS-15'
- name: Cleanup disk space
# CodeQL: 5G
# go: 748M
@@ -146,10 +146,10 @@ jobs:
rm -rf /Users/runner/hostedtoolcache/CodeQL
rm -rf /Users/runner/hostedtoolcache/go
rm -rf /Users/runner/Library/Android
if: matrix.os == 'macOS-14'
if: matrix.os == 'macOS-15'
- name: Check disk free space post-cleanup (macOS)
run: df -h .
if: matrix.os == 'macOS-14'
if: matrix.os == 'macOS-15'
- name: Build with Gradle
run: ./gradlew ${{ matrix.task }} -PbuildServer -PskipJavaFormat ${{ matrix.build-options }}
- name: Sign Libraries with Developer ID
@@ -161,7 +161,7 @@ jobs:
if: matrix.os == 'windows-2022'
- name: Check disk free space (macOS)
run: df -h .
if: matrix.os == 'macOS-14'
if: matrix.os == 'macOS-15'
- uses: actions/upload-artifact@v4
with:
name: ${{ matrix.artifact-name }}

View File

@@ -48,20 +48,25 @@ cppProjectZips.add(project(':romiVendordep').cppHeadersZip)
cppProjectZips.add(project(':xrpVendordep').cppHeadersZip)
doxygen {
// Doxygen binaries are only provided for x86_64 platforms
// Other platforms will need to provide doxygen via their system
// See below maven and https://doxygen.nl/download.html for provided binaries
// Ensure theme.css (from https://github.com/jothepro/doxygen-awesome-css) is compatible with
// doxygen version when updating
// Doxygen binaries are only provided for x86_64 platforms. Other platforms
// will need to use a local Doxygen install.
//
// executeByVersion() fetches Doxygen binaries from
// https://frcmaven.wpi.edu/ui/native/generic-release-mirror/doxygen/, which
// is a mirror of binaries from https://doxygen.nl/download.html.
//
// Ensure theme.css (from https://github.com/jothepro/doxygen-awesome-css)
// is compatible with Doxygen version when updating.
executables {
doxygen {
// Note: has no effect if not on an x86_64 platform - you need to have a global install available on your
// PATH for the doxygen plugin to run
// Note: has no effect if not on an x86_64 platform - you need to
// have a global install available on your PATH for the Doxygen
// plugin to run.
executableByVersion('1.12.0')
String arch = System.getProperty("os.arch");
if (!(arch.equals("x86_64") || arch.equals("amd64"))) {
// Search for a local doxygen install
// Search for a local Doxygen install
executableBySearchPath('doxygen')
}
}

View File

@@ -186,7 +186,7 @@ extern "C" {
#if defined(WIN32) || defined(_WIN32)
__declspec(dllexport)
#endif
int HALSIM_InitExtension(void) {
int HALSIM_InitExtension(void) {
static bool once = false;
if (once) {

View File

@@ -41,7 +41,7 @@ extern "C" {
#if defined(WIN32) || defined(_WIN32)
__declspec(dllexport)
#endif
int HALSIM_InitExtension(void) {
int HALSIM_InitExtension(void) {
std::puts("Simulator GUI Initializing.");
gui::CreateContext();

View File

@@ -54,13 +54,9 @@
HALSIM_Cancel##cbname##Callback(m_index, m_callback); \
} \
\
int32_t GetIndex() const { \
return m_index; \
} \
int32_t GetIndex() const { return m_index; } \
\
int GetChannel() const { \
return m_channel; \
} \
int GetChannel() const { return m_channel; } \
\
private: \
static void CallbackFunc(const char*, void* param, \
@@ -95,13 +91,9 @@
HALSIM_Cancel##cbname##Callback(m_index, m_channel, m_callback); \
} \
\
int32_t GetIndex() const { \
return m_index; \
} \
int32_t GetIndex() const { return m_index; } \
\
int32_t GetChannel() const { \
return m_channel; \
} \
int32_t GetChannel() const { return m_channel; } \
\
private: \
static void CallbackFunc(const char*, void* param, \

View File

@@ -18,7 +18,7 @@ extern "C" {
__declspec(dllexport)
#endif
int HALSIM_InitExtension(void) {
int HALSIM_InitExtension(void) {
std::puts("HALSim WS Client Extension Initializing");
HAL_OnShutdown(nullptr, [](void*) { gClient.reset(); });

View File

@@ -18,7 +18,7 @@ extern "C" {
#if defined(WIN32) || defined(_WIN32)
__declspec(dllexport)
#endif
int HALSIM_InitExtension(void) {
int HALSIM_InitExtension(void) {
std::puts("Websocket WS Server Initializing.");
HAL_OnShutdown(nullptr, [](void*) { gServer.reset(); });

View File

@@ -25,7 +25,7 @@ extern "C" {
__declspec(dllexport)
#endif
int HALSIM_InitExtension(void) {
int HALSIM_InitExtension(void) {
std::puts("HALSim XRP Extension Initializing");
HAL_OnShutdown(nullptr, [](void*) { gClient.reset(); });

View File

@@ -32,10 +32,6 @@
<Bug pattern="AT_STALE_THREAD_WRITE_OF_PRIMITIVE" />
<Class name="edu.wpi.first.wpilibj.Ultrasonic" />
</Match>
<Match>
<Bug pattern="AT_STALE_THREAD_WRITE_OF_PRIMITIVE" />
<Class name="edu.wpi.first.wpilibj.motorcontrol.NidecBrushless" />
</Match>
<Match>
<Bug pattern="AT_STALE_THREAD_WRITE_OF_PRIMITIVE" />
<Class name="edu.wpi.first.wpilibj2.command.CommandScheduler" />

View File

@@ -251,17 +251,17 @@ OLSResult CalculateFeedforwardGains(const Storage& data,
if (type == analysis::kArm) {
// dx/dt = -Kv/Ka x + 1/Ka u - Ks/Ka sgn(x)
// - Kg/Ka cos(offset) cos(angle) NOLINT
// + Kg/Ka sin(offset) sin(angle) NOLINT
// dx/dt = αx + βu + γ sgn(x) + δ cos(angle) + ε sin(angle) NOLINT
// - Kg/Ka cos(offset) cos(angle)
// + Kg/Ka sin(offset) sin(angle)
// dx/dt = αx + βu + γ sgn(x) + δ cos(angle) + ε sin(angle)
// δ = -Kg/Ka cos(offset)
// ε = Kg/Ka sin(offset)
double δ = ols.coeffs[3];
double ε = ols.coeffs[4];
// Kg = hypot(δ, ε)/β NOLINT
// offset = atan2(ε, -δ) NOLINT
// Kg = hypot(δ, ε)/β
// offset = atan2(ε, -δ)
gains.emplace_back(std::hypot(δ, ε) / β);
gains.emplace_back(std::atan2(ε, -δ));
}

View File

@@ -55,7 +55,6 @@ class Analyzer : public glass::View {
*/
static constexpr const char* kPresetNames[] = {"Default",
"WPILib",
"CTRE Phoenix 5 CANcoder",
"CTRE Phoenix 5",
"CTRE Phoenix 6",
"REV Brushless Encoder Port",

View File

@@ -19,10 +19,7 @@ def copy_upstream_src(wpilib_root: Path):
# Copy Sleipnir files into allwpilib
walk_cwd_and_copy_if(
lambda dp, f: (has_prefix(dp, Path("include")) or has_prefix(dp, Path("src")))
or f == ".clang-format"
or f == ".clang-tidy"
or f == ".styleguide"
or f == ".styleguide-license",
and f not in [".styleguide", ".styleguide-license"],
wpimath / "src/main/native/thirdparty/sleipnir",
)

View File

@@ -7,5 +7,5 @@
"libuv",
"libssh"
],
"builtin-baseline": "37c3e63a1306562f7f59c4c3c8892ddd50fdf992"
"builtin-baseline": "74e6536215718009aae747d86d84b78376bf9e09"
}

View File

@@ -25,8 +25,7 @@ namespace frc2 {
* std::unique_ptr<Command>, use CommandPtr::Unwrap to convert.
* CommandPtr::UnwrapVector does the same for vectors.
*/
class [[nodiscard]]
CommandPtr final {
class [[nodiscard]] CommandPtr final {
public:
explicit CommandPtr(std::unique_ptr<Command>&& command);

View File

@@ -1,19 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibc/generate_pwm_motor_controllers.py. DO NOT MODIFY
#include "frc/motorcontrol/DMC60.h"
#include <hal/UsageReporting.h>
using namespace frc;
DMC60::DMC60(int channel) : PWMMotorController("DMC60", channel) {
SetBounds(2.004_ms, 1.52_ms, 1.5_ms, 1.48_ms, 0.997_ms);
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
SetSpeed(0.0);
HAL_ReportUsage("IO", GetChannel(), "DigilentDMC60");
}

View File

@@ -1,19 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibc/generate_pwm_motor_controllers.py. DO NOT MODIFY
#include "frc/motorcontrol/Jaguar.h"
#include <hal/UsageReporting.h>
using namespace frc;
Jaguar::Jaguar(int channel) : PWMMotorController("Jaguar", channel) {
SetBounds(2.31_ms, 1.55_ms, 1.507_ms, 1.454_ms, 0.697_ms);
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
SetSpeed(0.0);
HAL_ReportUsage("IO", GetChannel(), "Jaguar");
}

View File

@@ -1,19 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibc/generate_pwm_motor_controllers.py. DO NOT MODIFY
#include "frc/motorcontrol/SD540.h"
#include <hal/UsageReporting.h>
using namespace frc;
SD540::SD540(int channel) : PWMMotorController("SD540", channel) {
SetBounds(2.05_ms, 1.55_ms, 1.5_ms, 1.44_ms, 0.94_ms);
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_5Ms);
SetSpeed(0.0);
HAL_ReportUsage("IO", GetChannel(), "MindsensorsSD540");
}

View File

@@ -1,19 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibc/generate_pwm_motor_controllers.py. DO NOT MODIFY
#include "frc/motorcontrol/Victor.h"
#include <hal/UsageReporting.h>
using namespace frc;
Victor::Victor(int channel) : PWMMotorController("Victor", channel) {
SetBounds(2.027_ms, 1.525_ms, 1.507_ms, 1.49_ms, 1.026_ms);
m_pwm.SetOutputPeriod(PWM::kOutputPeriod_10Ms);
SetSpeed(0.0);
HAL_ReportUsage("IO", GetChannel(), "Victor");
}

View File

@@ -1,43 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibc/generate_pwm_motor_controllers.py. DO NOT MODIFY
#pragma once
#include "frc/motorcontrol/PWMMotorController.h"
namespace frc {
/**
* Digilent DMC 60 Motor Controller with PWM control.
*
* Note that the DMC 60 uses the following bounds for PWM values. These
* values should work reasonably well for most controllers, but if users
* experience issues such as asymmetric behavior around the deadband or
* inability to saturate the controller in either direction, calibration is
* recommended. The calibration procedure can be found in the DMC 60 User
* Manual available from Digilent.
*
* \li 2.004ms = full "forward"
* \li 1.520ms = the "high end" of the deadband range
* \li 1.500ms = center of the deadband range (off)
* \li 1.480ms = the "low end" of the deadband range
* \li 0.997ms = full "reverse"
*/
class DMC60 : public PWMMotorController {
public:
/**
* Constructor for a DMC 60 connected via PWM.
*
* @param channel The PWM channel that the DMC 60 is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit DMC60(int channel);
DMC60(DMC60&&) = default;
DMC60& operator=(DMC60&&) = default;
};
} // namespace frc

View File

@@ -1,43 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibc/generate_pwm_motor_controllers.py. DO NOT MODIFY
#pragma once
#include "frc/motorcontrol/PWMMotorController.h"
namespace frc {
/**
* Luminary Micro / Vex Robotics Jaguar Motor Controller with PWM control.
*
* Note that the Jaguar uses the following bounds for PWM values. These
* values should work reasonably well for most controllers, but if users
* experience issues such as asymmetric behavior around the deadband or
* inability to saturate the controller in either direction, calibration is
* recommended. The calibration procedure can be found in the Jaguar User
* Manual available from Luminary Micro / Vex Robotics.
*
* \li 2.310ms = full "forward"
* \li 1.550ms = the "high end" of the deadband range
* \li 1.507ms = center of the deadband range (off)
* \li 1.454ms = the "low end" of the deadband range
* \li 0.697ms = full "reverse"
*/
class Jaguar : public PWMMotorController {
public:
/**
* Constructor for a Jaguar connected via PWM.
*
* @param channel The PWM channel that the Jaguar is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit Jaguar(int channel);
Jaguar(Jaguar&&) = default;
Jaguar& operator=(Jaguar&&) = default;
};
} // namespace frc

View File

@@ -1,43 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibc/generate_pwm_motor_controllers.py. DO NOT MODIFY
#pragma once
#include "frc/motorcontrol/PWMMotorController.h"
namespace frc {
/**
* Mindsensors SD540 Motor Controller with PWM control.
*
* Note that the SD540 uses the following bounds for PWM values. These
* values should work reasonably well for most controllers, but if users
* experience issues such as asymmetric behavior around the deadband or
* inability to saturate the controller in either direction, calibration is
* recommended. The calibration procedure can be found in the SD540 User
* Manual available from Mindsensors.
*
* \li 2.050ms = full "forward"
* \li 1.550ms = the "high end" of the deadband range
* \li 1.500ms = center of the deadband range (off)
* \li 1.440ms = the "low end" of the deadband range
* \li 0.940ms = full "reverse"
*/
class SD540 : public PWMMotorController {
public:
/**
* Constructor for a SD540 connected via PWM.
*
* @param channel The PWM channel that the SD540 is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit SD540(int channel);
SD540(SD540&&) = default;
SD540& operator=(SD540&&) = default;
};
} // namespace frc

View File

@@ -1,43 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibc/generate_pwm_motor_controllers.py. DO NOT MODIFY
#pragma once
#include "frc/motorcontrol/PWMMotorController.h"
namespace frc {
/**
* Vex Robotics Victor 888 Motor Controller with PWM control.
*
* Note that the Victor 888 uses the following bounds for PWM values. These
* values should work reasonably well for most controllers, but if users
* experience issues such as asymmetric behavior around the deadband or
* inability to saturate the controller in either direction, calibration is
* recommended. The calibration procedure can be found in the Victor 888 User
* Manual available from Vex Robotics.
*
* \li 2.027ms = full "forward"
* \li 1.525ms = the "high end" of the deadband range
* \li 1.507ms = center of the deadband range (off)
* \li 1.490ms = the "low end" of the deadband range
* \li 1.026ms = full "reverse"
*/
class Victor : public PWMMotorController {
public:
/**
* Constructor for a Victor 888 connected via PWM.
*
* @param channel The PWM channel that the Victor 888 is attached to. 0-9 are
* on-board, 10-19 are on the MXP port
*/
explicit Victor(int channel);
Victor(Victor&&) = default;
Victor& operator=(Victor&&) = default;
};
} // namespace frc

View File

@@ -181,6 +181,10 @@ void Notifier::StartPeriodic(units::second_t period) {
UpdateAlarm();
}
void Notifier::StartPeriodic(units::hertz_t frequency) {
StartPeriodic(1 / frequency);
}
void Notifier::Stop() {
std::scoped_lock lock(m_processMutex);
m_periodic = false;

View File

@@ -88,6 +88,8 @@ TimedRobot::TimedRobot(units::second_t period) : IterativeRobotBase(period) {
HAL_ReportUsage("Framework", "TimedRobot");
}
TimedRobot::TimedRobot(units::hertz_t frequency) : TimedRobot{1 / frequency} {}
TimedRobot::~TimedRobot() {
if (m_notifier != HAL_kInvalidHandle) {
int32_t status = 0;

View File

@@ -14,6 +14,7 @@
#include <utility>
#include <hal/Types.h>
#include <units/frequency.h>
#include <units/time.h>
#include <wpi/mutex.h>
@@ -107,6 +108,17 @@ class Notifier {
*/
void StartPeriodic(units::second_t period);
/**
* Run the callback periodically with the given frequency.
*
* The user-provided callback should be written so that it completes before
* the next time it's scheduled to run.
*
* @param frequency Frequency after which to call the callback starting one
* period after the call to this method.
*/
void StartPeriodic(units::hertz_t frequency);
/**
* Stop further callback invocations.
*

View File

@@ -11,6 +11,7 @@
#include <hal/Notifier.h>
#include <hal/Types.h>
#include <units/frequency.h>
#include <units/math.h>
#include <units/time.h>
#include <wpi/priority_queue.h>
@@ -47,10 +48,17 @@ class TimedRobot : public IterativeRobotBase {
/**
* Constructor for TimedRobot.
*
* @param period Period.
* @param period The period of the robot loop function.
*/
explicit TimedRobot(units::second_t period = kDefaultPeriod);
/**
* Constructor for TimedRobot.
*
* @param frequency The frequency of the robot loop function.
*/
explicit TimedRobot(units::hertz_t frequency);
TimedRobot(TimedRobot&&) = default;
TimedRobot& operator=(TimedRobot&&) = default;

View File

@@ -0,0 +1,54 @@
// 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 <frc/Encoder.h>
#include <frc/TimedRobot.h>
#include <frc/controller/ProfiledPIDController.h>
#include <frc/controller/SimpleMotorFeedforward.h>
#include <frc/motorcontrol/PWMSparkMax.h>
#include <units/acceleration.h>
#include <units/length.h>
#include <units/velocity.h>
#include <units/voltage.h>
/**
* ProfiledPIDController with feedforward snippets for frc-docs.
* https://docs.wpilib.org/en/stable/docs/software/advanced-controls/controllers/profiled-pidcontroller.html
*/
class Robot : public frc::TimedRobot {
public:
Robot() { m_encoder.SetDistancePerPulse(1.0 / 256.0); }
// Controls a simple motor's position using a SimpleMotorFeedforward
// and a ProfiledPIDController
void GoToPosition(units::meter_t goalPosition) {
auto pidVal = m_controller.Calculate(
units::meter_t{m_encoder.GetDistance()}, goalPosition);
m_motor.SetVoltage(units::volt_t{pidVal} +
m_feedforward.Calculate(
m_lastSpeed, m_controller.GetSetpoint().velocity));
m_lastSpeed = m_controller.GetSetpoint().velocity;
}
void TeleopPeriodic() override {
// Example usage: move to position 10.0 meters
GoToPosition(10.0_m);
}
private:
frc::ProfiledPIDController<units::meters> m_controller{
1.0, 0.0, 0.0, {5_mps, 10_mps_sq}};
frc::SimpleMotorFeedforward<units::meters> m_feedforward{0.5_V, 1.5_V / 1_mps,
0.3_V / 1_mps_sq};
frc::Encoder m_encoder{0, 1};
frc::PWMSparkMax m_motor{0};
units::meters_per_second_t m_lastSpeed = 0_mps;
};
#ifndef RUNNING_FRC_TESTS
int main() {
return frc::StartRobot<Robot>();
}
#endif

View File

@@ -146,5 +146,15 @@
],
"foldername": "OnboardIMU",
"gradlebase": "cpp"
},
{
"name": "ProfiledPIDFeedforward",
"description": "Snippets of ProfiledPIDController with feedforward for frc-docs.",
"tags": [
"PID",
"Profiled PID"
],
"foldername": "ProfiledPIDFeedforward",
"gradlebase": "cpp"
}
]

View File

@@ -1,30 +1,4 @@
[
{
"name": "DMC60",
"Manufacturer": "Digilent",
"DisplayName": "DMC 60",
"ResourceName": "DigilentDMC60",
"pulse_width_ms": {
"max": 2.004,
"deadbandMax": 1.520,
"center": 1.500,
"deadbandMin": 1.480,
"min": 0.997
}
},
{
"name": "Jaguar",
"Manufacturer": "Luminary Micro / Vex Robotics",
"DisplayName": "Jaguar",
"ResourceName": "Jaguar",
"pulse_width_ms": {
"max": 2.310,
"deadbandMax": 1.550,
"center": 1.507,
"deadbandMin": 1.454,
"min": 0.697
}
},
{
"name": "PWMSparkFlex",
"Manufacturer": "REV Robotics",
@@ -103,19 +77,6 @@
"min": 0.997
}
},
{
"name": "SD540",
"Manufacturer": "Mindsensors",
"DisplayName": "SD540",
"ResourceName": "MindsensorsSD540",
"pulse_width_ms": {
"max": 2.05,
"deadbandMax": 1.55,
"center": 1.50,
"deadbandMin": 1.44,
"min": 0.94
}
},
{
"name": "Spark",
"Manufacturer": "REV Robotics",
@@ -142,20 +103,6 @@
"min": 0.989
}
},
{
"name": "Victor",
"Manufacturer": "Vex Robotics",
"DisplayName": "Victor 888",
"ResourceName": "Victor",
"OutputPeriod": 10,
"pulse_width_ms": {
"max": 2.027,
"deadbandMax": 1.525,
"center": 1.507,
"deadbandMin": 1.490,
"min": 1.026
}
},
{
"name": "VictorSP",
"Manufacturer": "Vex Robotics",

View File

@@ -1,46 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibj/generate_pwm_motor_controllers.py. DO NOT MODIFY
package edu.wpi.first.wpilibj.motorcontrol;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.PWM;
/**
* Digilent DMC 60 Motor Controller.
*
* <p>Note that the DMC 60 uses the following bounds for PWM values. These values should work
* reasonably well for most controllers, but if users experience issues such as asymmetric behavior
* around the deadband or inability to saturate the controller in either direction, calibration is
* recommended. The calibration procedure can be found in the DMC 60 User Manual available from
* Digilent.
*
* <ul>
* <li>2.004ms = full "forward"
* <li>1.520ms = the "high end" of the deadband range
* <li>1.500ms = center of the deadband range (off)
* <li>1.480ms = the "low end" of the deadband range
* <li>0.997ms = full "reverse"
* </ul>
*/
public class DMC60 extends PWMMotorController {
/**
* Constructor.
*
* @param channel The PWM channel that the DMC 60 is attached to. 0-9 are on-board, 10-19
* are on the MXP port
*/
@SuppressWarnings("this-escape")
public DMC60(final int channel) {
super("DMC60", channel);
setBoundsMicroseconds(2004, 1520, 1500, 1480, 997);
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
setSpeed(0.0);
HAL.reportUsage("IO", getChannel(), "DigilentDMC60");
}
}

View File

@@ -1,46 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibj/generate_pwm_motor_controllers.py. DO NOT MODIFY
package edu.wpi.first.wpilibj.motorcontrol;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.PWM;
/**
* Luminary Micro / Vex Robotics Jaguar Motor Controller.
*
* <p>Note that the Jaguar uses the following bounds for PWM values. These values should work
* reasonably well for most controllers, but if users experience issues such as asymmetric behavior
* around the deadband or inability to saturate the controller in either direction, calibration is
* recommended. The calibration procedure can be found in the Jaguar User Manual available from
* Luminary Micro / Vex Robotics.
*
* <ul>
* <li>2.310ms = full "forward"
* <li>1.550ms = the "high end" of the deadband range
* <li>1.507ms = center of the deadband range (off)
* <li>1.454ms = the "low end" of the deadband range
* <li>0.697ms = full "reverse"
* </ul>
*/
public class Jaguar extends PWMMotorController {
/**
* Constructor.
*
* @param channel The PWM channel that the Jaguar is attached to. 0-9 are on-board, 10-19
* are on the MXP port
*/
@SuppressWarnings("this-escape")
public Jaguar(final int channel) {
super("Jaguar", channel);
setBoundsMicroseconds(2310, 1550, 1507, 1454, 697);
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
setSpeed(0.0);
HAL.reportUsage("IO", getChannel(), "Jaguar");
}
}

View File

@@ -1,46 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibj/generate_pwm_motor_controllers.py. DO NOT MODIFY
package edu.wpi.first.wpilibj.motorcontrol;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.PWM;
/**
* Mindsensors SD540 Motor Controller.
*
* <p>Note that the SD540 uses the following bounds for PWM values. These values should work
* reasonably well for most controllers, but if users experience issues such as asymmetric behavior
* around the deadband or inability to saturate the controller in either direction, calibration is
* recommended. The calibration procedure can be found in the SD540 User Manual available from
* Mindsensors.
*
* <ul>
* <li>2.050ms = full "forward"
* <li>1.550ms = the "high end" of the deadband range
* <li>1.500ms = center of the deadband range (off)
* <li>1.440ms = the "low end" of the deadband range
* <li>0.940ms = full "reverse"
* </ul>
*/
public class SD540 extends PWMMotorController {
/**
* Constructor.
*
* @param channel The PWM channel that the SD540 is attached to. 0-9 are on-board, 10-19
* are on the MXP port
*/
@SuppressWarnings("this-escape")
public SD540(final int channel) {
super("SD540", channel);
setBoundsMicroseconds(2050, 1550, 1500, 1440, 940);
m_pwm.setOutputPeriod(PWM.OutputPeriod.k5Ms);
setSpeed(0.0);
HAL.reportUsage("IO", getChannel(), "MindsensorsSD540");
}
}

View File

@@ -1,46 +0,0 @@
// 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.
// THIS FILE WAS AUTO-GENERATED BY ./wpilibj/generate_pwm_motor_controllers.py. DO NOT MODIFY
package edu.wpi.first.wpilibj.motorcontrol;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.wpilibj.PWM;
/**
* Vex Robotics Victor 888 Motor Controller.
*
* <p>Note that the Victor 888 uses the following bounds for PWM values. These values should work
* reasonably well for most controllers, but if users experience issues such as asymmetric behavior
* around the deadband or inability to saturate the controller in either direction, calibration is
* recommended. The calibration procedure can be found in the Victor 888 User Manual available from
* Vex Robotics.
*
* <ul>
* <li>2.027ms = full "forward"
* <li>1.525ms = the "high end" of the deadband range
* <li>1.507ms = center of the deadband range (off)
* <li>1.490ms = the "low end" of the deadband range
* <li>1.026ms = full "reverse"
* </ul>
*/
public class Victor extends PWMMotorController {
/**
* Constructor.
*
* @param channel The PWM channel that the Victor 888 is attached to. 0-9 are on-board, 10-19
* are on the MXP port
*/
@SuppressWarnings("this-escape")
public Victor(final int channel) {
super("Victor", channel);
setBoundsMicroseconds(2027, 1525, 1507, 1490, 1026);
m_pwm.setOutputPeriod(PWM.OutputPeriod.k10Ms);
setSpeed(0.0);
HAL.reportUsage("IO", getChannel(), "Victor");
}
}

View File

@@ -4,9 +4,12 @@
package edu.wpi.first.wpilibj;
import static edu.wpi.first.units.Units.Seconds;
import static edu.wpi.first.util.ErrorMessages.requireNonNullParam;
import edu.wpi.first.hal.NotifierJNI;
import edu.wpi.first.units.measure.Frequency;
import edu.wpi.first.units.measure.Time;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@@ -186,6 +189,15 @@ public class Notifier implements AutoCloseable {
}
}
/**
* Run the callback once after the given delay.
*
* @param delay Time to wait before the callback is called.
*/
public void startSingle(Time delay) {
startSingle(delay.in(Seconds));
}
/**
* Run the callback periodically with the given period.
*
@@ -207,6 +219,32 @@ public class Notifier implements AutoCloseable {
}
}
/**
* Run the callback periodically with the given period.
*
* <p>The user-provided callback should be written so that it completes before the next time it's
* scheduled to run.
*
* @param period Period after which to call the callback starting one period after the call to
* this method.
*/
public void startPeriodic(Time period) {
startPeriodic(period.in(Seconds));
}
/**
* Run the callback periodically with the given frequency.
*
* <p>The user-provided callback should be written so that it completes before the next time it's
* scheduled to run.
*
* @param frequency Frequency at which to call the callback, starting one period after the call to
* this method.
*/
public void startPeriodic(Frequency frequency) {
startPeriodic(frequency.asPeriod());
}
/**
* Stop further callback invocations.
*

View File

@@ -9,6 +9,7 @@ import static edu.wpi.first.units.Units.Seconds;
import edu.wpi.first.hal.DriverStationJNI;
import edu.wpi.first.hal.HAL;
import edu.wpi.first.hal.NotifierJNI;
import edu.wpi.first.units.measure.Frequency;
import edu.wpi.first.units.measure.Time;
import java.util.PriorityQueue;
@@ -82,7 +83,7 @@ public class TimedRobot extends IterativeRobotBase {
/**
* Constructor for TimedRobot.
*
* @param period Period in seconds.
* @param period The period of the robot loop function.
*/
protected TimedRobot(double period) {
super(period);
@@ -93,6 +94,24 @@ public class TimedRobot extends IterativeRobotBase {
HAL.reportUsage("Framework", "TimedRobot");
}
/**
* Constructor for TimedRobot.
*
* @param period The period of the robot loop function.
*/
protected TimedRobot(Time period) {
this(period.in(Seconds));
}
/**
* Constructor for TimedRobot.
*
* @param frequency The frequency of the robot loop function.
*/
protected TimedRobot(Frequency frequency) {
this(frequency.asPeriod());
}
@Override
public void close() {
NotifierJNI.stopNotifier(m_notifier);

View File

@@ -4,6 +4,10 @@
package edu.wpi.first.wpilibj;
import static edu.wpi.first.units.Units.Seconds;
import edu.wpi.first.units.measure.Time;
/**
* A timer class.
*
@@ -46,10 +50,20 @@ public class Timer {
}
/**
* Pause the thread for a specified time. Pause the execution of the thread for a specified period
* of time given in seconds. Motors will continue to run at their last assigned values, and
* sensors will continue to update. Only the task containing the wait will pause until the wait
* time is expired.
* Pause the execution of the thread for a specified period of time. Motors will continue to run
* at their last assigned values, and sensors will continue to update. Only the task containing
* the wait will pause until the wait time is expired.
*
* @param period Length of time to pause
*/
public static void delay(final Time period) {
delay(period.in(Seconds));
}
/**
* Pause the execution of the thread for a specified period of time given in seconds. Motors will
* continue to run at their last assigned values, and sensors will continue to update. Only the
* task containing the wait will pause until the wait time is expired.
*
* @param seconds Length of time to pause
*/
@@ -137,7 +151,17 @@ public class Timer {
/**
* Check if the period specified has passed.
*
* @param seconds The period to check.
* @param period The period to check.
* @return Whether the period has passed.
*/
public boolean hasElapsed(Time period) {
return hasElapsed(period.in(Seconds));
}
/**
* Check if the period specified has passed.
*
* @param seconds The period to check in seconds.
* @return Whether the period has passed.
*/
public boolean hasElapsed(double seconds) {

View File

@@ -4,7 +4,10 @@
package edu.wpi.first.wpilibj;
import static edu.wpi.first.units.Units.Seconds;
import edu.wpi.first.hal.NotifierJNI;
import edu.wpi.first.units.measure.Time;
import java.io.Closeable;
import java.util.PriorityQueue;
import java.util.concurrent.locks.ReentrantLock;
@@ -55,6 +58,16 @@ public class Watchdog implements Closeable, Comparable<Watchdog> {
m_tracer = new Tracer();
}
/**
* Watchdog constructor.
*
* @param timeout The watchdog's timeout with microsecond resolution.
* @param callback This function is called when the timeout expires.
*/
public Watchdog(Time timeout, Runnable callback) {
this(timeout.in(Seconds), callback);
}
@Override
public void close() {
disable();

View File

@@ -4,9 +4,11 @@
package edu.wpi.first.wpilibj.event;
import static edu.wpi.first.units.Units.Seconds;
import static edu.wpi.first.util.ErrorMessages.requireNonNullParam;
import edu.wpi.first.math.filter.Debouncer;
import edu.wpi.first.units.measure.Time;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiFunction;
import java.util.function.BooleanSupplier;
@@ -167,7 +169,18 @@ public class BooleanEvent implements BooleanSupplier {
* Creates a new debounced event from this event - it will become active when this event has been
* active for longer than the specified period.
*
* @param seconds The debounce period.
* @param period The debounce period.
* @return The debounced event (rising edges debounced only).
*/
public BooleanEvent debounce(Time period) {
return debounce(period.in(Seconds));
}
/**
* Creates a new debounced event from this event - it will become active when this event has been
* active for longer than the specified period.
*
* @param seconds The debounce period in seconds.
* @return The debounced event (rising edges debounced only).
*/
public BooleanEvent debounce(double seconds) {
@@ -178,7 +191,19 @@ public class BooleanEvent implements BooleanSupplier {
* Creates a new debounced event from this event - it will become active when this event has been
* active for longer than the specified period.
*
* @param seconds The debounce period.
* @param period The debounce period.
* @param type The debounce type.
* @return The debounced event.
*/
public BooleanEvent debounce(Time period, Debouncer.DebounceType type) {
return debounce(period.in(Seconds), type);
}
/**
* Creates a new debounced event from this event - it will become active when this event has been
* active for longer than the specified period.
*
* @param seconds The debounce period in seconds.
* @param type The debounce type.
* @return The debounced event.
*/

View File

@@ -4,11 +4,14 @@
package edu.wpi.first.wpilibj.smartdashboard;
import static edu.wpi.first.units.Units.Meters;
import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.networktables.NTSendable;
import edu.wpi.first.networktables.NTSendableBuilder;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.units.measure.Distance;
import edu.wpi.first.util.sendable.SendableRegistry;
import java.util.ArrayList;
import java.util.List;
@@ -66,6 +69,17 @@ public class Field2d implements NTSendable, AutoCloseable {
m_objects.get(0).setPose(x, y, rotation);
}
/**
* Set the robot pose from x, y, and rotation.
*
* @param x X location
* @param y Y location
* @param rotation rotation
*/
public synchronized void setRobotPose(Distance x, Distance y, Rotation2d rotation) {
m_objects.get(0).setPose(x.in(Meters), y.in(Meters), rotation);
}
/**
* Get the robot pose.
*

View File

@@ -4,11 +4,14 @@
package edu.wpi.first.wpilibj.smartdashboard;
import static edu.wpi.first.units.Units.Meters;
import edu.wpi.first.math.geometry.Pose2d;
import edu.wpi.first.math.geometry.Rotation2d;
import edu.wpi.first.math.geometry.Translation2d;
import edu.wpi.first.math.trajectory.Trajectory;
import edu.wpi.first.networktables.DoubleArrayEntry;
import edu.wpi.first.units.measure.Distance;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -51,6 +54,17 @@ public class FieldObject2d implements AutoCloseable {
setPose(new Pose2d(x, y, rotation));
}
/**
* Set the pose from x, y, and rotation.
*
* @param x X location
* @param y Y location
* @param rotation rotation
*/
public synchronized void setPose(Distance x, Distance y, Rotation2d rotation) {
setPose(new Pose2d(x.in(Meters), y.in(Meters), rotation));
}
/**
* Get the pose.
*

View File

@@ -0,0 +1,25 @@
// 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.
package edu.wpi.first.wpilibj.snippets.profiledpidfeedforward;
import edu.wpi.first.wpilibj.RobotBase;
/**
* Do NOT add any static variables to this class, or any initialization at all. Unless you know what
* you are doing, do not modify this file except to change the parameter class to the startRobot
* call.
*/
public final class Main {
private Main() {}
/**
* Main initialization function. Do not perform any initialization here.
*
* <p>If you change your main robot class, change the parameter type.
*/
public static void main(String... args) {
RobotBase.startRobot(Robot::new);
}
}

View File

@@ -0,0 +1,51 @@
// 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.
package edu.wpi.first.wpilibj.snippets.profiledpidfeedforward;
import edu.wpi.first.math.controller.ProfiledPIDController;
import edu.wpi.first.math.controller.SimpleMotorFeedforward;
import edu.wpi.first.math.trajectory.TrapezoidProfile;
import edu.wpi.first.wpilibj.Encoder;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.motorcontrol.PWMSparkMax;
/**
* ProfiledPIDController with feedforward snippets for frc-docs.
* https://docs.wpilib.org/en/stable/docs/software/advanced-controls/controllers/profiled-pidcontroller.html
*/
public class Robot extends TimedRobot {
private final ProfiledPIDController m_controller =
new ProfiledPIDController(1.0, 0.0, 0.0, new TrapezoidProfile.Constraints(5.0, 10.0));
private final SimpleMotorFeedforward m_feedforward = new SimpleMotorFeedforward(0.5, 1.5, 0.3);
private final Encoder m_encoder = new Encoder(0, 1);
private final PWMSparkMax m_motor = new PWMSparkMax(0);
double m_lastSpeed;
/** Called once at the beginning of the robot program. */
public Robot() {
m_encoder.setDistancePerPulse(1.0 / 256.0);
}
/**
* Controls a simple motor's position using a SimpleMotorFeedforward and a ProfiledPIDController.
*
* @param goalPosition the desired position
*/
public void goToPosition(double goalPosition) {
double pidVal = m_controller.calculate(m_encoder.getDistance(), goalPosition);
m_motor.setVoltage(
pidVal
+ m_feedforward.calculateWithVelocities(
m_lastSpeed, m_controller.getSetpoint().velocity));
m_lastSpeed = m_controller.getSetpoint().velocity;
}
@Override
public void teleopPeriodic() {
// Example usage: move to position 10.0
goToPosition(10.0);
}
}

View File

@@ -160,5 +160,16 @@
"foldername": "onboardimu",
"gradlebase": "java",
"mainclass": "Main"
},
{
"name": "ProfiledPIDFeedforward",
"description": "Snippets of ProfiledPIDController with feedforward for frc-docs.",
"tags": [
"PID",
"Profiled PID"
],
"foldername": "profiledpidfeedforward",
"gradlebase": "java",
"mainclass": "Robot"
}
]

View File

@@ -19,8 +19,6 @@ generatedFileExclude {
src/main/native/include/unsupported/
src/main/native/thirdparty/
src/test/native/cpp/UnitsTest\.cpp$
src/test/native/cpp/drake/
src/test/native/include/drake/
src/generated/main/java/edu/wpi/first/math/proto
src/generated/main/native/cpp
@@ -43,6 +41,7 @@ includeOtherLibs {
^fmt/
^gcem/
^gtest/
^sleipnir/
^unsupported/
^wpi/
}

View File

@@ -308,6 +308,42 @@ public class DCMotor implements ProtobufSerializable, StructSerializable {
12, 9.37, 483, 2, Units.rotationsPerMinuteToRadiansPerSecond(5800), numMotors);
}
/**
* Return a gearbox of Kraken X44 brushless motors.
*
* @param numMotors Number of motors in the gearbox.
* @return a gearbox of Kraken X44 motors.
*/
public static DCMotor getKrakenX44(int numMotors) {
// From https://motors.ctr-electronics.com/dyno/dynometer-testing/
return new DCMotor(
12, 4.11, 279, 2, Units.rotationsPerMinuteToRadiansPerSecond(7758), numMotors);
}
/**
* Return a gearbox of Kraken X44 brushless motors with FOC (Field-Oriented Control) enabled.
*
* @param numMotors Number of motors in the gearbox.
* @return A gearbox of Kraken X44 FOC enabled motors.
*/
public static DCMotor getKrakenX44Foc(int numMotors) {
// From https://motors.ctr-electronics.com/dyno/dynometer-testing/
return new DCMotor(
12, 5.01, 329, 2, Units.rotationsPerMinuteToRadiansPerSecond(7368), numMotors);
}
/**
* Return a gearbox of Minion brushless motors.
*
* @param numMotors Number of motors in the gearbox.
* @return A gearbox of Minion motors.
*/
public static DCMotor getMinion(int numMotors) {
// From https://motors.ctr-electronics.com/dyno/dynometer-testing/
return new DCMotor(
12, 3.17, 211, 2, Units.rotationsPerMinuteToRadiansPerSecond(7704), numMotors);
}
/**
* Return a gearbox of Neo Vortex brushless motors.
*

View File

@@ -260,7 +260,7 @@ WPILIB_DLLEXPORT constexpr Eigen::Vector3d PoseTo3dVector(const Pose2d& pose) {
}
/**
* Converts a Pose2d into a vector of [x, y, std::cos(theta), std::sin(theta)].
* Converts a Pose2d into a vector of [x, y, cos(theta), sin(theta)].
*
* @param pose The pose that is being represented.
*

View File

@@ -91,7 +91,7 @@ class WPILIB_DLLEXPORT Ellipse2d {
auto a = units::math::max(m_xSemiAxis, m_ySemiAxis);
// Minor semi-axis
auto b = units::math::min(m_xSemiAxis, m_ySemiAxis); // NOLINT
auto b = units::math::min(m_xSemiAxis, m_ySemiAxis);
auto c = units::math::sqrt(a * a - b * b);
@@ -203,7 +203,9 @@ class WPILIB_DLLEXPORT Ellipse2d {
auto x = rotPoint.X() - m_center.X();
auto y = rotPoint.Y() - m_center.Y();
// NOLINTNEXTLINE (bugprone-integer-division)
return (x * x) / (m_xSemiAxis * m_xSemiAxis) +
// NOLINTNEXTLINE (bugprone-integer-division)
(y * y) / (m_ySemiAxis * m_ySemiAxis);
}
};

View File

@@ -296,8 +296,8 @@ class WPILIB_DLLEXPORT Quaternion {
// 𝑣⃗ = θ * v̂
// v̂ = 𝑣⃗ / θ
// 𝑞 = std::cos(θ/2) + std::sin(θ/2) * v̂
// 𝑞 = std::cos(θ/2) + std::sin(θ/2) / θ * 𝑣⃗
// 𝑞 = cos(θ/2) + sin(θ/2) * v̂
// 𝑞 = cos(θ/2) + sin(θ/2) / θ * 𝑣⃗
double theta = gcem::hypot(rvec(0), rvec(1), rvec(2));
double cos = gcem::cos(theta / 2);

View File

@@ -247,6 +247,31 @@ class WPILIB_DLLEXPORT DCMotor {
return DCMotor(12_V, 9.37_Nm, 483_A, 2_A, 5800_rpm, numMotors);
}
/**
* Return a gearbox of Kraken X44 brushless motors.
*/
static constexpr DCMotor KrakenX44(int numMotors = 1) {
// From https://motors.ctr-electronics.com/dyno/dynometer-testing/
return DCMotor(12_V, 4.11_Nm, 279_A, 2_A, 7758_rpm, numMotors);
}
/**
* Return a gearbox of Kraken X44 brushless motors with FOC (Field-Oriented
* Control) enabled.
*/
static constexpr DCMotor KrakenX44FOC(int numMotors = 1) {
// From https://motors.ctr-electronics.com/dyno/dynometer-testing/
return DCMotor(12_V, 5.01_Nm, 329_A, 2_A, 7368_rpm, numMotors);
}
/**
* Return a gearbox of Minion brushless motors.
*/
static constexpr DCMotor Minion(int numMotors = 1) {
// From https://motors.ctr-electronics.com/dyno/dynometer-testing/
return DCMotor(12_V, 3.17_Nm, 211_A, 2_A, 7704_rpm, numMotors);
}
/**
* Return a gearbox of Neo Vortex brushless motors.
*/

View File

@@ -1,249 +0,0 @@
---
Language: Cpp
BasedOnStyle: Google
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveShortCaseStatements:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCaseColons: false
AlignEscapedNewlines: Left
AlignOperands: Align
AlignTrailingComments:
Kind: Always
OverEmptyLines: 0
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterExternBlock: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakAfterAttributes: Always
BreakAfterJavaFieldAnnotations: false
BreakArrays: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Attach
BreakBeforeInlineASMColon: OnlyMultiline
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^<.*\.h>'
Priority: 1
SortPriority: 0
CaseSensitive: false
- Regex: '^<.*'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 3
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseBlocks: false
IndentCaseLabels: true
IndentExternBlock: AfterExternBlock
IndentGotoLabels: true
IndentPPDirectives: None
IndentRequiresClause: true
IndentWidth: 2
IndentWrappedFunctionNames: false
InsertBraces: false
InsertNewlineAtEOF: false
InsertTrailingCommas: None
IntegerLiteralSeparator:
Binary: 0
BinaryMinDigits: 0
Decimal: 0
DecimalMinDigits: 0
Hex: 0
HexMinDigits: 0
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
KeepEmptyLinesAtEOF: false
LambdaBodyIndentation: Signature
LineEnding: DeriveLF
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: NextLine
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyIndentedWhitespace: 0
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
PPIndentWidth: -1
QualifierAlignment: Leave
RawStringFormats:
- Language: Cpp
Delimiters:
- cc
- CC
- cpp
- Cpp
- CPP
- 'c++'
- 'C++'
CanonicalDelimiter: ''
BasedOnStyle: google
- Language: TextProto
Delimiters:
- pb
- PB
- proto
- PROTO
EnclosingFunctions:
- EqualsProto
- EquivToProto
- PARSE_PARTIAL_TEXT_PROTO
- PARSE_TEST_PROTO
- PARSE_TEXT_PROTO
- ParseTextOrDie
- ParseTextProtoOrDie
- ParseTestProto
- ParsePartialTestProto
CanonicalDelimiter: pb
BasedOnStyle: google
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RemoveParentheses: Leave
RemoveSemicolon: false
RequiresClausePosition: OwnLine
RequiresExpressionIndentation: OuterScope
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: false
SortJavaStaticImport: Before
SortUsingDeclarations: LexicographicNumeric
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeJsonColon: false
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: Never
SpacesInContainerLiterals: true
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParens: Never
SpacesInParensOptions:
InCStyleCasts: false
InConditionalStatements: false
InEmptyParentheses: false
Other: false
SpacesInSquareBrackets: false
Standard: c++20
TabWidth: 8
UseTab: Never
...

View File

@@ -1,74 +0,0 @@
Checks:
'bugprone-assert-side-effect,
bugprone-bool-pointer-implicit-conversion,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-forward-declaration-namespace,
bugprone-forwarding-reference-overload,
bugprone-inaccurate-erase,
bugprone-incorrect-roundings,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-self-assignment,
bugprone-unused-raii,
bugprone-virtual-near-miss,
cert-err52-cpp,
cert-err60-cpp,
cert-mem57-cpp,
cert-oop57-cpp,
cert-oop58-cpp,
clang-diagnostic-*,
-clang-diagnostic-deprecated-declarations,
-clang-diagnostic-#warnings,
-clang-diagnostic-pedantic,
clang-analyzer-*,
-clang-analyzer-core.uninitialized.UndefReturn,
-clang-analyzer-optin.cplusplus.UninitializedObject,
-clang-analyzer-optin.portability.UnixAPI,
-clang-analyzer-unix.Malloc,
-cppcoreguidelines-slicing,
google-build-namespaces,
google-explicit-constructor,
google-global-names-in-headers,
google-readability-avoid-underscore-in-googletest-name,
google-readability-casting,
google-runtime-operator,
misc-definitions-in-headers,
misc-misplaced-const,
misc-new-delete-overloads,
misc-non-copyable-objects,
modernize-avoid-bind,
modernize-concat-nested-namespaces,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-use-default-member-init,
modernize-use-noexcept,
modernize-use-nullptr,
modernize-use-override,
modernize-use-using,
readability-braces-around-statements'
FormatStyle: file

View File

@@ -1,23 +0,0 @@
cppHeaderFileInclude {
\.hpp$
}
cppSrcFileInclude {
\.cpp$
}
modifiableFileExclude {
\.patch$
\.png$
\.svg$
jormungandr/cpp/docstrings\.hpp$
jormungandr/py\.typed$
}
includeOtherLibs {
^Eigen/
^catch2/
^gch/
^nanobind/
^sleipnir/
}

View File

@@ -1 +0,0 @@
// Copyright (c) Sleipnir contributors

View File

@@ -1,14 +0,0 @@
cppHeaderFileInclude {
\.hpp$
}
cppSrcFileInclude {
\.cpp$
}
includeOtherLibs {
^Eigen/
^fmt/
^gch/
^wpi/
}

View File

@@ -1,13 +0,0 @@
cppHeaderFileInclude {
\.hpp$
}
cppSrcFileInclude {
\.cpp$
}
includeOtherLibs {
^Eigen/
^fmt/
^gch/
}

View File

@@ -192,11 +192,11 @@ TEST(LinearFilterOutputTest, CentralFiniteDifference) {
AssertCentralResults<1, 3>(
[](double x) {
// f(x) = std::sin(x)
// f(x) = sin(x)
return std::sin(x);
},
[](double x) {
// df/dx = std::cos(x)
// df/dx = cos(x)
return std::cos(x);
},
h, -20.0, 20.0);
@@ -225,11 +225,11 @@ TEST(LinearFilterOutputTest, CentralFiniteDifference) {
AssertCentralResults<2, 5>(
[](double x) {
// f(x) = std::sin(x)
// f(x) = sin(x)
return std::sin(x);
},
[](double x) {
// d²f/dx² = -std::sin(x)
// d²f/dx² = -sin(x)
return -std::sin(x);
},
h, -20.0, 20.0);
@@ -265,11 +265,11 @@ TEST(LinearFilterOutputTest, BackwardFiniteDifference) {
AssertBackwardResults<1, 2>(
[](double x) {
// f(x) = std::sin(x)
// f(x) = sin(x)
return std::sin(x);
},
[](double x) {
// df/dx = std::cos(x)
// df/dx = cos(x)
return std::cos(x);
},
h, -20.0, 20.0);
@@ -298,11 +298,11 @@ TEST(LinearFilterOutputTest, BackwardFiniteDifference) {
AssertBackwardResults<2, 4>(
[](double x) {
// f(x) = std::sin(x)
// f(x) = sin(x)
return std::sin(x);
},
[](double x) {
// d²f/dx² = -std::sin(x)
// d²f/dx² = -sin(x)
return -std::sin(x);
},
h, -20.0, 20.0);

View File

@@ -39,8 +39,7 @@ class SendableHelper {
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1442819
__attribute__((no_sanitize("vptr")))
#endif
constexpr SendableHelper&
operator=(SendableHelper&& rhs) {
constexpr SendableHelper& operator=(SendableHelper&& rhs) {
if (!std::is_constant_evaluated()) {
// it is safe to call Move() multiple times with the same rhs
SendableRegistry::Move(static_cast<Derived*>(this),