Winpdb Remote Debugger ported to RobotPy

Hey, I’ve been playing with RobotPy quite a bit lately, and one thing you’ll probably note is that debugging scripts is a bit annoying. Ok, more than just a bit annoying… haha. Anyways, here’s a great solution to solve that problem! Winpdbis a GPL remote debugger that works pretty well from what I can see so far, and gives you full source debugging over the network. I’ve modified it a bit so that it works on RobotPy. Check it out:

http://www.virtualroadside.com/blog/index.php/2011/01/11/winpdb-remote-debugger-for-python-ported-to-robotpy-on-vxworks/

Note: Contrary to its name, Winpdb is cross platform, it just requires wxPython to run.

Sounds like this will really help! Unfortunately, I can’t try it out on our robot until Monday. D:

Speaking of debugging, have you found a way to compile and check your scripts before running on the robot?

In Java NetBeans would compile our code locally and show where we had syntax errors or improper API calls, but with Python we don’t find this out until runtime. This makes it hard to work on code when there is no robot access, since someone’s usually working on it mechanically.

So far I can check syntax with:
python3.1 -c “import py_compile; py_compile.compile(‘robot.py’)”

However that does not seem to catch many of the problems we’ll run into, like misspelling function names and other common errors.

Any ideas?

Indeed that’s the downside of using a dynamic language… static analysis is pretty much impossible (look up the halting problem). The long term solution will be a robot simulator (written in Python?) that provides an emulated Python wpilib so you can test your code offline. I’ve started looking at this but it’s a pretty large project (the simulator is hard enough but there’s also a LOT of wpilib classes to write emulated versions of).

i have a virtual robot thing half put together

#This file should emulate enough of wpilib to make it usable for testing
#DONE: use pygame to get joystick inputs from actual joysticks

print("="*40)
print("TESTING.PY LOADED, IF THIS IS ON THE ROBOT CALL SAM *NOW*")
print("NNN NNN NNNN")
print("="*40)

try:
    import pygame
    import pygame.joystick
    pygame.init()
    print(str(pygame.joystick.get_count()) + " Joysticks attatched")
    new = True
except:
    new = False
    print ("NO PYGAME FOUND")
        
def limit(n):
    if n > 1.0:
        return 1.0
    elif n < -1.0:
        return -1.0
    else:
        return n

class Victor:
    def __init__(self, port):
        self.port = port
        print("Virtual Victor set up on port " + str(port))
        self.speed = float()
    
    def Set(self, speed):
        """***FOR TESTING PURPOSES ONLY***
       This "sets" the virtual Victor to any arbitrary speed"""
        speed = limit(speed)
        print("on port " + str(self.port) + " the speed is now " + str(speed))
        self.speed = speed
    
    def Get(self):
        """***FOR TESTING PURPOSES ONLY***
       This emulates the wpilib.Victor.Get function"""
        return self.speed
        
class Joystick_old:
    def __init__(self, port):
        self.port = port
        print("New FAKE joystick set up at port "+str(port))
    
    def GetRawAxis(self, n):
        return float()
    
    def GetRawButton(self, n):
        return False

class Joystick_pygame:
    def __init__(self, port):
        self.port = port -1
        self.joy = pygame.joystick.Joystick(port-1)
        self.joy.init()
        print("made new pygame joystick on port " + str(port))
        print(self.joy.get_name())
        
    def GetRawAxis(self, n):
        pygame.event.pump()
        return self.joy.get_axis(n-1)
    
    def GetRawButton(self, n):
        pygame.event.pump()
        r = self.joy.get_button(n-1)
        if r == 1:
            return True
        else:
            return False

def Joystick(port):
    if new:
        print("trying to use awesomesauce new features")
        try:
            print ("can use awesome features")
            return Joystick_pygame(port)
        except:
            print ("cannot use awesome new features")
            return Joystick_old(port)
    else:
        print ("cannot use awesome new features")
        return Joystick_old(port)

def speedReport(list_obj):
    """Use this for the driver object"""
    for n in list_obj:
        n.Get()
        
def IsDisabled():
    return False   

def IsAutonomous():
    return False

def IsOperatorControl():
    return True
    
def IsEnabled():
    return True

class dummyDog:
    def SetEnabled(self, var):
        pass
    
    def SetExpiration(self, var):
        pass
    
    def Feed(self):
        pass
    
    def Kill(self):
        pass

def GetWatchdog():
    return dummyDog()

def Wait(n):
    pass

class Solenoid:
    def __init__(self, slot, port):
        self.slot = slot
        self.port = port
        print("Solenoid set up on slot " + str(slot) + " port " + str(port))
    
    def Get(self):
        return self.state
    
    def Set(self, state):
        self.state = state
        
        if state:
            print("port " + str(self.port) + " active")
        else:
            print("port " + str(self.port) + " inactive")

class Relay:
    def __init__(self, port):
        self.port = port
        print("Relay set up on port " + str(port))
        self.kForward = 1
        self.kOff     = 2
        self.kReverse = 3
    
    def Get(self):
        pass
    
    def Set(self, value):
        if value == self.kForward:
            print("relay forward")
        elif value == self.kOff:
            print ("relay off")
        elif value == self.kReverse:
            print ("relay backwards")

class Compressor:
    def __init__(self, port1, port2):
        pass
    def Start(self):
        print ("compressor on")
    def Stop(self):
        print ("compressor off")

class SimpleRobot():
    def StartCompetition():
        run_old()

edit:
Wow, i was high when i wrote this, pasted wrong file