I am going to come straight out and say that I have yet to actually test any of this code on a robot. The point of this is not to have anyone look over it and see if it will run or look for syntax errors or anything like that but to see if people would be interested in the concept behind the potential framework.
I am here to see the interest in my concept. I will continue developing for anyone who want’s it but any feedback/suggestions for the system would be awesome.
The idea is that you create individual modules (files) with classes in them that represent a system. In the like there is a drive module (drive.py) that represents a drive system. There is a method for teleop driving and one for autonomous driving for X amount of time at Y speed. The required objects to run the drive (Joysticks and Motors) are imported from the robotmap module at the top of the file along with a nifty Kalman filter I whipped up (have not documented yet). At the bottom of the drive.py there are 3 important lines. These lines import the scheduler instance, create a instance of the above class and register the DriveTeleop method to the scheduler as a task to be executed over and over during teleop. The DriveTeleop returns False always which means that it will never be removed from the scheduler.
In the robot.py on line 91 there is a method that is called RegisterAutonomous. This method registers our DriveForTime method from the instance of the Drive class called drive located in the drive module. It is registered as a sequential task then the time, and speed are specified. We then call this method on line 51 before we get into our autonomous loop. Once in the loop we execute the autonomous commands by calling scheduler.Autonomous() inside of the loop. After the loop is over we clear all the autonomous tasks incase they did not finish that way we may run autonomous again without rebooting the robot.
Running the teleop scheduler is as easy as calling scheduler.OperatorControl() inside of the teleop loop. We do not clear the teleop tasks after the loop though because the tasks have been registered in their individual modules.
There is another method called RegisterOperatorControlTaskIfNotAlready that will only register if there is not already a registered instance of that task. This is by name of the method not by the name you specify when you register it. This could be used for things like shooting. You have a button push run the method RegisterOperatorControlTaskIfNotAlready and try to schedual the kicker.kick method for example. This would then just “ignore” the push and continue with the kick until it resolves then if the button is still pushed it would register a new kicker.kick task.
This sounds very similar to the approach we took for Team 294’s Python robot code for the 2013 competition: https://github.com/team294/FRC2013.
While we started by splitting the teleop code amongst the various subsystems, we found this was somewhat error-prone due to e.g. joystick button mapping being spread around in a lot of different places, so we ended up consolidating all of the teleop code into one file, having it call into the subsystem interfaces. We reused the subsystem interfaces in our autonomous code.
Thanks. My idea was to have little/no code in the main robot class. I wanted to do something like the command base in java without all the bloat.
I see from your signature you were one of the creators of robotpy. I am a linux user and python is the latest language in my arsenal. I have not been able to successfully setup a test environment for robotpy using fake_wpilib.
Yes, I originally created RobotPy, but virtuald (Dustin Spicuzza) created fake-wpilib, and I’ve not taken the time to really familiarize myself with it. I assume you’ve read through http://www.chiefdelphi.com/forums/showthread.php?t=109678? Unfortunately, as far as I know, there’s not a formal tutorial available.
Thanks for the link. That looks like it will be handy. I have been thinking about starting a project to port the wpilib to JavaScript. As silly as that sounds, there are so many sources to learn JavaScript from and many of our students already know enough to get by if it was an option. Do you believe anyone would use it and what were your biggest challenges when porting it to Python?
We took a similar approach, except instead of having to register all of the modes in code somewhere, our mode manager enumerates all the files in a directory and registers them automatically if they contain the right class. Our 2012 code contains this pattern for autonomous mode if you’re interested. I haven’t released our 2013 code yet since I haven’t had time to clean it up…
fake-wpilib is pretty useful. What problems have you had getting your environment set up? If you use the included test.sh/test.bat files and set your paths correctly, it should all just work for the most part…
I got fake-wpilib running fine. I just had to look at it a bit and figure out how it worked. (I’m a have to know type of person). I am planning to expand the joystick functionality using pygame to use an actual joystick for testing.
Update:
A few more test cases have been added to allow emulating a full game, just autonomous or teleop or quick import testing.
Joystick emulation is done with PyGame if they are plugged in. If you have created two joystick objects and only have one plugged in the first will be usable and the second will return sudorandom numbers between -1 and 1.
You can now register timed autonomous tasks using RegisterAutonomousTimedTask. Both PARALLEL_TASK’s and SEQUENTIAL_TASK’s are supported.
I will be continuing to update this as I go and create a new thread once I have tested it on an actual robot.