diff --git a/examples/robot/DSGamepadChooser/robot.py b/examples/robot/DSGamepadChooser/robot.py new file mode 100644 index 000000000..c393d2174 --- /dev/null +++ b/examples/robot/DSGamepadChooser/robot.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +# +# 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. +# + +from hal import RobotMode +import wpilib +from wpilib.opmoderobot import OpModeRobot + + +class DoNothingTeleop(wpilib.PeriodicOpMode): + """A teleop opmode that intentionally does nothing.""" + + +class ScoreAuto(wpilib.PeriodicOpMode): + """An autonomous opmode with selectable scoring parameters.""" + + def __init__(self) -> None: + super().__init__() + wpilib.DriverStationDisplay.setMode(wpilib.DriverStationDisplay.Mode.Line) + self.chooser = wpilib.DSGamepadChooser(0) + self.chooser.addOptions("Target", ["High", "Mid", "Low"]) + self.chooser.addIntegerOptions("Delay", 0, 5, 1) + self.chooser.addDoubleOptions("Speed", 0.25, 1.0, 0.25) + self.target = "High" + self.delay = 0 + self.speed = 0.25 + + def disabledPeriodic(self) -> None: + self.chooser.update() + wpilib.DriverStationDisplay.updateLines() + + def start(self) -> None: + self.target = self.chooser.getSelected("Target") + self.delay = self.chooser.getSelectedInteger("Delay") + self.speed = self.chooser.getSelectedDouble("Speed") + + def periodic(self) -> None: + wpilib.DriverStationDisplay.addData("Selected Auto", "Score") + wpilib.DriverStationDisplay.addData("Target", self.target) + wpilib.DriverStationDisplay.addData("Delay", self.delay) + wpilib.DriverStationDisplay.addData("Speed", self.speed) + wpilib.DriverStationDisplay.updateLines() + + +class BalanceAuto(wpilib.PeriodicOpMode): + """An autonomous opmode with selectable balance parameters.""" + + def __init__(self) -> None: + super().__init__() + wpilib.DriverStationDisplay.setMode(wpilib.DriverStationDisplay.Mode.Line) + self.chooser = wpilib.DSGamepadChooser(0) + self.chooser.addOptions("Approach", ["Left", "Center", "Right"]) + self.chooser.addIntegerOptions("Attempts", 1, 3, 1) + self.chooser.addDoubleOptions("Turn Scale", 0.2, 1.0, 0.2) + self.approach = "Center" + self.attempts = 1 + self.turnScale = 0.5 + + def disabledPeriodic(self) -> None: + self.chooser.update() + wpilib.DriverStationDisplay.updateLines() + + def start(self) -> None: + self.approach = self.chooser.getSelected("Approach") + self.attempts = self.chooser.getSelectedInteger("Attempts") + self.turnScale = self.chooser.getSelectedDouble("Turn Scale") + + def periodic(self) -> None: + wpilib.DriverStationDisplay.addData("Selected Auto", "Balance") + wpilib.DriverStationDisplay.addData("Approach", self.approach) + wpilib.DriverStationDisplay.addData("Attempts", self.attempts) + wpilib.DriverStationDisplay.addData("Turn Scale", self.turnScale) + wpilib.DriverStationDisplay.updateLines() + + +class MyRobot(OpModeRobot): + def __init__(self) -> None: + super().__init__() + self.add_opmode(DoNothingTeleop, RobotMode.TELEOPERATED, "Do Nothing Teleop") + self.add_opmode(ScoreAuto, RobotMode.AUTONOMOUS, "Score Auto") + self.add_opmode(BalanceAuto, RobotMode.AUTONOMOUS, "Balance Auto") + self.publish_opmodes() diff --git a/examples/robot/examples.toml b/examples/robot/examples.toml index efef6ea1f..35494cfd9 100644 --- a/examples/robot/examples.toml +++ b/examples/robot/examples.toml @@ -15,6 +15,7 @@ base = [ "Encoder", "GettingStarted", "Gyro", + "DSGamepadChooser", "HatchbotInlined", "HatchbotTraditional", "MecanumBot", diff --git a/rdev.toml b/rdev.toml index ed5bb6c4a..32788dbc0 100644 --- a/rdev.toml +++ b/rdev.toml @@ -22,7 +22,7 @@ wrapper = "2027.0.0a6.post4" [params] -wpilib_bin_version = "2027.0.0-alpha-6-139-g34fee9a73" +wpilib_bin_version = "2027.0.0-alpha-6-167-gdb3a9c428" wpilib_bin_url = "https://frcmaven.wpi.edu/artifactory/development-2027" # wpilib_bin_url = "https://frcmaven.wpi.edu/artifactory/development-2027" diff --git a/subprojects/pyntcore/ntcore/src/py2value.h b/subprojects/pyntcore/ntcore/src/py2value.h index fce52c8ec..25d71bfed 100644 --- a/subprojects/pyntcore/ntcore/src/py2value.h +++ b/subprojects/pyntcore/ntcore/src/py2value.h @@ -1,6 +1,7 @@ #pragma once -#include +#include + #include #include "wpi/nt/NetworkTableType.hpp" @@ -18,7 +19,7 @@ py::function valueFactoryByType(wpi::nt::NetworkTableType type); inline void ensure_value_is(NT_Type expected, wpi::nt::Value* v) { if (v->type() != expected) { - throw py::value_error(fmt::format("Value type is {}, not {}", + throw py::value_error(std::format("Value type is {}, not {}", nttype2str(v->type()), nttype2str(expected))); } diff --git a/subprojects/robotpy-commands-v2/commands2/commandscheduler.py b/subprojects/robotpy-commands-v2/commands2/commandscheduler.py index 16986c7cc..3da8d9de3 100644 --- a/subprojects/robotpy-commands-v2/commands2/commandscheduler.py +++ b/subprojects/robotpy-commands-v2/commands2/commandscheduler.py @@ -100,9 +100,7 @@ def __init__(self) -> None: self._in_run_loop = False self._to_schedule: Dict[Command, None] = {} - # python: to_cancel_interruptors stored in _to_cancel dict self._to_cancel: Dict[Command, Optional[Command]] = {} - # self._to_cancel_interruptors: List[Optional[Command]] = [] self._ending_commands: Set[Command] = set() self._watchdog = Watchdog(TimedRobot.DEFAULT_PERIOD, lambda: None) diff --git a/subprojects/robotpy-commands-v2/tools/hids/first_ds_hids.json b/subprojects/robotpy-commands-v2/tools/hids/first_ds_hids.json index 0908002cb..df2c4223a 100644 --- a/subprojects/robotpy-commands-v2/tools/hids/first_ds_hids.json +++ b/subprojects/robotpy-commands-v2/tools/hids/first_ds_hids.json @@ -231,7 +231,7 @@ }, { "ClassName": "GameCube", - "HIDType": "STANDARD", + "HIDType": "GAMECUBE", "axes": { "leftX": 0, "leftY": 1, @@ -335,7 +335,7 @@ }, { "ClassName": "Steam", - "HIDType": "STANDARD", + "HIDType": "STEAM", "axes": { "leftX": 0, "leftY": 1, diff --git a/subprojects/robotpy-cscore/pyproject.toml b/subprojects/robotpy-cscore/pyproject.toml index 999e04808..096aa50bd 100644 --- a/subprojects/robotpy-cscore/pyproject.toml +++ b/subprojects/robotpy-cscore/pyproject.toml @@ -44,7 +44,7 @@ version_file = "cscore/version.py" artifact_id = "cscore-cpp" group_id = "org.wpilib.cscore" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" staticlibs = ["cscore"] extract_to = "lib" @@ -53,7 +53,7 @@ extract_to = "lib" artifact_id = "cameraserver-cpp" group_id = "org.wpilib.cameraserver" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" staticlibs = ["cameraserver"] extract_to = "lib" diff --git a/subprojects/robotpy-halsim-ds-socket/pyproject.toml b/subprojects/robotpy-halsim-ds-socket/pyproject.toml index cc6f919a9..913c48cca 100644 --- a/subprojects/robotpy-halsim-ds-socket/pyproject.toml +++ b/subprojects/robotpy-halsim-ds-socket/pyproject.toml @@ -30,7 +30,7 @@ version_file = "halsim_ds_socket/version.py" artifact_id = "halsim_ds_socket" group_id = "org.wpilib.halsim" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" use_headers = false extract_to = "halsim_ds_socket" diff --git a/subprojects/robotpy-halsim-ws/pyproject.toml b/subprojects/robotpy-halsim-ws/pyproject.toml index 19866ce05..9c64ce64d 100644 --- a/subprojects/robotpy-halsim-ws/pyproject.toml +++ b/subprojects/robotpy-halsim-ws/pyproject.toml @@ -35,7 +35,7 @@ version_file = "halsim_ws/version.py" artifact_id = "halsim_ws_server" group_id = "org.wpilib.halsim" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" use_headers = false extract_to = "halsim_ws/server" @@ -45,7 +45,7 @@ libs = ["halsim_ws_server"] artifact_id = "halsim_ws_client" group_id = "org.wpilib.halsim" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" use_headers = false extract_to = "halsim_ws/client" diff --git a/subprojects/robotpy-native-apriltag/pyproject.toml b/subprojects/robotpy-native-apriltag/pyproject.toml index 566608eb2..093156e4c 100644 --- a/subprojects/robotpy-native-apriltag/pyproject.toml +++ b/subprojects/robotpy-native-apriltag/pyproject.toml @@ -27,7 +27,7 @@ packages = ["src/native"] artifact_id = "apriltag-cpp" group_id = "org.wpilib.apriltag" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/apriltag" libs = ["apriltag"] diff --git a/subprojects/robotpy-native-datalog/pyproject.toml b/subprojects/robotpy-native-datalog/pyproject.toml index ab5eca40d..2a18b8a37 100644 --- a/subprojects/robotpy-native-datalog/pyproject.toml +++ b/subprojects/robotpy-native-datalog/pyproject.toml @@ -26,7 +26,7 @@ packages = ["src/native"] artifact_id = "datalog-cpp" group_id = "org.wpilib.datalog" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/datalog" libs = ["datalog"] diff --git a/subprojects/robotpy-native-halsim-gui/pyproject.toml b/subprojects/robotpy-native-halsim-gui/pyproject.toml index dbe19c644..8a93d8a80 100644 --- a/subprojects/robotpy-native-halsim-gui/pyproject.toml +++ b/subprojects/robotpy-native-halsim-gui/pyproject.toml @@ -29,7 +29,7 @@ packages = ["src/native"] artifact_id = "halsim_gui" group_id = "org.wpilib.halsim" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" use_headers = true extract_to = "src/native/halsim_gui" diff --git a/subprojects/robotpy-native-ntcore/pyproject.toml b/subprojects/robotpy-native-ntcore/pyproject.toml index a3a427677..5b3f02bf0 100644 --- a/subprojects/robotpy-native-ntcore/pyproject.toml +++ b/subprojects/robotpy-native-ntcore/pyproject.toml @@ -29,7 +29,7 @@ packages = ["src/native"] artifact_id = "ntcore-cpp" group_id = "org.wpilib.ntcore" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/ntcore" libs = ["ntcore"] diff --git a/subprojects/robotpy-native-romi/pyproject.toml b/subprojects/robotpy-native-romi/pyproject.toml index 804e1b481..557bceb82 100644 --- a/subprojects/robotpy-native-romi/pyproject.toml +++ b/subprojects/robotpy-native-romi/pyproject.toml @@ -25,7 +25,7 @@ packages = ["src/native"] artifact_id = "romiVendordep-cpp" group_id = "org.wpilib.romiVendordep" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/romi" libs = ["romiVendordep"] diff --git a/subprojects/robotpy-native-wpihal/pyproject.toml b/subprojects/robotpy-native-wpihal/pyproject.toml index 52c0f4ae8..aae31cc6d 100644 --- a/subprojects/robotpy-native-wpihal/pyproject.toml +++ b/subprojects/robotpy-native-wpihal/pyproject.toml @@ -27,7 +27,7 @@ packages = ["src/native"] artifact_id = "hal-cpp" group_id = "org.wpilib.hal" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/wpihal" libs = ["wpiHal"] diff --git a/subprojects/robotpy-native-wpilib/pyproject.toml b/subprojects/robotpy-native-wpilib/pyproject.toml index 20fa8899b..e3a3a12c2 100644 --- a/subprojects/robotpy-native-wpilib/pyproject.toml +++ b/subprojects/robotpy-native-wpilib/pyproject.toml @@ -33,7 +33,7 @@ packages = ["src/native"] artifact_id = "wpilibc-cpp" group_id = "org.wpilib.wpilibc" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/wpilib" libs = ["wpilibc"] diff --git a/subprojects/robotpy-native-wpimath/pyproject.toml b/subprojects/robotpy-native-wpimath/pyproject.toml index c99a58be1..f848ef9fc 100644 --- a/subprojects/robotpy-native-wpimath/pyproject.toml +++ b/subprojects/robotpy-native-wpimath/pyproject.toml @@ -25,7 +25,7 @@ packages = ["src/native"] artifact_id = "wpimath-cpp" group_id = "org.wpilib.wpimath" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/wpimath" libs = ["wpimath"] diff --git a/subprojects/robotpy-native-wpinet/pyproject.toml b/subprojects/robotpy-native-wpinet/pyproject.toml index 89ab4afd6..816c58820 100644 --- a/subprojects/robotpy-native-wpinet/pyproject.toml +++ b/subprojects/robotpy-native-wpinet/pyproject.toml @@ -25,7 +25,7 @@ packages = ["src/native"] artifact_id = "wpinet-cpp" group_id = "org.wpilib.wpinet" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/wpinet" libs = ["wpinet"] diff --git a/subprojects/robotpy-native-wpiutil/pyproject.toml b/subprojects/robotpy-native-wpiutil/pyproject.toml index c07dcf7f1..9a498df79 100644 --- a/subprojects/robotpy-native-wpiutil/pyproject.toml +++ b/subprojects/robotpy-native-wpiutil/pyproject.toml @@ -24,7 +24,7 @@ packages = ["src/native"] artifact_id = "wpiutil-cpp" group_id = "org.wpilib.wpiutil" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/wpiutil" libs = ["wpiutil"] diff --git a/subprojects/robotpy-native-xrp/pyproject.toml b/subprojects/robotpy-native-xrp/pyproject.toml index ffbc3ff7a..87b826d18 100644 --- a/subprojects/robotpy-native-xrp/pyproject.toml +++ b/subprojects/robotpy-native-xrp/pyproject.toml @@ -25,7 +25,7 @@ packages = ["src/native"] artifact_id = "xrpVendordep-cpp" group_id = "org.wpilib.xrpVendordep" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" extract_to = "src/native/xrp" libs = ["xrpVendordep"] diff --git a/subprojects/robotpy-wpilib/pyproject.toml b/subprojects/robotpy-wpilib/pyproject.toml index 09edde8b4..2677094e5 100644 --- a/subprojects/robotpy-wpilib/pyproject.toml +++ b/subprojects/robotpy-wpilib/pyproject.toml @@ -124,6 +124,7 @@ POVDirection = "wpi/driverstation/POVDirection.hpp" RobotState = "wpi/driverstation/RobotState.hpp" TouchpadFinger = "wpi/driverstation/TouchpadFinger.hpp" Gamepad = "wpi/driverstation/Gamepad.hpp" +DSGamepadChooser = "wpi/driverstation/DSGamepadChooser.hpp" GenericHID = "wpi/driverstation/GenericHID.hpp" HIDDevice = "wpi/driverstation/HIDDevice.hpp" Joystick = "wpi/driverstation/Joystick.hpp" diff --git a/subprojects/robotpy-wpilib/semiwrap/DSGamepadChooser.yml b/subprojects/robotpy-wpilib/semiwrap/DSGamepadChooser.yml new file mode 100644 index 000000000..8f6067426 --- /dev/null +++ b/subprojects/robotpy-wpilib/semiwrap/DSGamepadChooser.yml @@ -0,0 +1,48 @@ +extra_includes: +- pybind11/stl.h +- wpi/driverstation/Gamepad.hpp + +classes: + wpi::DSGamepadChooser: + methods: + DSGamepadChooser: + overloads: + int: + Gamepad&: + keepalive: + - [1, 2] + GetGamepad: + overloads: + "": + return_value_policy: reference_internal + '[const]': + ignore: true + AddOptions: + overloads: + std::string_view, std::vector: + return_value_policy: reference_internal + std::string_view, std::initializer_list: + ignore: true + AddIntegerOptions: + return_value_policy: reference_internal + AddDoubleOptions: + return_value_policy: reference_internal + Update: + GetSelected: + GetSelectedInteger: + GetSelectedDouble: + GetSelectedIndex: + GetSelectableNames: + GetSelectedSelectable: + overloads: + "": + return_value_policy: reference_internal + '[const]': + ignore: true + + wpi::DSGamepadChooser::GamepadSelectable: + methods: + GetName: + GetOptions: + GetSelected: + GetSelectedIndex: diff --git a/subprojects/robotpy-wpilib/semiwrap/ExpansionHubMotor.yml b/subprojects/robotpy-wpilib/semiwrap/ExpansionHubMotor.yml index 1ecd7b1b7..8adb28566 100644 --- a/subprojects/robotpy-wpilib/semiwrap/ExpansionHubMotor.yml +++ b/subprojects/robotpy-wpilib/semiwrap/ExpansionHubMotor.yml @@ -7,8 +7,6 @@ classes: SetPositionSetpoint: SetVelocitySetpoint: SetEnabled: - SetFloatOn0: - rename: set_float_on_0 GetCurrent: SetDistancePerCount: GetEncoderVelocity: @@ -17,8 +15,10 @@ classes: ResetEncoder: IsHubConnected: Follow: + Unfollow: GetVelocityConstants: GetPositionConstants: - Unfollow: + SetNeutralMode: enums: + NeutralMode: FollowDirection: diff --git a/subprojects/robotpy-wpilib/semiwrap/FieldObject2d.yml b/subprojects/robotpy-wpilib/semiwrap/FieldObject2d.yml index 3a0cc15dc..acce1b6ee 100644 --- a/subprojects/robotpy-wpilib/semiwrap/FieldObject2d.yml +++ b/subprojects/robotpy-wpilib/semiwrap/FieldObject2d.yml @@ -1,6 +1,6 @@ extra_includes: - wpi/math/trajectory/DifferentialTrajectory.hpp -- wpi/math/trajectory/SplineTrajectory.hpp +- wpi/math/trajectory/DrivetrainSplineTrajectory.hpp - wpi/math/trajectory/HolonomicTrajectory.hpp - wpi/math/trajectory/Trajectory.hpp @@ -22,9 +22,9 @@ classes: ignore: true SetTrajectory: template_impls: - - [wpi::math::SplineSample] - [wpi::math::DifferentialSample] - - [wpi::math::TrajectorySample] + - [wpi::math::DrivetrainSplineSample] + - [wpi::math::HolonomicSample] GetPoses: overloads: '[const]': diff --git a/subprojects/robotpy-wpilib/semiwrap/simulation/AddressableLEDSim.yml b/subprojects/robotpy-wpilib/semiwrap/simulation/AddressableLEDSim.yml index 6794bc0cd..09c2e9192 100644 --- a/subprojects/robotpy-wpilib/semiwrap/simulation/AddressableLEDSim.yml +++ b/subprojects/robotpy-wpilib/semiwrap/simulation/AddressableLEDSim.yml @@ -37,7 +37,7 @@ classes: cpp_code: | [](wpi::sim::AddressableLEDSim &self, std::span &data) { if (static_cast(data.size()) != self.GetLength()) { - std::string msg = fmt::format("data must have length {} (got {})", self.GetLength(), data.size()); + std::string msg = std::format("data must have length {} (got {})", self.GetLength(), data.size()); throw py::value_error(msg); } self.SetData(data.data()); diff --git a/subprojects/robotpy-wpilib/tests/driverstation/test_ds_gamepad_chooser.py b/subprojects/robotpy-wpilib/tests/driverstation/test_ds_gamepad_chooser.py new file mode 100644 index 000000000..4708b5213 --- /dev/null +++ b/subprojects/robotpy-wpilib/tests/driverstation/test_ds_gamepad_chooser.py @@ -0,0 +1,102 @@ +import pytest + +from wpilib import DriverStationDisplay, Gamepad, DSGamepadChooser +from wpilib.simulation import DriverStationSim, GamepadSim + + +@pytest.fixture(autouse=True) +def reset_driver_station_sim(): + DriverStationSim.reset_data() + DriverStationDisplay.set_mode(DriverStationDisplay.Mode.LINE) + + +def tap(sim: GamepadSim, chooser: DSGamepadChooser, button: Gamepad.Button) -> None: + sim.set_button(button, True) + sim.notify_new_data() + chooser.update() + + sim.set_button(button, False) + sim.notify_new_data() + chooser.update() + + +def test_add_options_selects_first_option_by_default() -> None: + chooser = DSGamepadChooser(0) + + selectable = chooser.add_options("Auto", ["Left", "Center", "Right"]) + + assert selectable.get_selected() == "Left" + assert chooser.get_selected("Auto") == "Left" + assert chooser.get_selected_index("Auto") == 0 + assert chooser.get_selectable_names() == ["Auto"] + assert chooser.get_selected_selectable().get_name() == selectable.get_name() + + +def test_add_integer_options_creates_range() -> None: + chooser = DSGamepadChooser(0) + + selectable = chooser.add_integer_options("Delay", -2, 3, 2) + + assert selectable.get_options() == ["-2", "0", "2", "3"] + assert selectable.get_selected() == "-2" + assert chooser.get_selected_integer("Delay") == -2 + + +def test_add_double_options_creates_range() -> None: + chooser = DSGamepadChooser(0) + + selectable = chooser.add_double_options("Speed", 0.0, 1.0, 0.3) + + assert selectable.get_options() == ["0.0", "0.3", "0.6", "0.9", "1.0"] + assert selectable.get_selected() == "0.0" + assert chooser.get_selected_double("Speed") == pytest.approx(0.0) + + +def test_dpad_moves_between_selectables_and_options() -> None: + gamepad = Gamepad(0) + sim = GamepadSim(gamepad) + chooser = DSGamepadChooser(gamepad) + auto = chooser.add_options("Auto", ["Left", "Center", "Right"]) + delay = chooser.add_integer_options("Delay", 0, 2, 1) + + tap(sim, chooser, Gamepad.Button.DPAD_RIGHT) + assert auto.get_selected() == "Center" + assert delay.get_selected() == "0" + assert chooser.get_selected_selectable().get_name() == "Auto" + + tap(sim, chooser, Gamepad.Button.DPAD_DOWN) + assert chooser.get_selected_selectable().get_name() == "Delay" + + tap(sim, chooser, Gamepad.Button.DPAD_RIGHT) + assert delay.get_selected() == "1" + assert auto.get_selected() == "Center" + + tap(sim, chooser, Gamepad.Button.DPAD_LEFT) + tap(sim, chooser, Gamepad.Button.DPAD_LEFT) + assert delay.get_selected() == "2" + + tap(sim, chooser, Gamepad.Button.DPAD_UP) + assert chooser.get_selected_selectable().get_name() == "Auto" + + tap(sim, chooser, Gamepad.Button.DPAD_LEFT) + tap(sim, chooser, Gamepad.Button.DPAD_LEFT) + assert auto.get_selected() == "Right" + + +def test_rejects_invalid_selectables() -> None: + chooser = DSGamepadChooser(0) + + with pytest.raises(ValueError): + chooser.add_options("", ["A"]) + with pytest.raises(ValueError): + chooser.add_options("Empty", []) + with pytest.raises(ValueError): + chooser.add_integer_options("Bad", 0, 2, 0) + with pytest.raises(ValueError): + chooser.add_double_options("Bad", 0.0, 1.0, 0.0) + + chooser.add_options("Auto", ["A"]) + with pytest.raises(ValueError): + chooser.add_options("Auto", ["B"]) + with pytest.raises(ValueError): + chooser.get_selected("Missing") diff --git a/subprojects/robotpy-wpilib/wpilib/__init__.py b/subprojects/robotpy-wpilib/wpilib/__init__.py index 41736e82c..4be0edb19 100644 --- a/subprojects/robotpy-wpilib/wpilib/__init__.py +++ b/subprojects/robotpy-wpilib/wpilib/__init__.py @@ -44,6 +44,7 @@ FieldObject2d, GameCubeController, Gamepad, + DSGamepadChooser, GenericHID, HIDDevice, I2C, @@ -173,6 +174,7 @@ "FieldObject2d", "GameCubeController", "Gamepad", + "DSGamepadChooser", "GenericHID", "HIDDevice", "I2C", diff --git a/subprojects/robotpy-wpimath/pyproject.toml b/subprojects/robotpy-wpimath/pyproject.toml index 908ef3988..570a30b87 100644 --- a/subprojects/robotpy-wpimath/pyproject.toml +++ b/subprojects/robotpy-wpimath/pyproject.toml @@ -1579,10 +1579,11 @@ NumericalJacobian = "wpi/math/system/NumericalJacobian.hpp" # wpi/math/trajectory DifferentialSample = "wpi/math/trajectory/DifferentialSample.hpp" DifferentialTrajectory = "wpi/math/trajectory/DifferentialTrajectory.hpp" +DrivetrainSplineSample = "wpi/math/trajectory/DrivetrainSplineSample.hpp" +DrivetrainSplineTrajectory = "wpi/math/trajectory/DrivetrainSplineTrajectory.hpp" ExponentialProfile = "wpi/math/trajectory/ExponentialProfile.hpp" +HolonomicSample = "wpi/math/trajectory/HolonomicSample.hpp" HolonomicTrajectory = "wpi/math/trajectory/HolonomicTrajectory.hpp" -SplineSample = "wpi/math/trajectory/SplineSample.hpp" -SplineTrajectory = "wpi/math/trajectory/SplineTrajectory.hpp" Trajectory = "wpi/math/trajectory/Trajectory.hpp" TrajectoryConfig = "wpi/math/trajectory/TrajectoryConfig.hpp" TrajectoryGenerator = "wpi/math/trajectory/TrajectoryGenerator.hpp" diff --git a/subprojects/robotpy-wpimath/semiwrap/DifferentialSample.yml b/subprojects/robotpy-wpimath/semiwrap/DifferentialSample.yml index 3671e0780..1d19113ea 100644 --- a/subprojects/robotpy-wpimath/semiwrap/DifferentialSample.yml +++ b/subprojects/robotpy-wpimath/semiwrap/DifferentialSample.yml @@ -15,20 +15,19 @@ classes: wpi::math::DifferentialSample: force_no_trampoline: true attributes: - leftSpeed: - rightSpeed: + leftVelocity: + rightVelocity: methods: DifferentialSample: overloads: "": - const TrajectorySample&, wpi::units::meters_per_second_t, wpi::units::meters_per_second_t: - const TrajectorySample&, const DifferentialDriveKinematics&: - const SplineSample&, const DifferentialDriveKinematics&: ? wpi::units::second_t, const Pose2d&, const ChassisVelocities&, const ChassisAccelerations&, wpi::units::meters_per_second_t, wpi::units::meters_per_second_t : ? wpi::units::second_t, const Pose2d&, const ChassisVelocities&, const ChassisAccelerations&, const DifferentialDriveKinematics& : + const HolonomicSample&, wpi::units::meters_per_second_t, wpi::units::meters_per_second_t: + const HolonomicSample&, const DifferentialDriveKinematics&: + const DrivetrainSplineSample&, const DifferentialDriveKinematics&: Transform: RelativeTo: - WithNewTimestamp: operator==: diff --git a/subprojects/robotpy-wpimath/semiwrap/SplineSample.yml b/subprojects/robotpy-wpimath/semiwrap/DrivetrainSplineSample.yml similarity index 84% rename from subprojects/robotpy-wpimath/semiwrap/SplineSample.yml rename to subprojects/robotpy-wpimath/semiwrap/DrivetrainSplineSample.yml index f45c49a1c..659ee60a9 100644 --- a/subprojects/robotpy-wpimath/semiwrap/SplineSample.yml +++ b/subprojects/robotpy-wpimath/semiwrap/DrivetrainSplineSample.yml @@ -4,21 +4,20 @@ functions: from_json: ignore: true classes: - wpi::math::SplineSample: + wpi::math::DrivetrainSplineSample: force_no_trampoline: true attributes: curvature: methods: - SplineSample: + DrivetrainSplineSample: overloads: "": ? wpi::units::second_t, const Pose2d&, wpi::units::meters_per_second_t, wpi::units::meters_per_second_squared_t, wpi::units::curvature_t : wpi::units::second_t, const Pose2d&, const ChassisVelocities&, const ChassisAccelerations&, wpi::units::curvature_t: - const TrajectorySample&: + const HolonomicSample&: ForwardVelocity: ForwardAcceleration: Transform: RelativeTo: - WithNewTimestamp: operator==: diff --git a/subprojects/robotpy-wpimath/semiwrap/SplineTrajectory.yml b/subprojects/robotpy-wpimath/semiwrap/DrivetrainSplineTrajectory.yml similarity index 51% rename from subprojects/robotpy-wpimath/semiwrap/SplineTrajectory.yml rename to subprojects/robotpy-wpimath/semiwrap/DrivetrainSplineTrajectory.yml index 1d3008b8c..904f1fbf9 100644 --- a/subprojects/robotpy-wpimath/semiwrap/SplineTrajectory.yml +++ b/subprojects/robotpy-wpimath/semiwrap/DrivetrainSplineTrajectory.yml @@ -1,11 +1,11 @@ classes: - wpi::math::SplineTrajectory: + wpi::math::DrivetrainSplineTrajectory: force_no_trampoline: true methods: - SplineTrajectory: + DrivetrainSplineTrajectory: overloads: - std::vector: - std::initializer_list: + std::vector: + std::initializer_list: ignore: true TransformBy: RelativeTo: diff --git a/subprojects/robotpy-wpimath/semiwrap/HolonomicSample.yml b/subprojects/robotpy-wpimath/semiwrap/HolonomicSample.yml new file mode 100644 index 000000000..b9699409f --- /dev/null +++ b/subprojects/robotpy-wpimath/semiwrap/HolonomicSample.yml @@ -0,0 +1,29 @@ +functions: + to_json: + overloads: + wpi::util::json&, const HolonomicSample&: + ignore: true + wpi::util::json&, const std::vector&: + ignore: true + from_json: + overloads: + const wpi::util::json&, HolonomicSample&: + ignore: true + const wpi::util::json&, std::vector&: + ignore: true + KinematicInterpolate: +classes: + wpi::math::HolonomicSample: + force_no_trampoline: true + attributes: + pose: + velocity: + acceleration: + methods: + HolonomicSample: + overloads: + "": + wpi::units::second_t, const Pose2d&, const ChassisVelocities&, const ChassisAccelerations&: + operator==: + Transform: + RelativeTo: diff --git a/subprojects/robotpy-wpimath/semiwrap/LTVUnicycleController.yml b/subprojects/robotpy-wpimath/semiwrap/LTVUnicycleController.yml index b5393555f..f949a8887 100644 --- a/subprojects/robotpy-wpimath/semiwrap/LTVUnicycleController.yml +++ b/subprojects/robotpy-wpimath/semiwrap/LTVUnicycleController.yml @@ -13,5 +13,5 @@ classes: Calculate: overloads: const Pose2d&, const Pose2d&, wpi::units::meters_per_second_t, wpi::units::radians_per_second_t: - const Pose2d&, const SplineSample&: + const Pose2d&, const HolonomicSample&: SetEnabled: diff --git a/subprojects/robotpy-wpimath/semiwrap/Trajectory.yml b/subprojects/robotpy-wpimath/semiwrap/Trajectory.yml index 172e7dc5f..2e7e06382 100644 --- a/subprojects/robotpy-wpimath/semiwrap/Trajectory.yml +++ b/subprojects/robotpy-wpimath/semiwrap/Trajectory.yml @@ -1,7 +1,7 @@ extra_includes: - geometryToString.h -- wpi/math/trajectory/SplineSample.hpp - wpi/math/trajectory/DifferentialSample.hpp +- wpi/math/trajectory/DrivetrainSplineSample.hpp classes: wpi::math::Trajectory: @@ -30,15 +30,15 @@ classes: m_duration: templates: - SplineTrajectoryBase: - qualname: wpi::math::Trajectory - params: - - wpi::math::SplineSample DifferentialTrajectoryBase: qualname: wpi::math::Trajectory params: - wpi::math::DifferentialSample + DrivetrainSplineTrajectoryBase: + qualname: wpi::math::Trajectory + params: + - wpi::math::DrivetrainSplineSample HolonomicTrajectoryBase: qualname: wpi::math::Trajectory params: - - wpi::math::TrajectorySample + - wpi::math::HolonomicSample diff --git a/subprojects/robotpy-wpimath/semiwrap/TrajectorySample.yml b/subprojects/robotpy-wpimath/semiwrap/TrajectorySample.yml index 9c8c9fb4f..1e6b3b66b 100644 --- a/subprojects/robotpy-wpimath/semiwrap/TrajectorySample.yml +++ b/subprojects/robotpy-wpimath/semiwrap/TrajectorySample.yml @@ -1,5 +1,4 @@ functions: - KinematicInterpolate: to_json: overloads: wpi::util::json&, const TrajectorySample&: @@ -14,17 +13,12 @@ functions: ignore: true classes: wpi::math::TrajectorySample: + force_no_trampoline: true attributes: - timestamp: - pose: - velocity: - acceleration: + time: methods: TrajectorySample: overloads: "": - wpi::units::second_t, const Pose2d&, const ChassisVelocities&, const ChassisAccelerations&: + wpi::units::second_t: operator==: - Transform: - RelativeTo: - WithNewTimestamp: diff --git a/subprojects/robotpy-wpimath/tests/test_trajectory.py b/subprojects/robotpy-wpimath/tests/test_trajectory.py index 8c406265c..4740ceada 100644 --- a/subprojects/robotpy-wpimath/tests/test_trajectory.py +++ b/subprojects/robotpy-wpimath/tests/test_trajectory.py @@ -2,6 +2,7 @@ from wpimath import ( CubicHermiteSpline, + DrivetrainSplineTrajectory, Ellipse2d, EllipticalRegionConstraint, MaxVelocityConstraint, @@ -10,9 +11,8 @@ RectangularRegionConstraint, Rotation2d, SplineHelper, - TrajectoryConstraint, - SplineTrajectory, TrajectoryConfig, + TrajectoryConstraint, TrajectoryGenerator, TrajectoryParameterizer, Transform2d, @@ -20,7 +20,7 @@ ) -def get_test_trajectory(config: TrajectoryConfig) -> SplineTrajectory: +def get_test_trajectory(config: TrajectoryConfig) -> DrivetrainSplineTrajectory: # 2018 cross scale auto waypoints side_start = Pose2d.from_feet(1.54, 23.23, Rotation2d.from_degrees(180)) cross_scale = Pose2d.from_feet(23.7, 6.8, Rotation2d.from_degrees(-160)) diff --git a/subprojects/robotpy-wpimath/wpimath/__init__.py b/subprojects/robotpy-wpimath/wpimath/__init__.py index 34a965ded..7f7ae00a6 100644 --- a/subprojects/robotpy-wpimath/wpimath/__init__.py +++ b/subprojects/robotpy-wpimath/wpimath/__init__.py @@ -38,6 +38,9 @@ DifferentialSample, DifferentialTrajectory, DifferentialTrajectoryBase, + DrivetrainSplineSample, + DrivetrainSplineTrajectory, + DrivetrainSplineTrajectoryBase, EdgeCounterFilter, ElevatorFeedforward, Ellipse2d, @@ -47,11 +50,12 @@ ExtendedKalmanFilter_2_1_1, ExtendedKalmanFilter_2_1_2, ExtendedKalmanFilter_2_2_2, + HolonomicSample, + HolonomicTrajectory, + HolonomicTrajectoryBase, ImplicitModelFollower_1_1, ImplicitModelFollower_2_1, ImplicitModelFollower_2_2, - HolonomicTrajectory, - HolonomicTrajectoryBase, KalmanFilter_1_1_1, KalmanFilter_2_1_1, KalmanFilter_2_1_2, @@ -123,9 +127,6 @@ Spline5, SplineHelper, SplineParameterizer, - SplineSample, - SplineTrajectory, - SplineTrajectoryBase, SwerveDrive2Kinematics, SwerveDrive2KinematicsBase, SwerveDrive2KinematicsConstraint, @@ -241,6 +242,9 @@ "DifferentialSample", "DifferentialTrajectory", "DifferentialTrajectoryBase", + "DrivetrainSplineSample", + "DrivetrainSplineTrajectory", + "DrivetrainSplineTrajectoryBase", "EdgeCounterFilter", "ElevatorFeedforward", "Ellipse2d", @@ -250,6 +254,7 @@ "ExtendedKalmanFilter_2_1_1", "ExtendedKalmanFilter_2_1_2", "ExtendedKalmanFilter_2_2_2", + "HolonomicSample", "HolonomicTrajectory", "HolonomicTrajectoryBase", "ImplicitModelFollower_1_1", @@ -326,9 +331,6 @@ "Spline5", "SplineHelper", "SplineParameterizer", - "SplineSample", - "SplineTrajectory", - "SplineTrajectoryBase", "SwerveDrive2Kinematics", "SwerveDrive2KinematicsBase", "SwerveDrive2KinematicsConstraint", diff --git a/subprojects/robotpy-wpiutil/pyproject.toml b/subprojects/robotpy-wpiutil/pyproject.toml index e328ac06c..c3d637f79 100644 --- a/subprojects/robotpy-wpiutil/pyproject.toml +++ b/subprojects/robotpy-wpiutil/pyproject.toml @@ -46,7 +46,6 @@ update_init = [ scan_headers_ignore = [ "debugging.hpp", "debugging/*", - "fmt/*", "google/*", "wpi/*", "wpystruct_fns.h", diff --git a/subprojects/robotpy-wpiutil/wpiutil/src/wpistruct/wpystruct.h b/subprojects/robotpy-wpiutil/wpiutil/src/wpistruct/wpystruct.h index 64c14f84c..1b3eb6757 100644 --- a/subprojects/robotpy-wpiutil/wpiutil/src/wpistruct/wpystruct.h +++ b/subprojects/robotpy-wpiutil/wpiutil/src/wpistruct/wpystruct.h @@ -1,12 +1,12 @@ #pragma once +#include #include #include #include #include -#include #include #include #include @@ -190,7 +190,7 @@ struct WPyStructPyConverter : WPyStructConverter { py::bytes result = m_pack(value.py); std::string_view rview = result; if (rview.size() != data.size()) { - std::string msg = fmt::format( + std::string msg = std::format( "{} pack did not return {} bytes (returned {})", pytypename(py::type::of(value.py)), data.size(), rview.size()); throw py::value_error(msg); @@ -230,7 +230,7 @@ struct WPyStructInfo { explicit WPyStructInfo(const py::type& t) { if (!py::hasattr(t, "WPIStruct")) { throw py::type_error( - fmt::format("{} is not struct serializable (does not have WPIStruct)", + std::format("{} is not struct serializable (does not have WPIStruct)", pytypename(t))); } @@ -249,7 +249,7 @@ struct WPyStructInfo { try { cvt = std::make_shared(s); } catch (py::error_already_set& e) { - std::string msg = fmt::format( + std::string msg = std::format( "{} is not struct serializable (invalid WPIStruct)", pytypename(t)); py::raise_from(e, PyExc_TypeError, msg.c_str()); throw py::error_already_set(); diff --git a/subprojects/robotpy-xrp/pyproject.toml b/subprojects/robotpy-xrp/pyproject.toml index a70991eb5..538e48697 100644 --- a/subprojects/robotpy-xrp/pyproject.toml +++ b/subprojects/robotpy-xrp/pyproject.toml @@ -38,7 +38,7 @@ version_file = "xrp/version.py" artifact_id = "halsim_xrp" group_id = "org.wpilib.halsim" repo_url = "https://frcmaven.wpi.edu/artifactory/development-2027" -version = "2027.0.0-alpha-6-139-g34fee9a73" +version = "2027.0.0-alpha-6-167-gdb3a9c428" use_headers = false extract_to = "xrp/extension"