Merge branch 'main' into 2027

This commit is contained in:
Peter Johnson
2025-02-20 00:26:23 -08:00
123 changed files with 4634 additions and 2291 deletions

View File

@@ -47,7 +47,7 @@ class {{ ConsoleName }}Controller : public GenericHID,
{{ ConsoleName }}Controller& operator=({{ ConsoleName }}Controller&&) = default;
{% for stick in sticks %}
/**
* Get the {{ stick.NameParts[1] }} axis value of {{ stick.NameParts[0] }} side of the controller.
* Get the {{ stick.NameParts[1] }} axis value of {{ stick.NameParts[0] }} side of the controller. {{ stick.PositiveDirection }} is positive.
*
* @return the axis value.
*/

View File

@@ -45,28 +45,28 @@ class PS4Controller : public GenericHID,
PS4Controller& operator=(PS4Controller&&) = default;
/**
* Get the X axis value of left side of the controller.
* Get the X axis value of left side of the controller. Right is positive.
*
* @return the axis value.
*/
double GetLeftX() const;
/**
* Get the Y axis value of left side of the controller.
* Get the Y axis value of left side of the controller. Back is positive.
*
* @return the axis value.
*/
double GetLeftY() const;
/**
* Get the X axis value of right side of the controller.
* Get the X axis value of right side of the controller. Right is positive.
*
* @return the axis value.
*/
double GetRightX() const;
/**
* Get the Y axis value of right side of the controller.
* Get the Y axis value of right side of the controller. Back is positive.
*
* @return the axis value.
*/

View File

@@ -45,28 +45,28 @@ class PS5Controller : public GenericHID,
PS5Controller& operator=(PS5Controller&&) = default;
/**
* Get the X axis value of left side of the controller.
* Get the X axis value of left side of the controller. Right is positive.
*
* @return the axis value.
*/
double GetLeftX() const;
/**
* Get the Y axis value of left side of the controller.
* Get the Y axis value of left side of the controller. Back is positive.
*
* @return the axis value.
*/
double GetLeftY() const;
/**
* Get the X axis value of right side of the controller.
* Get the X axis value of right side of the controller. Right is positive.
*
* @return the axis value.
*/
double GetRightX() const;
/**
* Get the Y axis value of right side of the controller.
* Get the Y axis value of right side of the controller. Back is positive.
*
* @return the axis value.
*/

View File

@@ -45,28 +45,28 @@ class StadiaController : public GenericHID,
StadiaController& operator=(StadiaController&&) = default;
/**
* Get the X axis value of left side of the controller.
* Get the X axis value of left side of the controller. Right is positive.
*
* @return the axis value.
*/
double GetLeftX() const;
/**
* Get the X axis value of right side of the controller.
* Get the X axis value of right side of the controller. Right is positive.
*
* @return the axis value.
*/
double GetRightX() const;
/**
* Get the Y axis value of left side of the controller.
* Get the Y axis value of left side of the controller. Back is positive.
*
* @return the axis value.
*/
double GetLeftY() const;
/**
* Get the Y axis value of right side of the controller.
* Get the Y axis value of right side of the controller. Back is positive.
*
* @return the axis value.
*/

View File

@@ -45,28 +45,28 @@ class XboxController : public GenericHID,
XboxController& operator=(XboxController&&) = default;
/**
* Get the X axis value of left side of the controller.
* Get the X axis value of left side of the controller. Right is positive.
*
* @return the axis value.
*/
double GetLeftX() const;
/**
* Get the X axis value of right side of the controller.
* Get the X axis value of right side of the controller. Right is positive.
*
* @return the axis value.
*/
double GetRightX() const;
/**
* Get the Y axis value of left side of the controller.
* Get the Y axis value of left side of the controller. Back is positive.
*
* @return the axis value.
*/
double GetLeftY() const;
/**
* Get the Y axis value of right side of the controller.
* Get the Y axis value of right side of the controller. Back is positive.
*
* @return the axis value.
*/

View File

@@ -34,6 +34,13 @@ AddressableLED::AddressableLED(int port) : m_port{port} {
HAL_ReportUsage("IO", port, "AddressableLED");
}
void AddressableLED::SetColorOrder(AddressableLED::ColorOrder order) {
int32_t status = 0;
HAL_SetAddressableLEDColorOrder(
m_handle, static_cast<HAL_AddressableLEDColorOrder>(order), &status);
FRC_CheckErrorStatus(status, "Port {} Color order {}", m_port, order);
}
void AddressableLED::SetLength(int length) {
int32_t status = 0;
HAL_SetAddressableLEDLength(m_handle, length, &status);

View File

@@ -82,17 +82,18 @@ class Alert::SendableAlerts : public nt::NTSendable,
* @return the SendableAlerts for the group
*/
static SendableAlerts& ForGroup(std::string_view group) {
// Force initialization of SendableRegistry before our magic static to
// prevent incorrect destruction order.
wpi::SendableRegistry::EnsureInitialized();
static wpi::StringMap<Alert::SendableAlerts> groups;
auto [iter, exists] = groups.try_emplace(group);
SendableAlerts& sendable = iter->second;
if (!exists) {
frc::SmartDashboard::PutData(group, &iter->second);
SendableAlerts* salert = nullptr;
try {
auto* sendable = frc::SmartDashboard::GetData(group);
salert = dynamic_cast<SendableAlerts*>(sendable);
} catch (frc::RuntimeError&) {
}
return sendable;
if (!salert) {
// this leaks if ResetSmartDashboardInstance is called, but that's fine
salert = new Alert::SendableAlerts;
frc::SmartDashboard::PutData(group, salert);
}
return *salert;
}
private:

View File

@@ -119,5 +119,13 @@ double Joystick::GetMagnitude() const {
}
units::radian_t Joystick::GetDirection() const {
// https://docs.wpilib.org/en/stable/docs/software/basic-programming/coordinate-system.html#joystick-and-controller-coordinate-system
// A positive rotation around the X axis moves the joystick right, and a
// positive rotation around the Y axis moves the joystick backward. When
// treating them as translations, 0 radians is measured from the right
// direction, and angle increases clockwise.
//
// It's rotated 90 degrees CCW (y is negated and the arguments are reversed)
// so that 0 radians is forward.
return units::radian_t{std::atan2(GetX(), -GetY())};
}

View File

@@ -24,12 +24,27 @@ namespace frc {
* By default, the timing supports WS2812B and WS2815 LEDs, but is configurable
* using SetBitTiming()
*
* Some LEDs use a different color order than the default GRB. The color order
* is configurable using SetColorOrder().
*
* <p>Only 1 LED driver is currently supported by the roboRIO. However,
* multiple LED strips can be connected in series and controlled from the
* single driver.
*/
class AddressableLED {
public:
/**
* Order that color data is sent over the wire.
*/
enum ColorOrder {
kRGB = HAL_ALED_RGB, ///< RGB order
kRBG = HAL_ALED_RBG, ///< RBG order
kBGR = HAL_ALED_BGR, ///< BGR order
kBRG = HAL_ALED_BRG, ///< BRG order
kGBR = HAL_ALED_GBR, ///< GBR order
kGRB = HAL_ALED_GRB ///< GRB order. This is the default order.
};
class LEDData : public HAL_AddressableLEDData {
public:
LEDData() : LEDData(0, 0, 0) {}
@@ -95,6 +110,15 @@ class AddressableLED {
AddressableLED(AddressableLED&&) = default;
AddressableLED& operator=(AddressableLED&&) = default;
/**
* Sets the color order for this AddressableLED. The default order is GRB.
*
* This will take effect on the next call to SetData().
*
* @param order the color order
*/
void SetColorOrder(ColorOrder order);
/**
* Sets the length of the LED strip.
*
@@ -169,4 +193,9 @@ class AddressableLED {
hal::Handle<HAL_AddressableLEDHandle, HAL_FreeAddressableLED> m_handle;
int m_port;
};
constexpr auto format_as(AddressableLED::ColorOrder order) {
return static_cast<int32_t>(order);
}
} // namespace frc

View File

@@ -148,6 +148,7 @@ class Joystick : public GenericHID {
* Get the X value of the current joystick.
*
* This depends on the mapping of the joystick connected to the current port.
* On most joysticks, positive is to the right.
*/
double GetX() const;
@@ -155,6 +156,7 @@ class Joystick : public GenericHID {
* Get the Y value of the current joystick.
*
* This depends on the mapping of the joystick connected to the current port.
* On most joysticks, positive is to the back.
*/
double GetY() const;
@@ -244,7 +246,7 @@ class Joystick : public GenericHID {
BooleanEvent Top(EventLoop* loop) const;
/**
* Get the magnitude of the direction vector formed by the joystick's
* Get the magnitude of the vector formed by the joystick's
* current position relative to its origin.
*
* @return The magnitude of the direction vector
@@ -252,7 +254,9 @@ class Joystick : public GenericHID {
double GetMagnitude() const;
/**
* Get the direction of the vector formed by the joystick and its origin.
* Get the direction of the vector formed by the joystick and its origin. 0 is
* forward and clockwise is positive. (Straight right is π/2 radians or 90
* degrees.)
*
* @return The direction of the vector.
*/

View File

@@ -52,11 +52,11 @@ class LinearSystemSim {
* @param dt The time between updates.
*/
void Update(units::second_t dt) {
// Update x. By default, this is the linear system dynamics x_k+1 = Ax_k +
// Bu_k
// Update x. By default, this is the linear system dynamics xₖ₊₁ = Ax +
// Buₖ.
m_x = UpdateX(m_x, m_u, dt);
// y = Cx + Du
// y = Cx + Du
m_y = m_plant.CalculateY(m_x, m_u);
// Add noise. If the user did not pass a noise vector to the
@@ -115,7 +115,14 @@ class LinearSystemSim {
*
* @param state The new state.
*/
void SetState(const Vectord<States>& state) { m_x = state; }
void SetState(const Vectord<States>& state) {
m_x = state;
// Update the output to reflect the new state.
//
// yₖ = Cxₖ + Duₖ
m_y = m_plant.CalculateY(m_x, m_u);
}
protected:
/**

View File

@@ -33,8 +33,7 @@ class AlertsTest : public ::testing::Test {
std::string GetGroupName() {
const ::testing::TestInfo* testInfo =
::testing::UnitTest::GetInstance()->current_test_info();
return fmt::format("{}_{}", testInfo->test_suite_name(),
testInfo->test_case_name());
return fmt::format("{}_{}", testInfo->test_suite_name(), testInfo->name());
}
template <typename... Args>
@@ -80,7 +79,16 @@ class AlertsTest : public ::testing::Test {
#define EXPECT_STATE(type, ...) \
EXPECT_EQ(GetActiveAlerts(type), (std::vector<std::string>{__VA_ARGS__}))
TEST_F(AlertsTest, SetUnset) {
TEST_F(AlertsTest, SetUnsetSingle) {
auto one = MakeAlert("one", kInfo);
EXPECT_FALSE(IsAlertActive("one", kInfo));
one.Set(true);
EXPECT_TRUE(IsAlertActive("one", kInfo));
one.Set(false);
EXPECT_FALSE(IsAlertActive("one", kInfo));
}
TEST_F(AlertsTest, SetUnsetMultiple) {
auto one = MakeAlert("one", kError);
auto two = MakeAlert("two", kInfo);
EXPECT_FALSE(IsAlertActive("one", kError));

View File

@@ -44,6 +44,15 @@ TEST(ElevatorSimTest, StateSpaceSim) {
EXPECT_NEAR(controller.GetSetpoint(), sim.GetPosition().value(), 0.2);
}
TEST(ElevatorSimTest, InitialState) {
constexpr auto startingHeight = 0.5_m;
frc::sim::ElevatorSim sim(frc::DCMotor::KrakenX60(2), 20, 8_kg, 0.1_m, 0_m,
1_m, true, startingHeight, {0.01, 0.0});
EXPECT_DOUBLE_EQ(startingHeight.value(), sim.GetPosition().value());
EXPECT_DOUBLE_EQ(0, sim.GetVelocity().value());
}
TEST(ElevatorSimTest, MinMax) {
frc::sim::ElevatorSim sim(frc::DCMotor::Vex775Pro(4), 14.67, 8_kg, 0.75_in,
0_m, 1_m, true, 0_m, {0.01});

View File

@@ -21,3 +21,12 @@ TEST(SingleJointedArmTest, Disabled) {
// The arm should swing down.
EXPECT_NEAR(sim.GetAngle().value(), -std::numbers::pi / 2, 0.01);
}
TEST(SingleJointedArmTest, InitialState) {
constexpr auto startingAngle = 45_deg;
frc::sim::SingleJointedArmSim sim(frc::DCMotor::KrakenX60(2), 125, 3_kg_sq_m,
30_in, 0_deg, 90_deg, true, startingAngle);
EXPECT_EQ(startingAngle, sim.GetAngle());
EXPECT_DOUBLE_EQ(0, sim.GetVelocity().value());
}