diff --git a/commands/autoconfig.py b/commands/autoconfig.py index cee1f9d2..dbdb0a5d 100644 --- a/commands/autoconfig.py +++ b/commands/autoconfig.py @@ -32,17 +32,20 @@ def init(): try: val = definedAutos[0] for auto in definedAutos: - if auto[-1] == '0': + if auto[-1] == "0": val = auto table.putString("selectedAuto", val) - except(IndexError): + except (IndexError): table.putString("selectedAuto", "NO AUTO FOUND") + def getAutoProgram(): """ Returns the first defined auto if none are selected. """ try: - return table.getString("selectedAuto", (definedAutos[0]).lower()) # Should never call the default here since default is populated above. - except(IndexError): + return table.getString( + "selectedAuto", (definedAutos[0]).lower() + ) # Should never call the default here since default is populated above. + except (IndexError): raise Exception("You don't have any autos defined!") diff --git a/commands/autonomouscommandgroup.py b/commands/autonomouscommandgroup.py index cc3e06a2..dd22d9bf 100644 --- a/commands/autonomouscommandgroup.py +++ b/commands/autonomouscommandgroup.py @@ -24,14 +24,14 @@ def __init__(self): if var.lower() == self.currentAuto: toRun = var break - + eval("self." + toRun + "()") # Runs the method def example(self): """ Define the function using the name of the autonomous program. It should then appear on the driverstation. Put a exclamation point in front of the chosen - default one! If there is no default selected, the default will be the auto first + default one! If there is no default selected, the default will be the auto first in alphabetical order. """ pass diff --git a/commands/drivetrain/drivecommand.py b/commands/drivetrain/drivecommand.py index a50282b3..e613f3f9 100644 --- a/commands/drivetrain/drivecommand.py +++ b/commands/drivetrain/drivecommand.py @@ -6,9 +6,10 @@ from custom import driverhud import math -logicalaxes.registerAxis('driveX') -logicalaxes.registerAxis('driveY') -logicalaxes.registerAxis('driveRotate') +logicalaxes.registerAxis("driveX") +logicalaxes.registerAxis("driveY") +logicalaxes.registerAxis("driveRotate") + class DriveCommand(CommandBase): def __init__(self): @@ -19,11 +20,10 @@ def __init__(self): def initialize(self): robot.drivetrain.stop() robot.drivetrain.setProfile(0) - + self.lastY = None self.slowed = False - def execute(self): # Avoid quick changes in direction y = logicalaxes.driveY.get() @@ -46,7 +46,5 @@ def execute(self): correction = 0 robot.drivetrain.move( - logicalaxes.driveX.get(), - y - correction, - logicalaxes.driveRotate.get() + logicalaxes.driveX.get(), y - correction, logicalaxes.driveRotate.get() ) diff --git a/commands/drivetrain/movecommand.py b/commands/drivetrain/movecommand.py index ee2b25a4..b3c3ad61 100644 --- a/commands/drivetrain/movecommand.py +++ b/commands/drivetrain/movecommand.py @@ -16,9 +16,9 @@ def __init__(self, distance, angle=0, tolerance=5, slow=False, name=None): name = "Move %f inches" % distance super().__init__() - + if isinstance(robot.drivetain, SwerveDrive): - + self.distance = -distance self.angle = angle self.tol = tolerance # Angle tolerance in degrees. diff --git a/commands/drivetrain/pivotcommand.py b/commands/drivetrain/pivotcommand.py index 193cd862..60754fbf 100644 --- a/commands/drivetrain/pivotcommand.py +++ b/commands/drivetrain/pivotcommand.py @@ -7,11 +7,11 @@ class PivotCommand(TurnCommand): - '''Allows autonomous turning using the drive base encoders.''' + """Allows autonomous turning using the drive base encoders.""" def __init__(self, degrees, reverse=False, name=None): if name is None: - name = 'Pivot %f degrees' % degrees + name = "Pivot %f degrees" % degrees super().__init__(degrees, name) @@ -23,9 +23,8 @@ def __init__(self, degrees, reverse=False, name=None): if reverse: self.pivotSide = abs(self.pivotSide - 1) - def initialize(self): - '''Calculates new positions by offsetting the current ones.''' + """Calculates new positions by offsetting the current ones.""" offset = self._calculateDisplacement() * 2 targetPositions = [] diff --git a/commands/drivetrain/pivottocommand.py b/commands/drivetrain/pivottocommand.py index 63682666..74461580 100644 --- a/commands/drivetrain/pivottocommand.py +++ b/commands/drivetrain/pivottocommand.py @@ -2,20 +2,16 @@ import robot + class PivotToCommand(PivotCommand): - '''Pivot to a specified angle using the gyroscope.''' + """Pivot to a specified angle using the gyroscope.""" def __init__(self, targetDegrees, reverse=False): - super().__init__( - targetDegrees, - reverse, - 'Pivot to %f degrees' % targetDegrees - ) + super().__init__(targetDegrees, reverse, "Pivot to %f degrees" % targetDegrees) self.targetDegrees = targetDegrees self.reversed = reverse - def initialize(self): self.distance = robot.drivetrain.getAngleTo(self.targetDegrees) diff --git a/commands/drivetrain/resettiltcommand.py b/commands/drivetrain/resettiltcommand.py index 18708b69..463ce73e 100644 --- a/commands/drivetrain/resettiltcommand.py +++ b/commands/drivetrain/resettiltcommand.py @@ -2,8 +2,8 @@ import robot -class ResetTiltCommand(InstantCommand): +class ResetTiltCommand(InstantCommand): def __init__(self): super().__init__() diff --git a/commands/drivetrain/setspeedcommand.py b/commands/drivetrain/setspeedcommand.py index 0ea9635e..155570c1 100644 --- a/commands/drivetrain/setspeedcommand.py +++ b/commands/drivetrain/setspeedcommand.py @@ -2,13 +2,13 @@ import robot + class SetSpeedCommand(InstantCommand): - '''Changes the max speed of the drive subsystem.''' + """Changes the max speed of the drive subsystem.""" def __init__(self, speed): super().__init__() self.speed = speed - def initialize(self): robot.drivetrain.setSpeedLimit(self.speed) diff --git a/commands/drivetrain/turncommand.py b/commands/drivetrain/turncommand.py index 851c2f6c..c51a9af6 100644 --- a/commands/drivetrain/turncommand.py +++ b/commands/drivetrain/turncommand.py @@ -7,17 +7,16 @@ class TurnCommand(MoveCommand): - '''Allows autonomous turning using the drive base encoders.''' + """Allows autonomous turning using the drive base encoders.""" def __init__(self, degrees, name=None): if name is None: - name = 'Turn %f degrees' % degrees + name = "Turn %f degrees" % degrees super().__init__(degrees, False, name) - def initialize(self): - '''Calculates new positions by offseting the current ones.''' + """Calculates new positions by offseting the current ones.""" offset = self._calculateDisplacement() targetPositions = [] @@ -26,15 +25,14 @@ def initialize(self): robot.drivetrain.setPositions(targetPositions) - def _calculateDisplacement(self): - ''' + """ In order to avoid having a separate ticksPerDegree, we calculate it based on the width of the robot base. - ''' + """ - inchesPerDegree = math.pi * Config('DriveTrain/width') / 360 + inchesPerDegree = math.pi * Config("DriveTrain/width") / 360 totalDistanceInInches = self.distance * inchesPerDegree ticks = robot.drivetrain.inchesToTicks(totalDistanceInInches) - return ticks * Config('DriveTrain/slip', 1.2) + return ticks * Config("DriveTrain/slip", 1.2) diff --git a/commands/drivetrain/turntocommand.py b/commands/drivetrain/turntocommand.py index 9742db2f..7222755a 100644 --- a/commands/drivetrain/turntocommand.py +++ b/commands/drivetrain/turntocommand.py @@ -2,18 +2,15 @@ import robot + class TurnToCommand(TurnCommand): - '''Turn to a specified angle using the gyroscope.''' + """Turn to a specified angle using the gyroscope.""" def __init__(self, targetDegrees): - super().__init__( - targetDegrees, - 'Turn to %f degrees' % targetDegrees - ) + super().__init__(targetDegrees, "Turn to %f degrees" % targetDegrees) self.targetDegrees = targetDegrees - def initialize(self): self.distance = robot.drivetrain.getAngleTo(self.targetDegrees) diff --git a/commands/drivetrain/zerogyrocommand.py b/commands/drivetrain/zerogyrocommand.py index 6c757704..5adf9b0a 100644 --- a/commands/drivetrain/zerogyrocommand.py +++ b/commands/drivetrain/zerogyrocommand.py @@ -2,13 +2,12 @@ import robot -class ZeroGyroCommand(InstantCommand): +class ZeroGyroCommand(InstantCommand): def __init__(self): - super().__init__('Zero Gyro') + super().__init__("Zero Gyro") self.requires(robot.drivetrain) - def initialize(self): robot.drivetrain.resetGyro() diff --git a/commands/monitorcommand.py b/commands/monitorcommand.py index dff88874..282944b1 100644 --- a/commands/monitorcommand.py +++ b/commands/monitorcommand.py @@ -2,21 +2,21 @@ import robot + class MonitorCommand(Command): - '''Runs continually while the robot is powered on.''' + """Runs continually while the robot is powered on.""" def __init__(self): - super().__init__('MonitorCommand') + super().__init__("MonitorCommand") - ''' + """ Required because this is the default command for the monitor subsystem. - ''' + """ self.requires(robot.monitor) self.setInterruptible(False) self.setRunWhenDisabled(True) - def execute(self): - '''Implement watchers here.''' + """Implement watchers here.""" pass diff --git a/commands/network/messagecommand.py b/commands/network/messagecommand.py index 85ad348d..ea4743f9 100644 --- a/commands/network/messagecommand.py +++ b/commands/network/messagecommand.py @@ -2,6 +2,7 @@ from subsystems.cougarsystem import CougarSystem + class MessageCommand(InstantCommand): def __init__(self, msg): super().__init__() diff --git a/commands/resetcommand.py b/commands/resetcommand.py index b70c5c92..5efc0655 100644 --- a/commands/resetcommand.py +++ b/commands/resetcommand.py @@ -2,16 +2,17 @@ import robot + class ResetCommand(InstantCommand): - ''' + """ Disable any running commands for all subsystems, except Monitor. This should be used to stop any motion and return the commands to a safe state. In general just requiring a subsystem will stop its current command. Additional resetting can be handled in the initialize method. - ''' + """ def __init__(self): super().__init__() - '''Require all subsystems to reset.''' + """Require all subsystems to reset.""" self.addRequirements(robot.drivetrain) diff --git a/commands/startupcommandgroup.py b/commands/startupcommandgroup.py index 0932faf7..7367aa9f 100644 --- a/commands/startupcommandgroup.py +++ b/commands/startupcommandgroup.py @@ -4,8 +4,8 @@ from .drivetrain.resettiltcommand import ResetTiltCommand -class StartUpCommandGroup(ParallelCommandGroup): +class StartUpCommandGroup(ParallelCommandGroup): def __init__(self): super().__init__() diff --git a/commands/tools/calculateerrorcommand.py b/commands/tools/calculateerrorcommand.py index 6c1c3a0c..cde6e808 100644 --- a/commands/tools/calculateerrorcommand.py +++ b/commands/tools/calculateerrorcommand.py @@ -4,6 +4,7 @@ import robot from custom.config import Config + class CalculateErrorCommand(MoveCommand): errors = [] @@ -12,15 +13,13 @@ def __init__(self, direction=1): super().__init__(30 * direction) self.addRequirements(robot.drivetrain) - Config('DriveTrain/wheelDiameter', 8) - self.table = NetworkTables.getTable('DriveTrain/Speed') - + Config("DriveTrain/wheelDiameter", 8) + self.table = NetworkTables.getTable("DriveTrain/Speed") def initialize(self): - self.table.putValue('P', 0) + self.table.putValue("P", 0) super().initialize() - def isFinished(self): if not self.isTimedOut(): return False @@ -35,9 +34,8 @@ def isFinished(self): return self.onTarget > 5 - def end(self): self.errors.append(robot.drivetrain.averageError()) avgError = sum(self.errors) / len(self.errors) - self.table.putValue('P', 415 / avgError) + self.table.putValue("P", 415 / avgError) diff --git a/commands/tools/calculatemaxspeedcommand.py b/commands/tools/calculatemaxspeedcommand.py index 3038e0f7..c22ef175 100644 --- a/commands/tools/calculatemaxspeedcommand.py +++ b/commands/tools/calculatemaxspeedcommand.py @@ -4,6 +4,7 @@ import robot + class CalculateMaxSpeedCommand(InstantCommand): measuredSpeeds = [] @@ -12,8 +13,7 @@ def __init__(self): super().__init__() self.addRequirements(robot.drivetrain) - self.table = NetworkTables.getTable('DriveTrain') - + self.table = NetworkTables.getTable("DriveTrain") def initialize(self): for speed in robot.drivetrain.getSpeeds(): @@ -22,8 +22,8 @@ def initialize(self): # Select the smallest max speed maxSpeed = min(self.measuredSpeeds) - self.table.putValue('maxSpeed', math.floor(maxSpeed)) - self.table.putValue('normalSpeed', round(maxSpeed * 0.7)) - self.table.putValue('preciseSpeed', round(maxSpeed * 0.3)) + self.table.putValue("maxSpeed", math.floor(maxSpeed)) + self.table.putValue("normalSpeed", round(maxSpeed * 0.7)) + self.table.putValue("preciseSpeed", round(maxSpeed * 0.3)) - self.table.putValue('Speed/F', 1023 / maxSpeed) + self.table.putValue("Speed/F", 1023 / maxSpeed) diff --git a/commands/tools/controllerdebugcommand.py b/commands/tools/controllerdebugcommand.py index 13686e97..324aa540 100644 --- a/commands/tools/controllerdebugcommand.py +++ b/commands/tools/controllerdebugcommand.py @@ -3,9 +3,8 @@ class ControllerDebugCommand(Command): - def __init__(self, port=0): - super().__init__('Get Controller Values') + super().__init__("Get Controller Values") self.setRunWhenDisabled(True) self.joystick = Joystick(port) @@ -13,13 +12,12 @@ def __init__(self, port=0): self.numOfAxes = self.joystick.ds.joystickAxes[port].count self.numOfButtons = self.joystick.ds.joystickButtons[port].count - def execute(self): for i in range(0, self.numOfAxes): value = self.joystick.getRawAxis(i) - if (abs(value) >= 0.5): - print('Axis %d: %f' % (i, value)) + if abs(value) >= 0.5: + print("Axis %d: %f" % (i, value)) for i in range(1, self.numOfButtons): if self.joystick.getRawButtonPressed(i): - print('Button %d Pressed' % i) + print("Button %d Pressed" % i) diff --git a/commands/tools/resetpidcommand.py b/commands/tools/resetpidcommand.py index f4d0ad0a..6dade2e2 100644 --- a/commands/tools/resetpidcommand.py +++ b/commands/tools/resetpidcommand.py @@ -2,13 +2,12 @@ import robot -class ResetPIDCommand(InstantCommand): +class ResetPIDCommand(InstantCommand): def __init__(self): super().__init__() self.addRequirements(robot.drivetrain) - def initialize(self): robot.drivetrain.resetPID() diff --git a/commands/tools/setuseencoderscommand.py b/commands/tools/setuseencoderscommand.py index 12378185..2877f0b5 100644 --- a/commands/tools/setuseencoderscommand.py +++ b/commands/tools/setuseencoderscommand.py @@ -4,21 +4,20 @@ from custom.config import Config from networktables import NetworkTables -class SetUseEncodersCommand(InstantCommand): +class SetUseEncodersCommand(InstantCommand): def __init__(self, encodersEnabled): super().__init__() self.addRequirements(robot.drivetrain) self.encodersEnabled = encodersEnabled - def initialize(self): robot.drivetrain.setUseEncoders(self.encodersEnabled) if not self.encodersEnabled: - maxSpeed = Config('DriveTrain/maxSpeed') + maxSpeed = Config("DriveTrain/maxSpeed") if not maxSpeed: - dt = NetworkTables.getTable('DriveTrain') - dt.putValue('maxSpeed', 1) + dt = NetworkTables.getTable("DriveTrain") + dt.putValue("maxSpeed", 1) robot.drivetrain.setSpeedLimit(maxSpeed) diff --git a/controller/controlleraxis.py b/controller/controlleraxis.py index 14de71a1..a08dc42a 100644 --- a/controller/controlleraxis.py +++ b/controller/controlleraxis.py @@ -1,11 +1,11 @@ class ControllerAxis: - '''Represents an axis of a joystick.''' + """Represents an axis of a joystick.""" def __init__(self, controller, id, isInverted): - ''' + """ An axis is considered inverted if pushing up gives a negative result. In that case, we multiply its value by -1 before returning it. - ''' + """ if isInverted: self.get = lambda: -1 * controller.getRawAxis(id) diff --git a/controller/genericcontroller.py b/controller/genericcontroller.py index c52b1b5e..73a84621 100644 --- a/controller/genericcontroller.py +++ b/controller/genericcontroller.py @@ -4,29 +4,30 @@ from .controlleraxis import ControllerAxis from .povbutton import POVButton + class GenericController(Joystick): - '''The base class for all controllers.''' + """The base class for all controllers.""" namedButtons = {} namedAxes = {} invertedAxes = [] def __init__(self, port): - ''' + """ Creates attributes of this class for every button and axis defined in its dictionaries. Subclasses need only fill in those dictionaries correctly. - ''' + """ super().__init__(port) - for name, id in self.namedButtons.items(): + for name, id in self.namedButtons.items(): if id >= 20: - ''' + """ By convention, the DPad buttons are 20 through 23 and can be converted to POV angles by the formula below. - ''' - + """ + angle = (id - 20) * 90 self.__dict__[name] = POVButton(self, angle) else: diff --git a/controller/layout.py b/controller/layout.py index f78f870f..136de4de 100644 --- a/controller/layout.py +++ b/controller/layout.py @@ -8,7 +8,7 @@ def init(): - ''' + """ Declare all controllers, assign axes to logical axes, and trigger commands on various button events. Available event types are: - whenPressed @@ -16,7 +16,7 @@ def init(): - whenReleased - toggleWhenPressed: start on first press, cancel on next - cancelWhenPressed: good for commands started with a different button - ''' + """ # The controller for driving the robot driveController = LogitechDualShock(0) @@ -28,7 +28,6 @@ def init(): driveController.Back.whenPressed(ResetCommand()) driveController.X.toggleWhenPressed(DriveCommand()) - # The controller for non-driving subsystems of the robot componentController = LogitechDualShock(1) diff --git a/controller/logicalaxes.py b/controller/logicalaxes.py index 14ddd8a3..eef79344 100644 --- a/controller/logicalaxes.py +++ b/controller/logicalaxes.py @@ -1,19 +1,20 @@ -''' +""" A store for axes that are used by commands, without dictating which controller axis the command reads. A command should call the registerAxis method with a name. An attribute with that name will then be added to this module. By default the axis is not attached to a controller and always reads zero. To send actual controller axis values to the command, assign it to the logical axis in OI. -''' +""" from .unassignedaxis import UnassignedAxis + def registerAxis(name): - ''' + """ This gives us access to this module's global variables so we can add new attributes to the module. - ''' + """ vars = globals() if not name in vars: diff --git a/controller/logitechdualshock.py b/controller/logitechdualshock.py index 590e18d3..8e0b4f22 100644 --- a/controller/logitechdualshock.py +++ b/controller/logitechdualshock.py @@ -1,38 +1,39 @@ from .genericcontroller import GenericController + class LogitechDualShock(GenericController): - ''' + """ Represents a Logitech Xbox controller with the underside switch set to "D" and mode turned off. If mode is one, the DPad and right joystick axes are swapped. - ''' + """ namedButtons = { - 'A': 2, - 'B': 3, - 'X': 1, - 'Y': 4, - 'LeftBumper': 5, - 'RightBumper': 6, - 'LeftTrigger': 7, - 'RightTrigger': 8, - 'Back': 9, - 'Start': 10, - 'LeftJoystick': 11, - 'RightJoystick': 12, - 'DPadUp': 20, - 'DPadRight': 21, - 'DPadDown': 22, - 'DPadLeft': 23 + "A": 2, + "B": 3, + "X": 1, + "Y": 4, + "LeftBumper": 5, + "RightBumper": 6, + "LeftTrigger": 7, + "RightTrigger": 8, + "Back": 9, + "Start": 10, + "LeftJoystick": 11, + "RightJoystick": 12, + "DPadUp": 20, + "DPadRight": 21, + "DPadDown": 22, + "DPadLeft": 23, } namedAxes = { - 'LeftX': 0, - 'LeftY': 1, - 'RightX': 2, - 'RightY': 3, - 'DPadX': 4, - 'DPadY': 5 + "LeftX": 0, + "LeftY": 1, + "RightX": 2, + "RightY": 3, + "DPadX": 4, + "DPadY": 5, } - invertedAxes = ['LeftY', 'RightY', 'DPadY'] + invertedAxes = ["LeftY", "RightY", "DPadY"] diff --git a/controller/povbutton.py b/controller/povbutton.py index 2ed2e3e2..7a5b15dd 100644 --- a/controller/povbutton.py +++ b/controller/povbutton.py @@ -1,17 +1,18 @@ from wpilib.buttons import Button + class POVButton(Button): - ''' + """ Turns DPad readings into button presses, so they can be used like any other button. - ''' + """ def __init__(self, controller, angle): - ''' + """ Pressing up on the DPad returns 0, up/right returns 45, right return 90 and so on. So, we can tell if a button is pressed if the reading is within 45 degrees of the passed angle. - ''' + """ super().__init__() @@ -20,8 +21,7 @@ def __init__(self, controller, angle): self.controller = controller - def get(self): - '''Whether the button is pressed or not.''' - + """Whether the button is pressed or not.""" + return self.controller.getPOV() in self.validAngles diff --git a/controller/unassignedaxis.py b/controller/unassignedaxis.py index 17399672..c05cfc90 100644 --- a/controller/unassignedaxis.py +++ b/controller/unassignedaxis.py @@ -1,5 +1,5 @@ class UnassignedAxis: - '''Dummy axis assigned to logical axes until they are configured in OI.''' + """Dummy axis assigned to logical axes until they are configured in OI.""" def get(self): - return 0 \ No newline at end of file + return 0 diff --git a/custom/config.py b/custom/config.py index 352779bc..ff5a1148 100644 --- a/custom/config.py +++ b/custom/config.py @@ -1,5 +1,6 @@ from networktables import NetworkTables, NetworkTable + class MissingConfigError(KeyError): pass @@ -10,21 +11,21 @@ def configListener(table, key, entry, value, flags): class Config: - ''' + """ Config values are stored on the roboRIO and updated using NetworkTables. By default the stored value is None, so make sure you set a value before running code that uses it. - ''' + """ _values = {} _nt = None _sep = NetworkTable.PATH_SEPARATOR_CHAR def __init__(self, key, default=None): - '''The key is the name that will be used in NetworkTables.''' + """The key is the name that will be used in NetworkTables.""" if self._sep not in key: - key = 'Config%s%s' % (self._sep, key) + key = "Config%s%s" % (self._sep, key) if key.startswith(self._sep): key = key[1:] @@ -41,20 +42,16 @@ def __init__(self, key, default=None): nf = NetworkTables.NotifyFlags Config._nt.addEntryListener( - self.key, - configListener, - nf.LOCAL | nf.NEW | nf.UPDATE + self.key, configListener, nf.LOCAL | nf.NEW | nf.UPDATE ) - def getValue(self): val = Config._values.get(self.key) if val is None: - raise MissingConfigError(f'{self.key} not set') + raise MissingConfigError(f"{self.key} not set") return val - def getValue(self): return Config._values.get(self.key) @@ -66,39 +63,35 @@ def getValue(self): val = Config._values.get(self.key) if val is None: - raise MissingConfigError(f'{self.key} not set') + raise MissingConfigError(f"{self.key} not set") return val - def getKey(self): return self.key - - ''' + """ We overload the "magic methods" for different primitive types that we would like to store in Config. - ''' + """ + def __bool__(self): return bool(self.getValue()) - def __float__(self): try: return float(self.getValue()) except (TypeError, ValueError): return 0.0 - def __int__(self): try: return int(self.getValue()) except (TypeError, ValueError): return 0 - def __str__(self): - '''If we're requesting a string for a number, show its key.''' + """If we're requesting a string for a number, show its key.""" try: float(self.getValue()) @@ -108,10 +101,10 @@ def __str__(self): except (TypeError, ValueError): return str(self.getValue()) - - ''' + """ Treat config values like normal numbers, if possible. - ''' + """ + def __lt__(self, other): return self.getValue() < other diff --git a/custom/driverhud.py b/custom/driverhud.py index 4a26281d..b180da51 100644 --- a/custom/driverhud.py +++ b/custom/driverhud.py @@ -24,6 +24,7 @@ def init(): if autonChooser is not None and not RobotBase.isSimulation(): raise RuntimeError("Driver HUD has already been initialized") + def getAutonomousProgram(): """ Return the autonomous program as selected on the dashboard. It is up to the diff --git a/generate.py b/generate.py index d96e2703..21775aad 100755 --- a/generate.py +++ b/generate.py @@ -8,28 +8,29 @@ def generateSubsystem(): if len(sys.argv) >= 3: subsystem = sys.argv[2] else: - subsystem = input('Enter a name for your subsystem: ') + subsystem = input("Enter a name for your subsystem: ") subsystem = subsystem.strip() if not subsystem: - error('Subsystem name must not be blank') + error("Subsystem name must not be blank") if subsystem[0].isdigit(): - error('Subsystem name cannot start with a digit') + error("Subsystem name cannot start with a digit") if not subsystem.isalnum(): - error('Subsystem name must contain only letters and numbers') + error("Subsystem name must contain only letters and numbers") if subsystem.lower() == subsystem: - error('Subsystem name should be ClassCased') + error("Subsystem name should be ClassCased") module = subsystem.lower() if hasattr(robot, module): - error('There is already a subsystem named %s' % module) + error("There is already a subsystem named %s" % module) - with open('subsystems/%s.py' % module, 'w') as f: - f.write(''' + with open("subsystems/%s.py" % module, "w") as f: + f.write( + """ from wpilib.command import Subsystem import ports @@ -40,182 +41,184 @@ class {subsystem}(Subsystem): def __init__(self): super().__init__('{subsystem}') -'''.lstrip().format(subsystem=subsystem)) +""".lstrip().format( + subsystem=subsystem + ) + ) - - with open('robot.py', 'r') as f: + with open("robot.py", "r") as f: init = f.read() - imports = re.compile( - '(from\s+subsystems\.\w+\s+import\s+[A-Z]\w+\s+as\s+\w+\s*)+' - ) + imports = re.compile("(from\s+subsystems\.\w+\s+import\s+[A-Z]\w+\s+as\s+\w+\s*)+") match = imports.search(init) old = match[0].strip() - new = '%s\nfrom subsystems.%s import %s as %s' + new = "%s\nfrom subsystems.%s import %s as %s" init = init.replace(old, new % (old, module, subsystem, module)) - with open('robot.py', 'w') as f: + with open("robot.py", "w") as f: f.write(init) - - with open('ports.py', 'r') as f: + with open("ports.py", "r") as f: ports = f.read() if not module in ports: - ports = ''' + ports = """ %s %s = PortsList() -''' % (ports, module) +""" % ( + ports, + module, + ) - with open('ports.py', 'w') as f: + with open("ports.py", "w") as f: f.write(ports) - with open('commands/resetcommand.py') as f: + with open("commands/resetcommand.py") as f: resetcommand = f.read() - requires = re.compile( - '(self\.requires\(robot.\w+\)\s*)+' - ) + requires = re.compile("(self\.requires\(robot.\w+\)\s*)+") match = requires.search(resetcommand) old = match[0].strip() - new = '%s\n self.requires(robot.%s)' + new = "%s\n self.requires(robot.%s)" resetcommand = resetcommand.replace(old, new % (old, module)) - with open('commands/resetcommand.py', 'w') as f: + with open("commands/resetcommand.py", "w") as f: f.write(resetcommand) - print('Generated subsystem %s' % subsystem) + print("Generated subsystem %s" % subsystem) def generateCommand(): if len(sys.argv) >= 3: command = sys.argv[2] else: - command = input('Enter a name for your command: ') + command = input("Enter a name for your command: ") command = command.strip() if not command: - error('Command name must not be blank') + error("Command name must not be blank") if command[0].isdigit(): - error('Command name cannot start with a digit') + error("Command name cannot start with a digit") if not command.isalnum(): - error('Command name must contain only letters and numbers') + error("Command name must contain only letters and numbers") if command.lower() == command: - error('Command name should be ClassCased') + error("Command name should be ClassCased") inherits = None - if command.endswith('CommandGroup'): - inherits = 'CommandGroup' - elif not command.endswith('Command'): - command += 'Command' + if command.endswith("CommandGroup"): + inherits = "CommandGroup" + elif not command.endswith("Command"): + command += "Command" - if command == 'DefaultCommand': - inherits = 'Command' + if command == "DefaultCommand": + inherits = "Command" if inherits is None: bases = [ - 'InstantCommand', - 'TimedCommand', - 'CommandGroup', - 'Command', - 'DefaultCommand' + "InstantCommand", + "TimedCommand", + "CommandGroup", + "Command", + "DefaultCommand", ] - print('Select a base class:') + print("Select a base class:") for id, cmd in enumerate(bases): - print('%d.) %s' % (id, cmd)) + print("%d.) %s" % (id, cmd)) - inherits = input('') + inherits = input("") if inherits.isdigit(): inherits = bases[int(inherits)] if not inherits in bases: - error('Unknown base class %s' % inherits) + error("Unknown base class %s" % inherits) - if inherits == 'CommandGroup': - inherits = 'fc.CommandFlow' - if command.endswith('Command'): - command += 'Group' + if inherits == "CommandGroup": + inherits = "fc.CommandFlow" + if command.endswith("Command"): + command += "Group" - if inherits == 'DefaultCommand': - inherits = 'Command' - command = 'DefaultCommand' + if inherits == "DefaultCommand": + inherits = "Command" + command = "DefaultCommand" # Put spaces before capital letters # https://stackoverflow.com/a/199215 - description = re.sub('Command(Group)?$', '', command) - description = re.sub(r'\B([A-Z])', r' \1', description) + description = re.sub("Command(Group)?$", "", command) + description = re.sub(r"\B([A-Z])", r" \1", description) - if inherits == 'TimedCommand': - duration = input('Duration in seconds (leave blank if variable): ') + if inherits == "TimedCommand": + duration = input("Duration in seconds (leave blank if variable): ") duration = duration.strip() - if duration != '': + if duration != "": try: float(duration) except ValueError: - error('Duration must be a number') + error("Duration must be a number") - subsystem = input('Which subsystem is %s for? ' % command) + subsystem = input("Which subsystem is %s for? " % command) requirements = subsystem.strip().lower().split() for subsystem in requirements: if not hasattr(robot, subsystem): - error('Unknown subsystem %s' % subsystem) + error("Unknown subsystem %s" % subsystem) - if command == 'DefaultCommand': + if command == "DefaultCommand": if len(requirements) == 0: - error('Subsystem is required for DefaultCommand') + error("Subsystem is required for DefaultCommand") - with open('subsystems/%s.py' % requirements[0]) as f: + with open("subsystems/%s.py" % requirements[0]) as f: content = f.read() - if 'initDefaultCommand' in content: - error('There is already a default command for this subsystem') + if "initDefaultCommand" in content: + error("There is already a default command for this subsystem") - if '.setDefaultCommand' in content: - error('There is already a default command for this subsystem') + if ".setDefaultCommand" in content: + error("There is already a default command for this subsystem") - content += ''' + content += ( + """ def initDefaultCommand(self): from commands.%s.defaultcommand import DefaultCommand self.setDefaultCommand(DefaultCommand()) -''' % requirements[0] +""" + % requirements[0] + ) - with open('subsystems/%s.py' % requirements[0], 'w') as f: + with open("subsystems/%s.py" % requirements[0], "w") as f: f.write(content) - description = 'Default for %s' % requirements[0] + description = "Default for %s" % requirements[0] - path = 'commands' + path = "commands" if len(requirements) > 0: - if not os.path.isdir('commands/%s' % requirements[0]): - os.makedirs('commands/%s' % requirements[0]) - - path += '/%s' % requirements[0] + if not os.path.isdir("commands/%s" % requirements[0]): + os.makedirs("commands/%s" % requirements[0]) + path += "/%s" % requirements[0] - if inherits == 'fc.CommandFlow': - content = 'import commandbased.flowcontrol as fc' + if inherits == "fc.CommandFlow": + content = "import commandbased.flowcontrol as fc" else: - content = 'from wpilib.command import %s' % inherits + content = "from wpilib.command import %s" % inherits if len(requirements) > 0: - content += '\n\nimport robot' + content += "\n\nimport robot" - content += '\n\n\nclass %s(%s):\n\n' % (command, inherits) + content += "\n\n\nclass %s(%s):\n\n" % (command, inherits) - if inherits == 'TimedCommand' and duration == '': - content += ' def __init__(self, timeout):\n' + if inherits == "TimedCommand" and duration == "": + content += " def __init__(self, timeout):\n" else: - content += ' def __init__(self):\n' + content += " def __init__(self):\n" - if inherits == 'TimedCommand': + if inherits == "TimedCommand": if duration: content += " super().__init__('%s', %s)" content = content % (description, duration) @@ -224,54 +227,54 @@ def initDefaultCommand(self): else: content += " super().__init__('%s')" % description - content += '\n\n' + content += "\n\n" - if inherits == 'fc.CommandFlow': - content += ' # Add commands here with self.addSequential() and ' - content += 'self.addParallel()' + if inherits == "fc.CommandFlow": + content += " # Add commands here with self.addSequential() and " + content += "self.addParallel()" else: if len(requirements) > 0: for subsystem in requirements: - content += ' self.requires(robot.%s)\n' % subsystem + content += " self.requires(robot.%s)\n" % subsystem - content += '\n' + content += "\n" - content += '\n def initialize(self):\n pass\n\n\n' + content += "\n def initialize(self):\n pass\n\n\n" - if inherits != 'InstantCommand': - content += ' def execute(self):\n pass\n\n\n' - content += ' def end(self):\n pass\n' + if inherits != "InstantCommand": + content += " def execute(self):\n pass\n\n\n" + content += " def end(self):\n pass\n" - with open('%s/%s.py' % (path, command.lower()), 'w') as f: + with open("%s/%s.py" % (path, command.lower()), "w") as f: f.write(content) - print('Created command %s' % command) + print("Created command %s" % command) def error(msg): - print('\033[91m%s\033[0m' % msg) + print("\033[91m%s\033[0m" % msg) sys.exit() def usage(): - usage = ''' + usage = """ usage: {0} command [CommandName] {0} subsystem [SubsystemName] -''' +""" print(usage.lstrip().format(sys.argv[0])) sys.exit() -if __name__ == '__main__': +if __name__ == "__main__": if len(sys.argv) < 2: usage() - if sys.argv[1] == 'subsystem': + if sys.argv[1] == "subsystem": generateSubsystem() - elif sys.argv[1] == 'command': + elif sys.argv[1] == "command": generateCommand() else: diff --git a/mockdata.py b/mockdata.py index d1583cda..627dc4f9 100644 --- a/mockdata.py +++ b/mockdata.py @@ -1,7 +1,7 @@ from custom.config import Config -Config('DriveTrain/maxSpeed', 950) -Config('DriveTrain/normalSpeed', 600) -Config('DriveTrain/preciseSpeed', 150) -Config('DriveTrain/wheelDiameter', 6) -Config('DriveTrain/width', 29.5) +Config("DriveTrain/maxSpeed", 950) +Config("DriveTrain/normalSpeed", 600) +Config("DriveTrain/preciseSpeed", 150) +Config("DriveTrain/wheelDiameter", 6) +Config("DriveTrain/width", 29.5) diff --git a/ports.py b/ports.py index 60bf0c0a..95cc7c0d 100644 --- a/ports.py +++ b/ports.py @@ -1,16 +1,19 @@ -''' +""" This is the place where we store port numbers for all subsystems. It is based on the RobotMap concept from WPILib. Each subsystem should have its own ports list. Values other than port numbers should be stored in Config. -''' +""" + class PortsList: - '''Dummy class used to store variables on an object.''' + """Dummy class used to store variables on an object.""" + pass + drivetrain = PortsList() -'''CAN IDs for motors''' +"""CAN IDs for motors""" drivetrain.frontLeftMotorID = 1 drivetrain.frontRightMotorID = 3 drivetrain.backLeftMotorID = 2 diff --git a/robot.py b/robot.py index 47ecce20..9c84fb16 100755 --- a/robot.py +++ b/robot.py @@ -37,7 +37,7 @@ def robotInit(self): controller.layout.init() autoconfig.init() driverhud.init() - + self.selectedAuto = autoconfig.getAutoProgram() self.auto = AutonomousCommandGroup() @@ -59,7 +59,7 @@ def autonomousInit(self): # Schedule the autonomous command self.auto.schedule() - + driverhud.showInfo("Starting %s" % self.auton) def disabledInit(self): diff --git a/subsystems/basedrive.py b/subsystems/basedrive.py index 2260d813..09b47735 100644 --- a/subsystems/basedrive.py +++ b/subsystems/basedrive.py @@ -10,20 +10,21 @@ import ports import constants + class BaseDrive(CougarSystem): - ''' + """ A general case drive train system. It abstracts away shared functionality of the various drive types that we can employ. Anything that can be done without knowing what type of drive system we have should be implemented here. - ''' + """ def __init__(self, name): super().__init__(name) - ''' + """ Create all motors, disable the watchdog, and turn off neutral braking since the PID loops will provide braking. - ''' + """ try: self.motors = [ WPI_TalonFX(ports.drivetrain.frontLeftMotorID), @@ -43,30 +44,30 @@ def __init__(self, name): motor.setSafetyEnabled(False) motor.configSelectedFeedbackSensor(FeedbackDevice.IntegratedSensor, 0, 0) - ''' + """ Subclasses should configure motors correctly and populate activeMotors. - ''' + """ self.activeMotors = [] self._configureMotors() - '''Initialize the navX MXP''' + """Initialize the navX MXP""" self.navX = AHRS.create_spi() self.resetGyro() self.flatAngle = constants.drivetrain.flatAngle - '''A record of the last arguments to move()''' + """A record of the last arguments to move()""" self.lastInputs = None - self.speedLimit = self.get('Normal Speed', 45) - self.deadband = self.get('Deadband', 0.05) - + self.speedLimit = self.get("Normal Speed", 45) + self.deadband = self.get("Deadband", 0.05) + self.wheelBase = ( constants.drivetrain.wheelBase ) # These are distances across the robot; horizontal, vertical, diagonal. - + self.trackWidth = constants.drivetrain.trackWidth self.r = math.sqrt(self.wheelBase ** 2 + self.trackWidth ** 2) - + self.wheelDiameter = ( constants.drivetrain.wheelDiameter ) # The diamter, in inches, of our driving wheels. @@ -85,29 +86,28 @@ def __init__(self, name): self.useEncoders = True def initDefaultCommand(self): - ''' + """ By default, unless another command is running that requires this subsystem, we will drive via joystick using the max speed stored in Config. - ''' + """ from commands.drivetrain.drivecommand import DriveCommand self.setDefaultCommand(DriveCommand()) - def move(self, x, y, rotate): - '''Turns coordinate arguments into motor outputs.''' + """Turns coordinate arguments into motor outputs.""" - ''' + """ Short-circuits the rather expensive movement calculations if the coordinates have not changed. - ''' + """ if [x, y, rotate] == self.lastInputs: return self.lastInputs = [x, y, rotate] - '''Prevent drift caused by small input values''' + """Prevent drift caused by small input values""" if self.useEncoders: x = math.copysign(max(abs(x) - self.deadband, 0), x) y = math.copysign(max(abs(y) - self.deadband, 0), y) @@ -115,7 +115,7 @@ def move(self, x, y, rotate): speeds = self._calculateSpeeds(x, y, rotate) - '''Prevent speeds > 1''' + """Prevent speeds > 1""" maxSpeed = 0 for speed in speeds: maxSpeed = max(abs(speed), maxSpeed) @@ -123,58 +123,55 @@ def move(self, x, y, rotate): if maxSpeed > 1: speeds = [x / maxSpeed for x in speeds] - '''Use speeds to feed motor output.''' + """Use speeds to feed motor output.""" for motor, speed in zip(self.activeMotors, speeds): motor.set(ControlMode.Velocity, speed * self.speedLimit) def setPositions(self, positions): - ''' + """ Have the motors move to the given positions. There should be one position per active motor. Extra positions will be ignored. - ''' + """ if not self.useEncoders: - raise RuntimeError('Cannot set position. Encoders are disabled.') + raise RuntimeError("Cannot set position. Encoders are disabled.") - for motor in self.motors: + for motor in self.motors: motor.set( TalonFXControlMode.MotionMagic, self.getModulePosition(False) + self.inchesToTicks(distance), ) - def averageError(self): - '''Find the average distance between setpoint and current position.''' + """Find the average distance between setpoint and current position.""" error = 0 for motor in self.activeMotors: - error += abs(motor.getClosedLoopTarget(0) - motor.getSelectedSensorPosition(0)) + error += abs( + motor.getClosedLoopTarget(0) - motor.getSelectedSensorPosition(0) + ) return error / len(self.activeMotors) - def atPosition(self, tolerance=10): - ''' + """ Check setpoint error to see if it is below the given tolerance. - ''' + """ return self.averageError() <= tolerance - def stop(self): - '''Disable all motors until set() is called again.''' + """Disable all motors until set() is called again.""" for motor in self.activeMotors: motor.stopMotor() self.lastInputs = None - def setProfile(self, profile): - '''Select which PID profile to use.''' + """Select which PID profile to use.""" for motor in self.activeMotors: motor.selectProfileSlot(profile, 0) - def resetPID(self): - '''Set all PID values to 0 for profiles 0 and 1.''' + """Set all PID values to 0 for profiles 0 and 1.""" for motor in self.activeMotors: motor.configClosedLoopRamp(0, 0) @@ -184,7 +181,7 @@ def resetPID(self): motor.config_kD(0, 0, 0) motor.config_kF(0, 0, 0) motor.config_IntegralZone(0, 0, 0) - + # Position control PIDs here. motor.config_kP(1, 0, 0) motor.config_kI(1, 0, 0) @@ -192,31 +189,27 @@ def resetPID(self): motor.config_kF(1, 0, 0) motor.config_IntegralZone(1, 0, 0) - def resetGyro(self): - '''Force the navX to consider the current angle to be zero degrees.''' + """Force the navX to consider the current angle to be zero degrees.""" self.setGyroAngle(0) - def setGyroAngle(self, angle): - '''Tweak the gyro reading.''' + """Tweak the gyro reading.""" self.navX.reset() self.navX.setAngleAdjustment(angle) - def getAngle(self): - '''Current gyro reading''' + """Current gyro reading""" return self.navX.getAngle() % 360 - def getAngleTo(self, targetAngle): - ''' + """ Returns the anglular distance from the given target. Values will be between -180 and 180, inclusive. - ''' + """ degrees = targetAngle - self.getAngle() while degrees > 180: degrees -= 360 @@ -246,7 +239,7 @@ def ticksToInches(self, ticks): return ( wheelRotations * self.circ ) # Basically just worked backwards from the sister method above. - + def inchesPerSecondToTicksPerTenth(self, inchesPerSecond): """ Convert a common velocity to falcon-interprettable @@ -262,60 +255,57 @@ def ticksPerTenthToInchesPerSecond(self, ticksPerTenth): def resetTilt(self): self.flatAngle = self.navX.getPitch() - def getTilt(self): return self.navX.getPitch() - self.flatAngle - def getAcceleration(self): - '''Reads acceleration from NavX MXP.''' + """Reads acceleration from NavX MXP.""" return self.navX.getWorldLinearAccelY() - def getSpeeds(self, inInchesPerSecond=True): - '''Returns the speed of each active motors.''' + """Returns the speed of each active motors.""" if inInchesPerSecond: - return [self.ticksPerTenthToInchesPerSecond( - motor.getSelectedSensorVelocity() - ) for motor in self.activeMotors] - + return [ + self.ticksPerTenthToInchesPerSecond(motor.getSelectedSensorVelocity()) + for motor in self.activeMotors + ] + # Returns ticks per 0.1 seconds (100 mS). return [motor.getSelectedSensorVelocity() for motor in self.activeMotors] - def getPositions(self, inInches=True): - '''Returns the position of each active motor.''' + """Returns the position of each active motor.""" if inInchesPerSecond: - return [self.ticksToInches(self.getSelectedSensorPosition(0)) for x in self.activeMotors] + return [ + self.ticksToInches(self.getSelectedSensorPosition(0)) + for x in self.activeMotors + ] return [x.getSelectedSensorPosition(0) for x in self.activeMotors] def setUseEncoders(self, useEncoders=True): - ''' + """ Turns on and off encoders. As a side effect, if encoders are enabled, the motors will be set to speed mode. Disabling encoders should not be done lightly, as many commands rely on encoder information. - ''' + """ self.useEncoders = useEncoders - def setSpeedLimit(self, speed): - ''' + """ Updates the max speed of the drive and changes to the appropriate mode depending on if encoders are enabled. - ''' + """ self.speedLimit = speed - def _configureMotors(self): - ''' + """ Make any necessary changes to the motors and populate self.activeMotors. - ''' + """ raise NotImplementedError() - def _calculateSpeeds(self, x, y, rotate): - '''Return a speed for each active motor.''' + """Return a speed for each active motor.""" raise NotImplementedError() diff --git a/subsystems/cougarsystem.py b/subsystems/cougarsystem.py index bba9e456..bdc03f0e 100644 --- a/subsystems/cougarsystem.py +++ b/subsystems/cougarsystem.py @@ -58,10 +58,10 @@ class CougarSystem(SubsystemBase): intialized = False orchestra = Orchestra() - + messageSystemTable = NetworkTables.getTable("MessagingSystem") messages = [] - messageSystemTable.putStringArray('messages', messages) + messageSystemTable.putStringArray("messages", messages) def __init__(self, subsystemName="Unknown Subsystem"): @@ -152,7 +152,7 @@ def constantlyUpdate(self, valueName, call): self.put(valueName, call()) self.updateThese[valueName] = call - + def sendMessage(self, message: str): """ Sends a message to the driver station @@ -160,20 +160,20 @@ def sendMessage(self, message: str): """ if len(CougarSystem.messages) > 99: CougarSystem.messages.pop(0) - - CougarSystem.messages.append(self.tableName + ': ' + message) + + CougarSystem.messages.append(self.tableName + ": " + message) @staticmethod def sendGeneralMessage(self, message: str): """ Used in MessageCommand. Do not use for subsystems! Instead, - use sendMessage(). + use sendMessage(). """ if len(CougarSystem.messages) > 99: CougarSystem.messages.pop(0) - - CougarSystem.messages.append('Robot: ' + message) - + + CougarSystem.messages.append("Robot: " + message) + def feed(self): """ Called in periodic. This does all the updating stuff needed! diff --git a/subsystems/drivetrain.py b/subsystems/drivetrain.py index 7970dfc3..1fce6361 100644 --- a/subsystems/drivetrain.py +++ b/subsystems/drivetrain.py @@ -1,10 +1,11 @@ from .skiddrive import SkidDrive + class DriveTrain(SkidDrive): - ''' + """ A custom drive train for the current year's game. Only add functionality here if it isn't likely to be used again in future seasons. - ''' + """ def __init__(self): - super().__init__('DriveTrain') + super().__init__("DriveTrain") diff --git a/subsystems/mecanumdrive.py b/subsystems/mecanumdrive.py index 32eceb74..03d7b408 100644 --- a/subsystems/mecanumdrive.py +++ b/subsystems/mecanumdrive.py @@ -3,44 +3,43 @@ from .basedrive import BaseDrive + class MecanumDrive(BaseDrive): - ''' + """ A drive base with four wheels, each independently driven. Due to the rollers placed at forty-five degree angles around the wheels, the robot can drive sideways, as well as forward and rotating, depending on how the motors are driven. - ''' + """ def __init__(self, name): super().__init__(name) self.isFieldOriented = False - def setUseFieldOrientation(self, isFieldOriented=True): - ''' + """ If set to true, the robot will drive the direction the joystick is moved (assuming the robot started facing the "up" direction), without regard to where the front of the robot is facing. - ''' + """ self.isFieldOriented = isFieldOriented def _configureMotors(self): - '''All four motors are active in a mecanum system.''' + """All four motors are active in a mecanum system.""" self.activeMotors = self.motors - '''Invert the motors on the left side.''' + """Invert the motors on the left side.""" self.motors[RobotDriveBase.MotorType.kFrontLeft].reverseSensor(True) self.motors[RobotDriveBase.MotorType.kRearLeft].reverseSensor(True) - def _calculateSpeeds(self, x, y, rotate): - '''Determines what speed each motor should have.''' + """Determines what speed each motor should have.""" if self.isFieldOriented: - '''Fancy math changes x and y based on gyro reading.''' + """Fancy math changes x and y based on gyro reading.""" heading = self.getAngle() * math.pi / 180 cosA = math.cos(heading) @@ -52,9 +51,4 @@ def _calculateSpeeds(self, x, y, rotate): x = newX y = newY - return [ - x + y + rotate, - x - y + rotate, - -x + y + rotate, - -x - y + rotate - ] + return [x + y + rotate, x - y + rotate, -x + y + rotate, -x - y + rotate] diff --git a/subsystems/monitor.py b/subsystems/monitor.py index 41632b8b..b4747a40 100644 --- a/subsystems/monitor.py +++ b/subsystems/monitor.py @@ -2,14 +2,12 @@ class Monitor(Subsystem): - '''Exists to observe system state via its default command.''' + """Exists to observe system state via its default command.""" def __init__(self): - super().__init__('Monitor') - + super().__init__("Monitor") def initDefaultCommand(self): from commands.monitorcommand import MonitorCommand self.setDefaultCommand(MonitorCommand()) - diff --git a/subsystems/skiddrive.py b/subsystems/skiddrive.py index 6bcaa9db..839dea45 100644 --- a/subsystems/skiddrive.py +++ b/subsystems/skiddrive.py @@ -3,27 +3,27 @@ from wpilib.drive import RobotDriveBase import ports -class SkidDrive(BaseDrive): - '''A drive base where all wheels on each side move together.''' +class SkidDrive(BaseDrive): + """A drive base where all wheels on each side move together.""" def _configureMotors(self): - '''Only the front motors are active in a skid system.''' + """Only the front motors are active in a skid system.""" self.activeMotors = self.motors[0:2] - '''Make the back motors follow the front.''' + """Make the back motors follow the front.""" if len(self.motors) == 4: - self.motors[RobotDriveBase.MotorType.kRearLeft] \ - .follow(self.motors[RobotDriveBase.MotorType.kFrontLeft]) - self.motors[RobotDriveBase.MotorType.kRearRight] \ - .follow(self.motors[RobotDriveBase.MotorType.kFrontRight]) - - - '''Invert encoders''' + self.motors[RobotDriveBase.MotorType.kRearLeft].follow( + self.motors[RobotDriveBase.MotorType.kFrontLeft] + ) + self.motors[RobotDriveBase.MotorType.kRearRight].follow( + self.motors[RobotDriveBase.MotorType.kFrontRight] + ) + + """Invert encoders""" for motor in self.activeMotors: motor.setSensorPhase(True) - def _calculateSpeeds(self, x, y, rotate): return [y + rotate, -y + rotate]