robotpy / mostrobotpy

Official Repository of python implementation of WPILib components
https://robotpy.github.io
Other
11 stars 14 forks source link

New Feature: Single Step Debugger Support #49

Open gerth2 opened 11 months ago

gerth2 commented 11 months ago

Problem description

Basic debug support through debugpy works well today with vsCode.

Documenting this here for potential future integration.

Overall design goal: single-click debugger activation that lets you walk code line by line on a development computer, while execution is happening on the RIO.

1) Standard vsCode python extensions 2) install debugpy on both the RIO and local desktop 3) Add a vsCode task to start the robot in debug mode - for us, this involves dropping a blank file with a magic name in the RIO's filesystem, then restarting the robot code 4) a small snippet of code in the robot main code to detect the "wait for debugger" file trigger and wait for a debug connection.

tasks.json:

        {
            "label": "PyFRC: _Activate Debug",
            "type": "shell",
            "windows": {
                "command": "ssh lvuser@roboRIO-1736-FRC.local -t 'chmod +x ./robotCommand; touch /home/lvuser/py/enableDebug; ./robotCommand || true; echo Waiting for robot program to start...; sleep 5' "
            },
            "linux": {
                "command": "ssh lvuser@roboRIO-1736-FRC.local -t 'chmod +x ./robotCommand; touch /home/lvuser/py/enableDebug; ./robotCommand || true; echo Waiting for robot program to start...; sleep 5' "
            },
            "group": {
                "kind": "build",
            },
            "presentation": {
                "reveal": "always",
                "panel": "dedicated",
                "clear": true,
                "focus": true,
                "showReuseMessage": false
            },
            "problemMatcher": [],
            "icon": {
                "id": "cloud-upload"
            }
        },

launch.json:

...
        {
            "name": "Debug RoboRIO",
            "type": "python",
            "request": "attach",
            "connect": {
                "host": "roboRIO-1736-frc.local",
                "port": 5678
            },
            "pathMappings": [
                {
                    "localRoot": "${workspaceFolder}",
                    "remoteRoot": "/home/lvuser/py"
                }
            ],
            "justMyCode": true,
            "preLaunchTask": "PyFRC: _Activate Debug"
        },
...

Robot Code:

if __name__ == '__main__':

    enableDebug = os.path.isfile("/home/lvuser/py/enableDebug")
    if(enableDebug):
        print("Starting Debug Support....")
        import debugpy 
        debugpy.listen(('0.0.0.0', 5678))
        debugpy.wait_for_client()

    wpilib.run(MyRobot)

The real trick is just to make sure the robot code gets restarted with the correct value for enableDebug - it does slow down execution noticeably, and isn't something I think you'd want all the time.

I've got no idea if there's a better way than a file (environment variables?), but that just seemed to be the most reliable way.

One nice thingabout using a file: if the code is simply redeployed, the file is wiped away, so the code goes back to "normal/non-debug" mode.

Hopefully helps? Other than the funkiness of the file itself, I'd highly recommend the rest.

Operating System

Windows

Installed Python Packages

N/A

Reproducible example code

N/A
auscompgeek commented 11 months ago

you can deploy in debug mode already, no need for a complex ssh command

./robot.py deploy --debug

this can be detected with __debug__ e.g.


if __name__ == "__main__":
    if __debug__:
        try:
            import debugpy
        except ModuleNotFoundError:
            pass
        else:
            debugpy.listen(('0.0.0.0', 5678))

    wpilib.run(MyRobot)
gerth2 commented 11 months ago

that is way better than magic files. One moment please...

gerth2 commented 11 months ago

https://github.com/RobotCasserole1736/firstRoboPy/blob/chris_daves_dandy_debug_design/.vscode/tasks.json

https://github.com/RobotCasserole1736/firstRoboPy/blob/chris_daves_dandy_debug_design/robot.py#L117

Updated, works well.

Tasks is a bit more complex now, to keep a "single button" paradigm I had to chain together the deploy with --debug and a short pause to let the RIO get up and running before the host PC tries to connect (otherwise vscode was giving me a connection refused error)

Also, in the code stnippet, I added inspection to check that we were indeed running the code, not deploying or simulating. Otherwise, it's likely that debug is true, which will stall things out.

I do think it's valid for teams to want to be able to walk through robotInit(), so I included the debugpy.wait_for_client() call to facilitate that.

auscompgeek commented 11 months ago

See also previous discussion: https://github.com/robotpy/robotpy-wpilib/issues/99