PyCroCart
Pycrocart is a python implemented GUI that rather than interfacing with the rich Microcart infrastructure of the backend and the rest of the quads, is connected only to cflib which can be used to connect to crazyflie based quadcopters. While it is intended to eventually be slotted into the Microcart infrastructure, it is also able to function without it. This allows it to be used both as a debugging tool to define whether a bug exists in the backend, or the GUI. It also eliminates a many year buildup of technical debt and poor documentation in the GUI. Furthermore, in case the backend still has lots of issues like it does for our team (sdmay23), but you still need to run MP4 with crazyflies, you can use this GUI to act as a more stable version which will hopefully allow students to complain less about random crashes and more about how they can't get their PID to work the way they think it should.
Pycrocart is implemented using PyQT, and it uses cflib in order to integrate with a crazyflie. The intention is that we will be able to use the TCP connection example that bitcraze offers in order to connect to the FlyPi as well. This will be easier to implement than connecting to the MicroCART backend, which should be the ultimate end goal.
Requirements
Developed with Python 3.11
Library requirements can be installed in a venv via requirements.txt.
How to run
Pycrocart was developed in Pycharm and will work best when used in pycharm. As of right now, in order to use it you must have a crazyradio plugged into your computer, and a drone turned on and on the same uri as said in the __ main__ function. The default right now is 120. Hopefully we will have a connect button soon so that you can start the gui up and connect to a crazyradio dongle and drone during runtime.
In order to run the program from the command line enter:
python ./Pycrocart.py
This will execute the program and if all went well you should see the GUI appear.
You can also run it from Pycharm by clicking the run button near the
__ main__ function inside the Pycrocart.py script.
How to use
The pycrocart GUI has several windows: the controls window, the gamepad configuration window, the logging configuration window, and the parameter window.
Controls Tab
Seen above, the controls tab is the first page shown when entering the GUI. The controls tab features a setpoint menu which allows the user to send setpoints of thrust, yaw, pitch, and roll. It can do this in rate mode (yaw rate, pitch rate, roll rate) or attitude mode which controls the raw angles themselves. When gamepad mode is enabled the setpoints enter a "mixed" control mode. This lets the pitch and roll angles to be set directly but the yaw is not. Instead, the user controls the yaw rate, and the controller will hold the yaw angle it accumulates to.
Also in the controls tab is a logging selection menu. This allows the user to select up to 5 logging signals to plot in the plotting window which covers the entire right-hand portion of the controls tab.
Gamepad Configuration Tab
Seen below, the gamepad tab is used in order to configure the gamepad to detect each axis of control correctly. The detect button is used in order to detect when a joystick or button is pressed. This is a copy paste of the gamepad configuration tab in cfclient. If you would like more documentation of how to use it please see the bitcraze wiki. As of right now, in order to use a gamepad, it must be connected to the computer at launch of pycrocart. The logitech controller has been saved, at least on my computer as logitech. Theoretically, other controllers can be connected as well but this has not been tested by me.
To connect a controller once the program is running, click configure, select logitech from the combo box at the bottom of the page and click load to load the logitech controller configuration. You can also save a configuration. If you do not click load, a different mapping of inputs will be used. If you do not click configure, no input from the gamepad will be used.
Parameter Tab
Seen below, the parameter tab is able to be used in order to either set individual parameter values, or whole groups of parameters. There is also a parameter json file which can be opened by clicking edit from the UI. These parameters will be sent to the crazyflie whenever the set params from json file is pressed. Due to the amount of data being sent, a slight delay has been added to ensure that parameter is set successfully. While there are default groups within the file for attitude rate and attitude PID's, the file is also capable of setting other parameters and groups. Anything that is able to be set from the set parameter interaction is able to be set from the file.
Logging Tab
Seen below, the logging tab is used in order to configure logging on the crazyflie. The signals that are logged are configured within the logging block setup file. These will then be in use whenever the refresh logging blocks button is pressed. The signals available to be logged are read directly from the drones table of contents and change based on what is available from the firmware of the quad itself. These signals are all listed on the left hand side of the tab, which can be useful for knowing what to write in the logging block setup file.
The file itself is a json file which contains several logging groups. Each of these groups has an independent update frequency. Due to the way the crazyflie firmware works, no more than 5 signals are able to be used in a single group, and no more than 4 groups are able to be used period. If you attempt to, the GUI will throw an error in the window at you telling you to do something else. The signals of a group are configured within the vars array. Each group also has an independent update frequency in milliseconds. The maximum update frequency in ms is just over 20 ms, which is also the update rate of the controller in the crazyflie itself.
The logging blocks in the file are what controls what signals are available in the controls window.
Architecture
I cannot verify that the architecture of pycrocart is highly optimal, but I can tell you how it works, because I threw this thing together in a week and a half. So first things first, take some time to learn PyQT. It IS NOT hard. You just need to get a little used to how it works. One of the most useful things to know is timers and callbacks, which are pretty common in other languages but rarely seen in python.
Now that you understand PyQT, lets abstract away from PyQT. The GUI handles its connection to a gamepad. The way the gamepad is connected was 100% stolen from the cfclient source code, and is utilized as a Joystick reader. This is passed into the SetpointHandler whenever the gamepad is enabled, and the raw manual setpoint is passed in whenever the gamepad is not enabled.
The GUI is connected to a CrazyflieProtoConnection. This class began as a way to mock a crazyflie connection, and evolved into a way to manage the crazyflie connection. This is what handles the Synchronous Crazyflie Connection that is commonly used in cflib example code. Any information the GUI requires, or tries to manipulate passes through the CrazyflieProtoConnection.
Cflib is the open source crazyflie control library. It has a ton of already implemented methods that handle connecting to a crazyradio, and sending commands. There are more commands cflib is capable of that we do not utilize. We have implemented code using the low level commander controls, but there exist types of setpoints in the low level commander that the GUI does not use. There is also a HighLevelCommander that can do things such as "take off" or "land". This is commonly used on full positional controllers. One of the guiding reasons for why this GUI works well is leveraging cflib. My understanding of what the current CrazyflieGroundStation does is that it acts as an in house total rewrite of cflib. This makes little sense for why it exists other than being able to say we did it ourselves. CrazyflieGroundStation should be rewritten so that it works with the crazyflie adapter to adapt Microcart commands into something that can be used with cflib. Cflib is open source, supported by a large community, and continuing development.
The only thing that was changed with cflib in order to get pycrocart to function was the implementation of a custom uCartCommander. This simply adds commands possible to be sent to a crazyflie, while leaving the rest of the cflib source code unaltered. This is how the set attitude, and set attitude rates are accomplished. Similarly, these custom setpoints are also added to the firmware on the crazyflie. These were added to the source code by I believe the sdmay22 team, and are a great way to allow MP4 to have access to tune a full attitude controller.
One important thing to note is that while the GUI is responsive, there is zero multithreading/processing happening in order to make this the case. Instead, a system of timers and callback functions have been used in order to accomplish things in a timely manner. This does not mean that there are not issues when using shared resources though. For this reason, I've tried to use semaphores and locks whenever working with something that is accessed via timers.