mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
[copybara] Resync robotpy (#8585)
Project import generated by Copybara.
GitOrigin-RevId: fd000778e9b78c72cc7ca7b2ebe476129b78c6e0
This commit is contained in:
24
commandsv2/src/main/python/LICENSE
Normal file
24
commandsv2/src/main/python/LICENSE
Normal file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2009-2021 FIRST and other WPILib contributors
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of FIRST, WPILib, nor the names of other WPILib
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY FIRST AND OTHER WPILIB CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY NONINFRINGEMENT AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FIRST OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
7
commandsv2/src/main/python/README.md
Normal file
7
commandsv2/src/main/python/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
robotpy-commands-v2
|
||||
===================
|
||||
|
||||
Python wrappers around a modified version of the new WPILib commands library.
|
||||
|
||||
* Documentation @ https://robotpy.readthedocs.io/projects/commands-v2
|
||||
* Examples @ https://github.com/robotpy/examples/tree/main/commands-v2
|
||||
@@ -9,7 +9,7 @@ from .trigger import Trigger
|
||||
|
||||
class CommandGenericHID:
|
||||
"""
|
||||
A version of :class:`wpilib.interfaces.GenericHID` with :class:`.Trigger` factories for command-based.
|
||||
A version of :class:`wpilib.GenericHID` with :class:`.Trigger` factories for command-based.
|
||||
"""
|
||||
|
||||
def __init__(self, port: int):
|
||||
|
||||
@@ -6,7 +6,7 @@ from .trigger import Trigger
|
||||
|
||||
class JoystickButton(Trigger):
|
||||
"""
|
||||
A Button that gets its state from a :class:`wpilib.interfaces.GenericHID`.
|
||||
A Button that gets its state from a :class:`wpilib.GenericHID`.
|
||||
"""
|
||||
|
||||
def __init__(self, joystick: GenericHID, buttonNumber: int):
|
||||
@@ -14,6 +14,6 @@ class JoystickButton(Trigger):
|
||||
Creates a joystick button for triggering commands.
|
||||
|
||||
:param joystick: The GenericHID object that has the button (e.g. Joystick, KinectStick, etc)
|
||||
:param buttonNumber: The button number (see :func:`wpilib.interfaces.GenericHID.getRawButton`
|
||||
:param buttonNumber: The button number (see :func:`wpilib.GenericHID.getRawButton`
|
||||
"""
|
||||
super().__init__(lambda: joystick.getRawButton(buttonNumber))
|
||||
|
||||
@@ -112,8 +112,7 @@ class NetworkButton(Trigger):
|
||||
if inst is not None and table is not None and field is not None:
|
||||
return init_inst_table_field(inst, table, field)
|
||||
|
||||
raise TypeError(
|
||||
f"""
|
||||
raise TypeError(f"""
|
||||
TypeError: NetworkButton(): incompatible function arguments. The following argument types are supported:
|
||||
1. (self: NetworkButton, topic: BooleanTopic)
|
||||
2. (self: NetworkButton, sub: BooleanSubscriber)
|
||||
@@ -122,5 +121,4 @@ TypeError: NetworkButton(): incompatible function arguments. The following argum
|
||||
5. (self: NetworkButton, inst: NetworkTableInstance, table: str, field: str)
|
||||
|
||||
Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
"""
|
||||
)
|
||||
""")
|
||||
|
||||
@@ -6,7 +6,7 @@ from .trigger import Trigger
|
||||
|
||||
class POVButton(Trigger):
|
||||
"""
|
||||
A Button that gets its state from a POV on a :class:`wpilib.interfaces.GenericHID`.
|
||||
A Button that gets its state from a POV on a :class:`wpilib.GenericHID`.
|
||||
"""
|
||||
|
||||
def __init__(self, joystick: GenericHID, angle: int, povNumber: int = 0):
|
||||
@@ -15,6 +15,6 @@ class POVButton(Trigger):
|
||||
|
||||
:param joystick: The GenericHID object that has the POV
|
||||
:param angle: The desired angle in degrees (e.g. 90, 270)
|
||||
:param povNumber: The POV number (see :func:`wpilib.interfaces.GenericHID.getPOV`)
|
||||
:param povNumber: The POV number (see :func:`wpilib.GenericHID.getPOV`)
|
||||
"""
|
||||
super().__init__(lambda: joystick.getPOV(povNumber) == angle)
|
||||
|
||||
@@ -73,16 +73,29 @@ class Trigger:
|
||||
if loop is not None and condition is not None:
|
||||
return init_loop_condition(loop, condition)
|
||||
|
||||
raise TypeError(
|
||||
f"""
|
||||
raise TypeError(f"""
|
||||
TypeError: Trigger(): incompatible function arguments. The following argument types are supported:
|
||||
1. (self: Trigger)
|
||||
2. (self: Trigger, condition: () -> bool)
|
||||
3. (self: Trigger, loop: EventLoop, condition: () -> bool)
|
||||
|
||||
Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
"""
|
||||
)
|
||||
""")
|
||||
|
||||
def _add_binding(self, body: Callable[[bool, bool], None]) -> None:
|
||||
"""
|
||||
Adds a binding to the EventLoop.
|
||||
|
||||
:param body: The body of the binding to add.
|
||||
"""
|
||||
|
||||
state = SimpleNamespace(previous=self._condition())
|
||||
|
||||
@self._loop.bind
|
||||
def _():
|
||||
current = self._condition()
|
||||
body(state.previous, current)
|
||||
state.previous = current
|
||||
|
||||
def onTrue(self, command: Command) -> Self:
|
||||
"""
|
||||
@@ -92,14 +105,10 @@ Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
:returns: this trigger, so calls can be chained
|
||||
"""
|
||||
|
||||
state = SimpleNamespace(pressed_last=self._condition())
|
||||
|
||||
@self._loop.bind
|
||||
def _():
|
||||
pressed = self._condition()
|
||||
if not state.pressed_last and pressed:
|
||||
@self._add_binding
|
||||
def _(previous, current):
|
||||
if not previous and current:
|
||||
command.schedule()
|
||||
state.pressed_last = pressed
|
||||
|
||||
return self
|
||||
|
||||
@@ -111,14 +120,10 @@ Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
:returns: this trigger, so calls can be chained
|
||||
"""
|
||||
|
||||
state = SimpleNamespace(pressed_last=self._condition())
|
||||
|
||||
@self._loop.bind
|
||||
def _():
|
||||
pressed = self._condition()
|
||||
if state.pressed_last and not pressed:
|
||||
@self._add_binding
|
||||
def _(previous, current):
|
||||
if previous and not current:
|
||||
command.schedule()
|
||||
state.pressed_last = pressed
|
||||
|
||||
return self
|
||||
|
||||
@@ -130,17 +135,11 @@ Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
:returns: this trigger, so calls can be chained
|
||||
"""
|
||||
|
||||
state = SimpleNamespace(pressed_last=self._condition())
|
||||
|
||||
@self._loop.bind
|
||||
def _():
|
||||
pressed = self._condition()
|
||||
|
||||
if state.pressed_last != pressed:
|
||||
@self._add_binding
|
||||
def _(previous, current):
|
||||
if previous != current:
|
||||
command.schedule()
|
||||
|
||||
state.pressed_last = pressed
|
||||
|
||||
return self
|
||||
|
||||
def whileTrue(self, command: Command) -> Self:
|
||||
@@ -155,16 +154,12 @@ Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
:returns: this trigger, so calls can be chained
|
||||
"""
|
||||
|
||||
state = SimpleNamespace(pressed_last=self._condition())
|
||||
|
||||
@self._loop.bind
|
||||
def _():
|
||||
pressed = self._condition()
|
||||
if not state.pressed_last and pressed:
|
||||
@self._add_binding
|
||||
def _(previous, current):
|
||||
if not previous and current:
|
||||
command.schedule()
|
||||
elif state.pressed_last and not pressed:
|
||||
elif previous and not current:
|
||||
command.cancel()
|
||||
state.pressed_last = pressed
|
||||
|
||||
return self
|
||||
|
||||
@@ -180,16 +175,12 @@ Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
:returns: this trigger, so calls can be chained
|
||||
"""
|
||||
|
||||
state = SimpleNamespace(pressed_last=self._condition())
|
||||
|
||||
@self._loop.bind
|
||||
def _():
|
||||
pressed = self._condition()
|
||||
if state.pressed_last and not pressed:
|
||||
@self._add_binding
|
||||
def _(previous, current):
|
||||
if previous and not current:
|
||||
command.schedule()
|
||||
elif not state.pressed_last and pressed:
|
||||
elif not previous and current:
|
||||
command.cancel()
|
||||
state.pressed_last = pressed
|
||||
|
||||
return self
|
||||
|
||||
@@ -201,17 +192,13 @@ Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
:returns: this trigger, so calls can be chained
|
||||
"""
|
||||
|
||||
state = SimpleNamespace(pressed_last=self._condition())
|
||||
|
||||
@self._loop.bind
|
||||
def _():
|
||||
pressed = self._condition()
|
||||
if not state.pressed_last and pressed:
|
||||
@self._add_binding
|
||||
def _(previous, current):
|
||||
if not previous and current:
|
||||
if command.isScheduled():
|
||||
command.cancel()
|
||||
else:
|
||||
command.schedule()
|
||||
state.pressed_last = pressed
|
||||
|
||||
return self
|
||||
|
||||
@@ -223,17 +210,13 @@ Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
:returns: this trigger, so calls can be chained
|
||||
"""
|
||||
|
||||
state = SimpleNamespace(pressed_last=self._condition())
|
||||
|
||||
@self._loop.bind
|
||||
def _():
|
||||
pressed = self._condition()
|
||||
if state.pressed_last and not pressed:
|
||||
@self._add_binding
|
||||
def _(previous, current):
|
||||
if previous and not current:
|
||||
if command.isScheduled():
|
||||
command.cancel()
|
||||
else:
|
||||
command.schedule()
|
||||
state.pressed_last = pressed
|
||||
|
||||
return self
|
||||
|
||||
|
||||
@@ -9,13 +9,14 @@ from typing import Any, Callable, Dict, Iterable, List, Optional, Set, Union
|
||||
import hal
|
||||
from typing_extensions import Self
|
||||
from wpilib import (
|
||||
RobotBase,
|
||||
DriverStation,
|
||||
EventLoop,
|
||||
RobotBase,
|
||||
TimedRobot,
|
||||
Watchdog,
|
||||
reportWarning,
|
||||
)
|
||||
|
||||
from wpiutil import Sendable, SendableBuilder, SendableRegistry
|
||||
|
||||
from .command import Command, InterruptionBehavior
|
||||
|
||||
@@ -79,15 +79,13 @@ class ProxyCommand(Command):
|
||||
elif callable(args[0]):
|
||||
return init_supplier(args[0])
|
||||
|
||||
raise TypeError(
|
||||
f"""
|
||||
raise TypeError(f"""
|
||||
TypeError: ProxyCommand(): incompatible function arguments. The following argument types are supported:
|
||||
1. (self: ProxyCommand, supplier: () -> Command)
|
||||
2. (self: ProxyCommand, command: Command)
|
||||
|
||||
Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
"""
|
||||
)
|
||||
""")
|
||||
|
||||
def initialize(self):
|
||||
self._command = self._supplier()
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
from .sysidroutine import SysIdRoutine
|
||||
|
||||
|
||||
__all__ = ["SysIdRoutine"]
|
||||
|
||||
@@ -11,7 +11,6 @@ from wpimath.units import seconds, volts
|
||||
|
||||
from typing import Callable, Optional
|
||||
|
||||
|
||||
volts_per_second = float
|
||||
|
||||
|
||||
|
||||
@@ -63,15 +63,13 @@ class WaitUntilCommand(Command):
|
||||
elif callable(args[0]):
|
||||
return init_condition(args[0])
|
||||
|
||||
raise TypeError(
|
||||
f"""
|
||||
raise TypeError(f"""
|
||||
TypeError: WaitUntilCommand(): incompatible function arguments. The following argument types are supported:
|
||||
1. (self: WaitUntilCommand, condition: () -> bool)
|
||||
2. (self: WaitUntilCommand, time: wpimath.units.seconds)
|
||||
|
||||
Invoked with: {format_args_kwargs(self, *args, **kwargs)}
|
||||
"""
|
||||
)
|
||||
""")
|
||||
|
||||
def isFinished(self) -> bool:
|
||||
return self._condition()
|
||||
|
||||
36
commandsv2/src/main/python/pyproject.toml
Normal file
36
commandsv2/src/main/python/pyproject.toml
Normal file
@@ -0,0 +1,36 @@
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[project]
|
||||
name = "robotpy-commands-v2"
|
||||
version = "0.0.0"
|
||||
description = "WPILib command framework v2"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.10"
|
||||
license = "BSD-3-Clause"
|
||||
license-files = ["LICENSE"]
|
||||
dependencies = [
|
||||
"wpilib==0.0.0",
|
||||
"typing_extensions>=4.1.0,<5",
|
||||
]
|
||||
|
||||
[[project.authors]]
|
||||
name = "RobotPy Development Team"
|
||||
email = "robotpy@googlegroups.com"
|
||||
|
||||
[[project.maintainers]]
|
||||
name = "RobotPy Development Team"
|
||||
email = "robotpy@googlegroups.com"
|
||||
|
||||
[project.urls]
|
||||
"Source code" = "https://github.com/robotpy/robotpy-commands-v2"
|
||||
|
||||
[tool.hatch.version]
|
||||
source = "vcs"
|
||||
|
||||
[tool.hatch.build.targets.sdist]
|
||||
packages = ["commands2"]
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["commands2"]
|
||||
@@ -5,7 +5,6 @@ import inspect
|
||||
import commands2
|
||||
from wpilib.simulation import DriverStationSim, pauseTiming, resumeTiming, stepTiming
|
||||
|
||||
|
||||
Y = TypeVar("Y")
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user