View Full Version : RobotPy: Python for FRC
Peter Johnson
26-10-2010, 00:49
After being inspired by Ross Light and Team 973's success in porting Lua to the cRIO (see the "Announcing FIRSTLua" thread), I have completed a port of Python to the cRIO, called RobotPy.
RobotPy is a fully functioning port of Python 3.1.2 that can be used for programming your FRC robot. The full set of WPILib functions, including CANJaguar, is available in Python via "import wpilib".
As with the Lua port,
Python is easier to learn than C
Live code reloads
Errors won't crash the robot
Python provides automatic garbage collection
WindRiver isn't needed after the base code is installed. Just a text editor and an FTP client.
I've performed some initial testing on Team 294's 2010 robot, including running CAN bus Jaguars and compressors and pneumatics. Examples and installation documentation are available on the website and are also included in the download. Also, the download .zip file includes a prebuilt FRC_UserProgram.out, so you don't need to have any programming software installed to get up and running (just FTP a bunch of files to your robot)! Please report any bugs you find via the RobotPy website's ticket system (note: registration is required).
RobotPy website: http://www.tortall.net/projects/robotpy/
While the download .zip doesn't include the source code, it is available via a git repository. See the Download page on the website for details.
With the exception of modules with large dependencies (e.g. databases), almost all of the Python standard library is included. So yes, you can parse XML files with expat on the robot if you so choose :). Much of this is untested however (I have not tried to run the Python test suite on the robot).
Major thanks go to Ross Light and Team 973; this project would not have happened without them creating FIRSTLua first to inspire me to port Python. RobotPy uses the WPILib SWIG wrapper created by Ross, with the addition of CANJaguar. The idea of using a boot script to auto-reload the user code is also taken from FIRSTLua.
Robototes2412
26-10-2010, 01:18
thank you so much :)
I'm already porting my team's high level motor grouper and pneumatics classes, I'm hoping these can be included with your permission, of course
Peter Johnson
26-10-2010, 01:42
I'm already porting my team's high level motor grouper and pneumatics classes, I'm hoping these can be included with your permission, of course
Of course! I'd love to build up and include (maybe as a separate download) a library of team-built robot-oriented Python modules. And if anyone has suggestions on any other common/useful modules to include, I'll look at adding them as well (NumPy and SciPy come to mind, for example).
Robototes2412
26-10-2010, 01:47
I have most of the common inputs that my team used coded in python for prototyping, so I will be done with the whole thing by tomorrow
AustinSchuh
26-10-2010, 02:09
Of course! I'd love to build up and include (maybe as a separate download) a library of team-built robot-oriented Python modules. And if anyone has suggestions on any other common/useful modules to include, I'll look at adding them as well (NumPy and SciPy come to mind, for example).
If you don't get to it first, I'm going to try to port NumPy and SciPy to the cRIO. I've been using those for prototyping up control loops on my desktop, and they are really nice.
Do sockets work? That would make it easy to add a telnet server to the robot, and allow remote execution of code to aid testing. Also, does print work correctly?
Thanks again for doing this! I'm really excited.
Peter Johnson
26-10-2010, 02:22
If you don't get to it first, I'm going to try to port NumPy and SciPy to the cRIO. I've been using those for prototyping up control loops on my desktop, and they are really nice.
Do sockets work? That would make it easy to add a telnet server to the robot, and allow remote execution of code to aid testing. Also, does print work correctly?
I haven't tested sockets yet. Theoretically they should work, but a lot has to be correct for them to work, and I might have missed something.
Yes, print works correctly.
Feel free to tackle NumPy and SciPy. FYI, to date, I've been integrating C/C++ modules directly into Python/Lib and Python/Modules/ (and updating Modules/config.c to add them to _PyImport_Inittab), because it's all a static executable anyway.
AustinSchuh
26-10-2010, 02:49
I haven't tested sockets yet. Theoretically they should work, but a lot has to be correct for them to work, and I might have missed something.
Yes, print works correctly.
Feel free to tackle NumPy and SciPy. FYI, to date, I've been integrating C/C++ modules directly into Python/Lib and Python/Modules/ (and updating Modules/config.c to add them to _PyImport_Inittab), because it's all a static executable anyway.
Thanks for the information. Unfortunately my course load is quite high this semester, so it might be quite a number of weeks until I get to NumPy and SciPy. But they are definitely on the list of things to do, and I'll let you know when I get time and get somewhere with them.
Robototes2412
26-10-2010, 09:44
where does print go?
Peter Johnson
26-10-2010, 12:39
where does print go?
The cRIO console. There's a couple different ways to see it; NetConsole is probably the best (see http://www.chiefdelphi.com/forums/showthread.php?t=80146).
Robototes2412
26-10-2010, 18:41
I have basic driving functions and inputs programmed:
output.py
#Made by Sam Dodrill for Team 2412, WTFPL
from wpilib import Victor, Solenoid
import wpilib
import math
class Driver:
def __init__(self, FL, FR, RL = None, RR = None):
self.FLvictor = Victor(FL)
self.FRvictor = Victor(FR)
if RL != None and RR != None:become standard for the interpreter :)
self.RLvictor = Victor(RL)
self.RRvictor = Victor(RR)
self.fourWheel = True
def drive(self, speed):
self.FLvictor.Set(speed)
self.FRvictor.Set(-speed)
if fourWheel:
self.RLvictor.Set(speed)
self.RRvictor.Set(-speed)
def tankDrive(self, left, right):
self.FLvictor.Set(left)
self.FRvictor.Set(-right)
if fourWheel:
self.RLvictor.Set(left)
self.FRvictor.Set(-right)
def limit(self, n):
if n > 1:
return 1
elif n < -1:
return -1
else:
return n
def arcadeDrive(self, speed, direction):
left = speed - direction
right = speed + direction
maxi = max(left, right)
if maxi > 1:
left = left/maxi
right = right/maxi
left = limit(left)
right = limit(right)
self.tankDrive(left, right)
def holonomicDrive(self, power, slide, spin):
fl = power + slide + spin
fr = power - slide - spin
rl = power - slide + spin
rr = power + slide - spin
fl = limit(fl);
fr = limit(fr);
rl = limit(rl);
rr = limit(rr);
self.setSpeed(fl, fr, rl, rr)
def setSpeed(self, fl, fr, rl, rr):
self.FLvictor.Set(fl)
self.FRvictor.Set(-fr)
self.RLvictor.Set(rl)
self.RRvictor.Set(-rr)
def goLeft(self):
self.holonomicDrive(0, 0.5, 0)
def goRight(self):
self.holonomicDrive(0, -0.5, 0)
def goForward(self):
self.holonomicDrive(0.5, 0, 0)
def goBackward(self):
self.holonomicDrive(-0.5, 0, 0)
def turnLeft(self):
self.holonomicDrive(0, 0, -0.5)
def turnRight(self):
self.holonomicDrive(0, 0, 0.5)
def stop(self):
print("OH CRAP")
self.drive(0)
input.py:
#made by Sam Dodrill for team 2412, but you can use it too
import wpilib, math
class Attack3:
def __init__(self, port)
self.joy = wpilib.Joystick(port)
def getX(self):
return self.joy.GetRawAxis(2)
def getY(self):
return self.joy.GetRawAxis(1)
def getThrottle(self):
return self.joy.GetRawAxis(3)
def getTrigger(self):
return self.joy.GetRawButton(1)
def get2(self):
return self.joy.GetRawButton(2)
def get3(self):
return self.joy.GetRawButton(3)
def get4(self):
return self.joy.GetRawButton(4)
#yada yada yada, TODO: finish with all 11 buttons
def calcBuffer(self, n):
buffers = 0.2
if math.abs(n) < buffers:
n = 0
return n
class Xbox:
def __init__(self, port):
self.joy = wpilib.Joystick(port)
def getStick(self, n1, n2): #returns a list in the form of [x,y]
r = list()
r.append(calcBuffer(self.joy.GetRawAxis(n1)))
r.append(calcBuffer(self.joy.GetRawAxis(n2)))
return r
def getLeftStick(self):
return self.getStick(1,2)
def getRightStick(self):
return self.getStick(4,5)
def getButtons(self, n1, n2, n3, n4): #returns a list in the form of [b1, b2, b3, b4]
r = list()
r.append(self.joy.GetRawButton(n1))
r.append(self.joy.GetRawButton(n2))
r.append(self.joy.GetRawButton(n3))
r.append(self.joy.GetRawButton(n4))
return r
def getMainButtons(self): #returns [a,b,x,y]
return self.getButtons(1, 2, 3, 4)
Robototes2412
26-10-2010, 19:43
Code Zipped up and is attatched.
First Release, nothing fancy
Peter Johnson
26-10-2010, 23:29
Thanks for the information. Unfortunately my course load is quite high this semester, so it might be quite a number of weeks until I get to NumPy and SciPy. But they are definitely on the list of things to do, and I'll let you know when I get time and get somewhere with them.
I glanced at NumPy/SciPy. NumPy should be straightforward. SciPy, however, requires a Fortran compiler, which isn't included with WindRiver. It should be possible to build a cross-compiler but it will definitely take more work.
AustinSchuh
27-10-2010, 00:58
I glanced at NumPy/SciPy. NumPy should be straightforward. SciPy, however, requires a Fortran compiler, which isn't included with WindRiver. It should be possible to build a cross-compiler but it will definitely take more work.
Hmm. That does complicate things. Something else to add to the list of prereqs for SciPy. It looks like some of what I assumed was in SciPy is also in NumPy (matricies, for example) so NumPy might be enough. At the very least, it'll help quite a bit.
virtuald
27-10-2010, 09:14
This is totally awesome. When I saw the Lua thing, I was thinking the same thing, so I'm glad someone took the time to do it. I'll have to try it on the bot later.
I'm super excited to see this! I love Python as a langue, and I can't wait to maybe load this on a practice robot.
Peter Johnson
28-10-2010, 01:48
I've implemented dynamic loading of C modules. The next release of RobotPy will break out many of the C modules into separate loadable object files, the same way that normal Python does. These separate .out files are located in /lib/python3.1/dyn-load on the robot, so they won't clutter up the /ni-rt/system directory.
This should also make distributing other modules (e.g. NumPy) easier, as they can be distributed as separate .zip packages without having to integrate them into the RobotPy executable.
I'm also going to make the wpilib module dynamically loaded. This will make it easier to test with different/beta/custom versions of WPILib. This reduces the size of the basic Python executable down to ~3.5M; the wpilib module is ~5M!
EricS-Team180
02-11-2010, 19:14
After they were blown away with WindRiver/C++ last season, I introduced the controls and software team to Python by taking part in Team 342's summerpygames (http://www.summerpygames.org). They got the hang of it and are asking for more. This is perfect! :cool:
We'll give it a try.
Thanks,
Eric
EricS-Team180
03-11-2010, 17:31
Hmm. That does complicate things. Something else to add to the list of prereqs for SciPy. It looks like some of what I assumed was in SciPy is also in NumPy (matricies, for example) so NumPy might be enough. At the very least, it'll help quite a bit.
...just a thought. You might be able to f2c the FORTRAN. I've had success with this with older versions of vxWorks.
Tom Bottiglieri
04-11-2010, 12:53
A bit off topic, but the book "Learn Python The Hard Way" seems like a great guide to learning how to program, using Python. (Different than learning how to use Python :p)
This might be good supplement to RobotPy.
http://learnpythonthehardway.org/index
andreboos
06-11-2010, 17:23
I built the most recent version from source. The make_dist.bat file copies the loadable modules to "dyn-load", but Python looks for the modules in the "lib-dynload" directory. I fixed the bat file to reflect this, and it works fine now. Before, boot.py couldn't find the time library and aborted.
I post this here because the discussion boards on FIRST Forge are limited to project members (total project members: 1).
Peter Johnson
06-11-2010, 18:23
I built the most recent version from source. The make_dist.bat file copies the loadable modules to "dyn-load", but Python looks for the modules in the "lib-dynload" directory. I fixed the bat file to reflect this, and it works fine now. Before, boot.py couldn't find the time library and aborted.
I post this here because the discussion boards on FIRST Forge are limited to project members (total project members: 1).
Sorry about the problem, although you shouldn't have seen it with the latest git sources (it was fixed in http://git.tortall.net/cgit.cgi/RobotPy.git/commit/?id=ccd7d79a2ddcda39751ca3f1f49b7ade9051151a). The zip files have also been updated.
You should be able to request project membership on FIRST Forge to post there... let me know if you are unable to for some reason; maybe there's a setting I missed. Thanks!
andreboos
06-11-2010, 22:51
Hmm. I checked out from the git repository just this morning. However, all the other files seem to match the most recent changeset, so maybe it's a client-side issue.
Anyways, I'm happy to report that I've finished porting last year's code to Python, and as a separate project, modified our existing C++ code to load Python to run an autonomous script that our drive team can edit while queuing for a match with alliance members, with surprising ease. I copied the RobotPy/Python directory and the wchar.h and wchar.c files into the old directory, expanded the include paths to include the root directory (containing the wchar files), /Python/, and /Python/Include/, and compiled. In our autonomous method I put the contents of RobotTask(), replacing ROBOTPY_BOOT with the path (on the robot) to our Python autonomous script. Then I uploaded the resulting .out file to the robot, leaving the existing Python libraries intact.
NetConsole shows many error messages about duplicate symbols when Autonomous mode starts, probably as a result of linking WPILib to the C++ code and also loading the _wpilib.out from RobotPy. However, WPILib also throws (fatal) "resource resuse [sic]" errors when WPILib instances from the Python code are not properly deleted before the script ends and the same resources are used in teleoperated code. I'm still resolving the kinks in WPILib on Python, but Python itself runs fine.
Peter Johnson
07-11-2010, 19:55
However, WPILib also throws (fatal) "resource resuse [sic]" errors when WPILib instances from the Python code are not properly deleted before the script ends and the same resources are used in teleoperated code. I'm still resolving the kinks in WPILib on Python, but Python itself runs fine.
Unfortunately I haven't yet been able to get Python to always call the WPILib destructors. It does seem to call them if you explicitly del the WPILib Python variables, but that's obviously non-ideal. I'm actively trying to get this fixed (it's tied in with how Python unloads modules, so it's somewhat of a pain). Note it'll probably always be necessary to call gc.collect() explicitly to ensure the objects are destroyed (the default boot.py will do this).
Glad you were able to have some early success even not using the library how it's designed (as a full-up Python solution)!
dbeckwith
15-11-2010, 14:57
Python sounds great! Is it legal for the 2010 season? And are there handlers or image-recognition algorithims for the camera?
Peter Johnson
16-11-2010, 01:26
Python sounds great! Is it legal for the 2010 season? And are there handlers or image-recognition algorithims for the camera?
You mean the 2011 season? See the second FAQ (http://firstforge.wpi.edu/sf/wiki/do/viewPage/projects.robotpy/wiki/Faq) for the full answer (and a caveat emptor warning). Basically I can't say as I'm not the GDC and can't predict future rules, but I see no reason why it wouldn't be legal according to the 2010 rules. Python itself is available to all teams and thus should be considered COTS code, and to the robot it looks like a C++ program that reads text files.
With regards to the image recognition suite (WPILib Vision library), there's currently no wrappers but it should a straightforward project for an enterprising person who wants to learn a bit about SWIG (see Packages\wpilib\wpilib.i in the source tree).
Hi,
We are a rookie team (temp# 2012085) interested in using RobotPy. Any recommendations on how to start preparing (websites, tutorials, etc).
Thank you!!
z_beeblebrox
16-10-2012, 21:15
I'm very sorry to bring back an old thread, but I'm wondering if this project has gone anywhere since 2010. If not, would everything in it still work? I've heard some very good things about Python, so am curious about maybe using it next year.
Peter Johnson
17-10-2012, 01:32
I'm very sorry to bring back an old thread, but I'm wondering if this project has gone anywhere since 2010. If not, would everything in it still work? I've heard some very good things about Python, so am curious about maybe using it next year.
Yes, we've continued to update it (generally as part of the beta test so it's fully up to date by the time of kickoff). For example, last year we updated it to support the Kinect. Team 294 has used in in competition in both 2011 and 2012 and plan to continue doing so in future years. I believe there are a handful of other teams out there using it as well.
virtuald
17-10-2012, 11:46
As Peter said, RobotPy still works and is being maintained. There's a bunch of resources included with the RobotPy distribution, and my team has released our robot code (http://www.virtualroadside.com/FRC/) the last two years, both of which are written in python.
vBulletin® v3.6.4, Copyright ©2000-2017, Jelsoft Enterprises Ltd.