robotpy / robotpy-wpilib-utilities Goto Github PK
View Code? Open in Web Editor NEWUseful utility functions/objects for RobotPy
License: BSD 3-Clause "New" or "Revised" License
Useful utility functions/objects for RobotPy
License: BSD 3-Clause "New" or "Revised" License
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.
Would that be a useful tool for users to understand what they created?
Seems like a reasonable thing to do.
Oops.
The isDisplacmentSupported() method returns false in the simulator
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.
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.
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?
This is solvable, and fixing it should make the period more stable when things go south.
The 2016 version works on the 2017 image with the 2016 firmware. No idea if the new firmware will work yet.
This could do a number of things that would be useful:
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.
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.
Similar to robotpy-ctre
Hi @virtuald and @PeterJohnson,
I think it's confusing that there are higher and lower level components. I like the way that @frc1418 had components
and automations
. I think updating this in the docs would make it easier for beginners to understand the difference, and it would be good for them to live in separate folders.
Need to update that.
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
I'm working on it and it partially works, we'll see if I get it in before kickoff.
Slightly inspired by a planned feature in Oblarg's Oblog.
Idea: Add a convenient way of calling a setter over NT to magicbot.
Strawman:
feedback
decorator, a set_
prefix will be stripped from the name used for NT keys.tunable
and feedback
.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:
...
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:
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.
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?).
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,
...
Currently breaks. I fixed it, just need to push it.
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)
Initial content:
Our code is crashing during autonomous with the above stated error.
Let's avoid reinventing the wheel.
Need to come up with a good pattern to do this.
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
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:
Other proposals accepted!
WPILib 2020 has a rewrite of the command framework. We should think about how the commandbased wrapper here should interact with it.
My thoughts:
robotpy_ext.command
(name bikesheddable) with a new CommandBasedRobot
that uses the new scheduler.Thoughts?
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.
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.
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.
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.
Seems like a common enough thing. I don't have an XBox controller to test with, however.
A place for nt value updates would be nice
Probably visit this in November/December, but a few things have been added recently:
If this isn't done, then it makes it very difficult to do one-time initialization that involves other components (such as motors), though arguably it should be done in robot.py?
From kauailabs/navxmxp@7a1a601
The bug is observable in simulation, working on a fix.
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.
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)
Due to the changes to SendableChooser this season.
We should have an official prescribed way to do this. Ideas?
Might want to use this for PreciseDelay also, which needs to be revisited.
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.
Pressing the joystick buttons doesn't cause robot to turn like the code says it should.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.