Git Product home page Git Product logo

robotpy-wpilib-utilities's Introduction

robotpy-wpilib-utilities

Useful utility functions/objects for RobotPy WPILib (2015+).

Documentation

Contribution guidelines

This repository is intended to be a common place for high quality code to live for "things that should be in WPILib, but aren't". The python implementation of WPILib is intended to be very close to the implementations in the other languages, which is where packages like this come in.

  • Most anything will be accepted, but ideally full frameworks will be separate packages and don't belong here
  • Ideally, contributions will have unit tests
  • Ideally, contributions will not have external python dependencies other than WPILib -- though, this may change.
  • Contributions will work (or at least, not break) on all supported RobotPy platforms (Windows/Linux/OSX, RoboRio)
  • All pull requests will be tested using Travis-CI

Installation

This library is automatically installed when you install pyfrc or RobotPy

License

BSD License, similar to WPILib.

Authors

robotpy-wpilib-utilities's People

Contributors

amorygalili avatar archduketim avatar arthurallshire avatar auscompgeek avatar benjiboy50fonz avatar calebeby avatar computer-whisperer avatar m-shadow avatar matt-puentes avatar noskcaj19 avatar virtuald avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

robotpy-wpilib-utilities's Issues

Console fills with NavX errors (NavX still works)

Both when the robot is disabled and enabled, the console is constantly being flooded with almost identical messages:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/robotpy_ext/common_drivers/navx/registerio.py", line 114, in run
    self.getCurrentData()
  File "/usr/local/lib/python3.6/site-packages/robotpy_ext/common_drivers/navx/registerio.py", line 176, in getCurrentData
    curr_data = self.io_provider.read(first_address, read_count)
  File "/usr/local/lib/python3.6/site-packages/robotpy_ext/common_drivers/navx/registerio_spi.py", line 85, in read
    raise IOError("CRC error")
OSError: CRC error


Locals at innermost frame:

{ 'count': 108,
  'crc': 237,
  'data': [ 123,
            123,
... continued ...

The NavX works fine as far as I can tell (I've only tested getAngle()). But these constant errors make it difficult to debug any other problems.

magicbot: Use Python 3.6 variable annotations to mark objects to be injected

Idea for the future (since this would require users to use Python 3.6). Instead of having components that look like this:

class Component:
  sd = NetworkTable

  def execute(self):
    self.sd.putValue('foo', 'bar')

have something that looks like this instead:

class Component:
  sd: NetworkTable

  def execute(self):
    self.sd.putValue('foo', 'bar')

(i.e. change the = to :)

This has the added advantage of not confusing tooling such as pylint, and would look less confusing to those new to magicbot.

magicbot: add default_state decorator

A state that will execute if nothing else is executing. Technically, this is almost the same as overriding execute... but I think it's more intuitive to have a separate mechanism for it.

NotifierDelay is broken

Issues with notifier cleanup. Temporarily fixed, but I'd like to use Notifier again. If wpilibsuite/allwpilib#960 is merged, then a HAL update is sufficient to fix this. Otherwise, we can work around it by creating an unused notifier.

magicbot: Add tunable setter

Slightly inspired by a planned feature in Oblarg's Oblog.

Idea: Add a convenient way of calling a setter over NT to magicbot.

Strawman:

  • A new decorator is added which is intended for methods of components (or the robot object).
  • Upon initialisation, magicbot will attach the method as an update listener on the relevant NT key. The key will be named according to the method name.
  • The method will only receive the value that was set to the key. No flags; KISS.
  • Similarly to the feedback decorator, a set_ prefix will be stripped from the name used for NT keys.
  • This should cooperate with both tunable and feedback.
  • An example of anticipated usage could be tuning PID loops on-the-fly on a SPARK MAX.

Usage would look like this:

class Component:
    @configurable
    def set_p(self, value) -> None:
        ...

An alternative interface may involve decorating with a method on a tunable:

class Component:
    p = tunable(1)

    @p.setter
    def set_p(self, value: float) -> None:
        ...

Access the magicbot component constructor

Use case: I have two objects that control swerve drive. The SwerveModule class controls individual modules. The SwerveDrive class controls the overall driving of the four SwerveModules. It would be useful to have access to the constructor of SwerveModule because I need to pass it around 4 parameters per class (motor1, motor2, encoder, inverted). If I had to create object for all of these in robot.py I would end up with about 16 variables that I never use again.

AutonomousModeSelector doesn't check if autonomous is a package

Should use pkgutil instead.

This mainly manifests itself by the need to create an autonomous/__init__.py (i.e. currently an "implicit" package can't be used), although this can also cause problems if a user accidentally creates an autonomous.py (or maybe this is a feature?).

magicbot doesn't understand the typing module

Currently you can't ask for injection using a type from typing (as they aren't runtime types). For example, this errors:

from typing import Sequence
import wpilib

class Component:
    motors: Sequence[wpilib.interfaces.SpeedController]

Not sure whether we want to check against the generic for the container types though.

Add print timer to magicbot

Example implementation:

class MyRobot(magicbot.MagicRobot):

    def teleopPeriodic(self):
        ...
        if self.should_print('identifier1'):
              # get a value
              print("something")

        # or perhaps this... 
        self.maybe_print("Foo is %s", self.get_something())

Printing on every control loop is bad and should be avoided. However, printing periodically involves annoying boilerplate, would be good to move that boilerplate to a function.

tunable needs additional documentation

Needs clarification for users who aren't familiar with python properties.

Additionally, it needs a better error message when you access it before createObjects is finished.

NavX is broken in latest WPILib

04:56:36:580 WARNING : navx                : Error reading configuration data, retrying (CRC error)
04:56:37:086 WARNING : navx                : Error reading configuration data, retrying (CRC error)
04:56:37:590 WARNING : navx                : Error reading configuration data, retrying (CRC error)
04:56:38:093 WARNING : navx                : Error reading configuration data, retrying (CRC error)
04:56:38:597 WARNING : navx                : Error reading configuration data, retrying (CRC error)
04:56:39:099 WARNING : navx                : -- Did not get configuration data
04:56:39:104 ERROR   : navx                : Error getting data
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/robotpy_ext/common_drivers/navx/registerio.py", line 101, in run
    self.getCurrentData()
  File "/usr/local/lib/python3.6/site-packages/robotpy_ext/common_drivers/navx/registerio.py", line 163, in getCurrentData
    curr_data = self.io_provider.read(first_address, read_count)
  File "/usr/local/lib/python3.6/site-packages/robotpy_ext/common_drivers/navx/registerio_spi.py", line 74, in read
    raise IOError("CRC error")
OSError: CRC error


Locals at innermost frame:

{ 'count': 82,
  'crc': 255,
  'data': [ 255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
            255,
...

New command-based framework

WPILib 2020 has a rewrite of the command framework. We should think about how the commandbased wrapper here should interact with it.

My thoughts:

  • Cancel robotpy/robotpy-wpilib#195, as the new command framework seems to actually be sane.
  • We deprecate the existing commandbased package as loudly as possible.
  • We then create a new package robotpy_ext.command (name bikesheddable) with a new CommandBasedRobot that uses the new scheduler.
  • Any of the control flow helper stuff can be ported by whoever wants to.

Thoughts?

/cc @FRC2539 @Tyler-Duckworth

magicbot: Add marker to cause variables to be reset

Magicbot programs have some boilerplate involved with variables that get reset at the end of each execute loop. An idea I have is to mark some variables to be reset to defaults at the end of each loop.

Notionally, a component using this functionality would look like this:

class Climber:
  motor = wpilib.Talon
  do_climb = magic_reset_to(False)

  def climb(self):
    self.do_climb = True

  def execute(self):
    self.motor.set(1 if self.do_climb else 0)

I imagine the implementation would be similar to how tunable is implemented: an object is stored on the class, and then at initialization time the object is switched with the default value. At the end of every loop, the defaults are placed. I imagine an efficient implementation would just store a per-class dictionary, and then do component.__dict__.update(defaults).

Haven't decided on a name for the marker yet. Some proposals were:

  • magicreset
  • magicdefault
  • magicDefaultTo
  • magic_reset_to
  • will_reset_to
  • magic_loop_var

Other proposals accepted!

AutonomousModeSelector: Consider allowing teams to use own timings

We should consider allowing teams to let the robot class deal with timing rather than enforcing our own. Currently this means that AutonomousModeSelector cannot be used with TimedRobot, unless if it were run in a separate thread (bad idea, please don't do this).

The only major problem I can foresee is that there'd be no way to call an on_disable. I wonder how many teams actually find an on_disable in their autonomous modes to be useful in the first place though.

Add debug version of MagicRobot

This could do a number of things that would be useful:

  • Keep track of various timing stuff related to components and sent to NetworkTables
    • Main control loop timing
    • Per-component execution tracking
  • On some trigger, capture profiling information and store it somewhere

magicbot: tunables shuffleboard integration ala oblog

I had already been thinking about something vaguely similar even before shuffleboard (though, thinking about the integration via pynetworktables2js), but this seems like it would be convenient. Haven't looked very hard at the shuffleboard APIs to see if it's even possible or a good idea yet.

Calling the super() methods in robot.py is required for command code, but outputs a warning that they need to be overridden.

Ideally, this shouldn't be terrible to fix, and it isn't a real problem, but having to call the super() methods can be confusing and not doing it causes the scheduler to fail. The methods work now as such: default autonomousPeriodic/teleopPeriodic/etc = a(), your overriding version of a() = b(). Currently, a() is called by default. If a() is overridden by b(), b() is called, but then b() must call a() using super().a(). Because you always have to call the default in some way, users always receive the "override me" message. Ideally, the change should be implemented only for a commend based robot, and it would work as such: Equivalent to the old default function minus the "Override me" message = a(), function with just the "override me" message = b(), your overriding version of the old a() = c(). [note: c() actually overrides b()] By default, a() would always be called. a() runs the scheduler and other default stuff then calls b(). b() runs only if it has not been overridden by c(). If b() has been overridden, c() runs instead. Now teams with command based code would no longer have to run the super() methods, and would only receive the "override me" message when they have not overridden the default periodic method. Sorry if this seems a bit rambly, its late at night and I want to register this thought somewhere so either I or someone else can get around to fixing it later. I plan on fixing this once I finish my competition code if someone else doesn't do it first.

Update navX library for 2018

There's been a number of changes in WPILib that have necessitated changes to the navX library. kauailabs/navxmxp@73aa4ea84010 in particular sticks out to me.

@virtuald I was taking a brief look at this earlier, and I noticed the commit referenced in the git-source-track line in ahrs.py is from 2016. Judging by the code, I'm guessing that wasn't intended?

NavX getRate() not working

It seems that getRate() stopped working due to an update within the past two weeks. Now when the NavX is not rotating, getRate() returns 360 degrees per second. However, getAngle() still seems to work fine. Unfortunately, I did not have enough time today to play with the NavX to see if the offset of 360 degrees per second was consistent. In case it's relevant, I'm using spi.

Create new SD Table for automodes

Currently, autonomous variables add variables to the path SmartDashboard/MODE/VAR, but they are all under the SmartDashboard table. I propose creating a new table for each Automode, so they show up under their own folder. Much cleaner that way

NavX MXP support

I'm working on it and it partially works, we'll see if I get it in before kickoff.

MagicBot StateMachine breaks when its last state is timed and has a default state

In the example below I would expect after b is done the state machine would transition to either the default or a state. Instead the console shows the state machine switching back and forth between the default and a state (it never transitions from a to b). If you run this code in the simulator with teleop enabled the console shows this:

19:36:23:486 WARNING : robot : Default MagicRobot.disabledPeriodic() method... Overload me!
19:36:23:642 INFO : nt : CONNECTED 127.0.0.1 port 51670 (pynetworktables 2017.0.8)
19:36:23:685 WARNING : pyfrc.sim.ui : pygame not detected, real joystick support not loaded
a
b
default
a
default
a
default
a
default
a
default

Calling the StateMachine done method seems to fix this issue, maybe it should be called automatically at the end of the final state?

Here's the code:

#!/usr/bin/env python3

import wpilib
from magicbot import StateMachine, state, timed_state, MagicRobot
from magicbot.state_machine import default_state

class SM(StateMachine):

    @default_state
    def d(self):
        print('default')

    @state(first=True)
    def a(self):
        print('a')
        self.next_state('b')

    @timed_state(duration=.01)
    def b(self):
        print('b')


class MyRobot(MagicRobot):

    sm = SM

    def createObjects(self):
        pass

    def teleopPeriodic(self):
        self.sm.engage()


if __name__ == "__main__":
    wpilib.run(MyRobot)

AttributeError: "SimpleWatchdog" object has no attribute "printEpochs"

A CSA needed help at an event where the team's code is crashing in autonomous. They aren't using a selector for it and are just running teleop code in autonomous and are getting errors on code pushed in commit #141 on line 273. I suggested to revert back to the previous version of robotpy just to be sure that it's just that change that broke it.

Console from driver station is included. They updated to .3 after their last competition that was running .2

Code Image

Support NavX enhancements

Probably visit this in November/December, but a few things have been added recently:

  • 100/200Hz update rates (will that even work well in Python, or too much CPU?)
  • Timestamp retrieval from serial packets

magicbot: add feedback tunable

Example:

class Component:
    # this would automatically set an NT value at /components/component/angle
    @feedback
    def get_angle(self):
        return ... 

There's a few things I would like to solve:

  • Need to provide sensor feedback in disabled mode -- would like to avoid adding extra user code to make that happen
  • Would like to cache variables read at the beginning of each control loop, to avoid potential race conditions

Common device driver library

There are countless devices in FRC, so it is understandable that there aren't device-specific drivers for all of them. Perhaps there could be a central library with drivers for many of the common sensors and devices that teams are likely to use, yet not built into wpilib? They could extend from the wpilib objects, and be a group effort to support as many devices as teams use. A few examples for drivers:

MaxBotics ultrasonic sensor
Nxt light sensor

Also, I am unsure of how exactly this might be done, but perhaps the drivers could pass data to the simulator enviornments (Similar to how you could set labels in 2014 pyfrc) to help display the sensors appropriately (eg, show real values vs raw sensor input values)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.