From 3d8daf1ac6eb62b367deb7f7eda24f660a4851bc Mon Sep 17 00:00:00 2001 From: phfriedl <phfriedl@student.ethz.ch> Date: Mon, 3 Apr 2017 16:31:38 +0200 Subject: [PATCH] Updated crazyradio client library --- .../src/d_fall_pps/crazyradio/CrazyRadio.py | 8 +- .../crazyradio/cfclient/__init__.py | 37 +- .../crazyradio/cfclient/__init__.pyc | Bin 526 -> 0 bytes .../crazyradio/cfclient/cfclient.pyc | Bin 3443 -> 0 bytes .../crazyradio/cfclient/configs/config.json | 32 +- .../cfclient/configs/input/Generic_OS_X.json | 0 .../cfclient/configs/input/Joystick.json | 190 ++--- .../cfclient/configs/input/PS3_Mode_1.json | 0 .../cfclient/configs/input/PS3_Mode_2.json | 0 .../cfclient/configs/input/PS3_Mode_3.json | 98 +-- .../cfclient/configs/input/PS4_Mode_1.json | 106 +-- .../cfclient/configs/input/PS4_Mode_2.json | 106 +-- .../configs/input/PS4_shoulder_btns_yaw.json | 0 .../cfclient/configs/input/xbox360_mode1.json | 174 ++--- .../cfclient/configs/log/stabilizer.json | 0 .../cfclient/{cfclient.py => gui.py} | 66 +- .../crazyradio/cfclient/headless.py | 173 +++++ .../crazyradio/cfclient/icon-256.png | Bin .../crazyradio/cfclient/resources/map.html | 14 + .../crazyradio/cfclient/resources/map.js | 25 + .../crazyradio/cfclient/ui/__init__.py | 10 +- .../crazyradio/cfclient/ui/__init__.pyc | Bin 467 -> 0 bytes .../cfclient/ui/dialogs/__init__.py | 0 .../cfclient/ui/dialogs/__init__.pyc | Bin 171 -> 0 bytes .../crazyradio/cfclient/ui/dialogs/about.py | 122 ++-- .../crazyradio/cfclient/ui/dialogs/about.pyc | Bin 6672 -> 0 bytes .../crazyradio/cfclient/ui/dialogs/about.ui | 0 .../cfclient/ui/dialogs/bootloader.py | 52 +- .../cfclient/ui/dialogs/bootloader.pyc | Bin 11724 -> 0 bytes .../cfclient/ui/dialogs/bootloader.ui | 0 .../cfclient/ui/dialogs/cf1config.py | 51 +- .../cfclient/ui/dialogs/cf1config.pyc | Bin 11202 -> 0 bytes .../cfclient/ui/dialogs/cf1config.ui | 0 .../cfclient/ui/dialogs/cf2config.py | 36 +- .../cfclient/ui/dialogs/cf2config.pyc | Bin 4257 -> 0 bytes .../cfclient/ui/dialogs/cf2config.ui | 0 .../cfclient/ui/dialogs/connectiondialogue.py | 122 ---- .../ui/dialogs/connectiondialogue.pyc | Bin 4769 -> 0 bytes .../cfclient/ui/dialogs/connectiondialogue.ui | 102 --- .../ui/dialogs/inputconfigdialogue.py | 272 +++---- .../ui/dialogs/inputconfigdialogue.pyc | Bin 19318 -> 0 bytes .../ui/dialogs/inputconfigdialogue.ui | 10 +- .../cfclient/ui/dialogs/logconfigdialogue.py | 78 +- .../cfclient/ui/dialogs/logconfigdialogue.pyc | Bin 11145 -> 0 bytes .../cfclient/ui/dialogs/logconfigdialogue.ui | 0 .../d_fall_pps/crazyradio/cfclient/ui/main.py | 539 +++++++++----- .../crazyradio/cfclient/ui/main.pyc | Bin 22709 -> 0 bytes .../d_fall_pps/crazyradio/cfclient/ui/main.ui | 203 ++++-- .../crazyradio/cfclient/ui/pluginhelper.py | 7 +- .../crazyradio/cfclient/ui/pluginhelper.pyc | Bin 857 -> 0 bytes .../d_fall_pps/crazyradio/cfclient/ui/tab.py | 28 +- .../d_fall_pps/crazyradio/cfclient/ui/tab.pyc | Bin 2814 -> 0 bytes .../crazyradio/cfclient/ui/tabs/ConsoleTab.py | 60 +- .../cfclient/ui/tabs/ConsoleTab.pyc | Bin 1935 -> 0 bytes .../crazyradio/cfclient/ui/tabs/ExampleTab.py | 26 +- .../cfclient/ui/tabs/ExampleTab.pyc | Bin 4045 -> 0 bytes .../crazyradio/cfclient/ui/tabs/FlightTab.py | 295 ++++---- .../crazyradio/cfclient/ui/tabs/FlightTab.pyc | Bin 22594 -> 0 bytes .../crazyradio/cfclient/ui/tabs/GpsTab.py | 265 ++----- .../crazyradio/cfclient/ui/tabs/GpsTab.pyc | Bin 8654 -> 0 bytes .../crazyradio/cfclient/ui/tabs/LEDTab.py | 44 +- .../crazyradio/cfclient/ui/tabs/LEDTab.pyc | Bin 7144 -> 0 bytes .../cfclient/ui/tabs/LogBlockDebugTab.py | 40 +- .../cfclient/ui/tabs/LogBlockDebugTab.pyc | Bin 3746 -> 0 bytes .../cfclient/ui/tabs/LogBlockTab.py | 54 +- .../cfclient/ui/tabs/LogBlockTab.pyc | Bin 14996 -> 0 bytes .../crazyradio/cfclient/ui/tabs/LogTab.py | 38 +- .../crazyradio/cfclient/ui/tabs/LogTab.pyc | Bin 2830 -> 0 bytes .../crazyradio/cfclient/ui/tabs/ParamTab.py | 52 +- .../crazyradio/cfclient/ui/tabs/ParamTab.pyc | Bin 10768 -> 0 bytes .../crazyradio/cfclient/ui/tabs/PlotTab.py | 80 ++- .../crazyradio/cfclient/ui/tabs/PlotTab.pyc | Bin 9626 -> 0 bytes .../crazyradio/cfclient/ui/tabs/__init__.py | 52 +- .../crazyradio/cfclient/ui/tabs/__init__.pyc | Bin 1101 -> 0 bytes .../crazyradio/cfclient/ui/tabs/consoleTab.ui | 43 +- .../crazyradio/cfclient/ui/tabs/exampleTab.ui | 0 .../crazyradio/cfclient/ui/tabs/flightTab.ui | 24 +- .../crazyradio/cfclient/ui/tabs/gpsTab.ui | 82 ++- .../crazyradio/cfclient/ui/tabs/ledTab.ui | 0 .../cfclient/ui/tabs/locopositioning_tab.py | 671 ++++++++++++++++++ .../cfclient/ui/tabs/locopositioning_tab.ui | 338 +++++++++ .../cfclient/ui/tabs/logBlockDebugTab.ui | 0 .../cfclient/ui/tabs/logBlockTab.ui | 0 .../crazyradio/cfclient/ui/tabs/logTab.ui | 0 .../crazyradio/cfclient/ui/tabs/paramTab.ui | 0 .../crazyradio/cfclient/ui/tabs/plotTab.ui | 0 .../cfclient/ui/toolboxes/ConsoleToolbox.py | 48 +- .../cfclient/ui/toolboxes/ConsoleToolbox.pyc | Bin 2448 -> 0 bytes .../cfclient/ui/toolboxes/CrtpSharkToolbox.py | 93 +-- .../ui/toolboxes/CrtpSharkToolbox.pyc | Bin 5286 -> 0 bytes .../ui/toolboxes/DebugDriverToolbox.py | 40 +- .../ui/toolboxes/DebugDriverToolbox.pyc | Bin 4458 -> 0 bytes .../cfclient/ui/toolboxes/__init__.py | 36 +- .../cfclient/ui/toolboxes/__init__.pyc | Bin 1136 -> 0 bytes .../cfclient/ui/toolboxes/consoleToolbox.ui | 0 .../cfclient/ui/toolboxes/crtpSharkToolbox.ui | 0 .../ui/toolboxes/debugDriverToolbox.ui | 0 .../cfclient/ui/widgets/__init__.py | 9 +- .../cfclient/ui/widgets/__init__.pyc | Bin 238 -> 0 bytes .../crazyradio/cfclient/ui/widgets/ai.py | 161 ++--- .../crazyradio/cfclient/ui/widgets/ai.pyc | Bin 8343 -> 0 bytes .../cfclient/ui/widgets/hexspinbox.py | 18 +- .../cfclient/ui/widgets/hexspinbox.pyc | Bin 2777 -> 0 bytes .../crazyradio/cfclient/ui/widgets/plotter.ui | 0 .../cfclient/ui/widgets/plotwidget.py | 124 ++-- .../cfclient/ui/widgets/plotwidget.pyc | Bin 10686 -> 0 bytes .../crazyradio/cfclient/utils/__init__.py | 6 +- .../crazyradio/cfclient/utils/__init__.pyc | Bin 190 -> 0 bytes .../crazyradio/cfclient/utils/config.py | 21 +- .../crazyradio/cfclient/utils/config.pyc | Bin 3450 -> 0 bytes .../cfclient/utils/config_manager.py | 88 ++- .../cfclient/utils/config_manager.pyc | Bin 3562 -> 0 bytes .../crazyradio/cfclient/utils/guiconfig.pyc | Bin 1832 -> 0 bytes .../crazyradio/cfclient/utils/input.pyc | Bin 11733 -> 0 bytes .../cfclient/utils/input/__init__.py | 176 +++-- .../cfclient/utils/input/__init__.pyc | Bin 13812 -> 0 bytes .../utils/input/inputinterfaces/__init__.py | 44 +- .../utils/input/inputinterfaces/__init__.pyc | Bin 3290 -> 0 bytes .../utils/input/inputinterfaces/leapmotion.py | 44 +- .../input/inputinterfaces/leapmotion.pyc | Bin 6071 -> 0 bytes .../utils/input/inputinterfaces/wiimote.py | 22 +- .../utils/input/inputinterfaces/wiimote.pyc | Bin 6087 -> 0 bytes .../utils/input/inputinterfaces/zmqpull.py | 33 +- .../utils/input/inputinterfaces/zmqpull.pyc | Bin 4432 -> 0 bytes .../utils/input/inputreaderinterface.py | 49 +- .../utils/input/inputreaderinterface.pyc | Bin 8721 -> 0 bytes .../utils/input/inputreaders/__init__.py | 37 +- .../utils/input/inputreaders/__init__.pyc | Bin 4311 -> 0 bytes .../utils/input/inputreaders/linuxjsdev.py | 45 +- .../utils/input/inputreaders/linuxjsdev.pyc | Bin 9030 -> 0 bytes .../utils/input/inputreaders/pysdl2.py | 92 +-- .../utils/input/inputreaders/pysdl2.pyc | Bin 8270 -> 0 bytes .../cfclient/utils/input/mux/__init__.py | 35 +- .../cfclient/utils/input/mux/__init__.pyc | Bin 3102 -> 0 bytes .../cfclient/utils/input/mux/nomux.py | 9 +- .../cfclient/utils/input/mux/nomux.pyc | Bin 1267 -> 0 bytes .../cfclient/utils/input/mux/takeovermux.py | 16 +- .../cfclient/utils/input/mux/takeovermux.pyc | Bin 1396 -> 0 bytes .../utils/input/mux/takeoverselectivemux.py | 15 +- .../utils/input/mux/takeoverselectivemux.pyc | Bin 2001 -> 0 bytes .../cfclient/utils/joystick/__init__.pyc | Bin 245 -> 0 bytes .../cfclient/utils/joystick/linuxjsdev.pyc | Bin 9305 -> 0 bytes .../cfclient/utils/logconfigreader.py | 30 +- .../cfclient/utils/logconfigreader.pyc | Bin 4251 -> 0 bytes .../cfclient/utils/logdatawriter.py | 15 +- .../cfclient/utils/logdatawriter.pyc | Bin 3823 -> 0 bytes .../cfclient/utils/periodictimer.py | 9 +- .../cfclient/utils/periodictimer.pyc | Bin 2914 -> 0 bytes .../cfclient/utils/pysdl2reader.pyc | Bin 5784 -> 0 bytes .../crazyradio/cfclient/utils/singleton.py | 6 +- .../crazyradio/cfclient/utils/singleton.pyc | Bin 899 -> 0 bytes .../cfclient/utils/zmq_led_driver.py | 11 +- .../cfclient/utils/zmq_led_driver.pyc | Bin 3608 -> 0 bytes .../crazyradio/cfclient/utils/zmq_param.py | 20 +- .../crazyradio/cfclient/utils/zmq_param.pyc | Bin 3797 -> 0 bytes .../d_fall_pps/crazyradio/cflib/__init__.pyc | Bin 1182 -> 1185 bytes .../crazyradio/cflib/crazyflie/__init__.pyc | Bin 15562 -> 15661 bytes .../crazyradio/cflib/crazyflie/commander.pyc | Bin 2173 -> 2188 bytes .../crazyradio/cflib/crazyflie/console.pyc | Bin 1678 -> 1690 bytes .../crazyradio/cflib/crazyflie/log.pyc | Bin 19930 -> 20023 bytes .../crazyradio/cflib/crazyflie/mem.pyc | Bin 27976 -> 28147 bytes .../crazyradio/cflib/crazyflie/param.pyc | Bin 11522 -> 11588 bytes .../cflib/crazyflie/platformservice.pyc | Bin 1580 -> 1592 bytes .../crazyradio/cflib/crazyflie/toc.pyc | Bin 7071 -> 7119 bytes .../crazyradio/cflib/crazyflie/toccache.pyc | Bin 3809 -> 3830 bytes .../crazyradio/cflib/crtp/__init__.pyc | Bin 2559 -> 2574 bytes .../crazyradio/cflib/crtp/crtpdriver.pyc | Bin 3669 -> 3705 bytes .../crazyradio/cflib/crtp/crtpstack.pyc | Bin 5176 -> 5224 bytes .../crazyradio/cflib/crtp/debugdriver.pyc | Bin 27858 -> 27966 bytes .../crazyradio/cflib/crtp/exceptions.pyc | Bin 1069 -> 1078 bytes .../crazyradio/cflib/crtp/radiodriver.pyc | Bin 12349 -> 12421 bytes .../crazyradio/cflib/crtp/serialdriver.pyc | Bin 1867 -> 1885 bytes .../crazyradio/cflib/crtp/udpdriver.pyc | Bin 3552 -> 3582 bytes .../crazyradio/cflib/crtp/usbdriver.pyc | Bin 7434 -> 7482 bytes .../crazyradio/cflib/drivers/__init__.pyc | Bin 254 -> 257 bytes .../crazyradio/cflib/drivers/cfusb.pyc | Bin 5866 -> 5902 bytes .../crazyradio/cflib/drivers/crazyradio.pyc | Bin 9622 -> 9682 bytes .../crazyradio/cflib/utils/__init__.pyc | Bin 241 -> 244 bytes .../crazyradio/cflib/utils/callbacks.pyc | Bin 1737 -> 1755 bytes 179 files changed, 3843 insertions(+), 2334 deletions(-) mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/__init__.pyc delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/cfclient.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/config.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/Generic_OS_X.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/Joystick.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_1.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_2.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_3.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_1.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_2.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_shoulder_btns_yaw.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/xbox360_mode1.json mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/log/stabilizer.json rename pps_ws/src/d_fall_pps/crazyradio/cfclient/{cfclient.py => gui.py} (75%) mode change 100755 => 100644 create mode 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/headless.py mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/icon-256.png create mode 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/resources/map.html create mode 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/resources/map.js mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.ui delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.pyc delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/pluginhelper.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/pluginhelper.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ConsoleTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ConsoleTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ExampleTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ExampleTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/FlightTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/FlightTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/GpsTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/GpsTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LEDTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LEDTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockDebugTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockDebugTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ParamTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ParamTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/PlotTab.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/PlotTab.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/consoleTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/exampleTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/flightTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/gpsTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ledTab.ui create mode 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/locopositioning_tab.py create mode 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/locopositioning_tab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logBlockDebugTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logBlockTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/paramTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/plotTab.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/ConsoleToolbox.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/ConsoleToolbox.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/CrtpSharkToolbox.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/CrtpSharkToolbox.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/DebugDriverToolbox.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/DebugDriverToolbox.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/consoleToolbox.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/crtpSharkToolbox.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/debugDriverToolbox.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/ai.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/ai.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/hexspinbox.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/hexspinbox.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotter.ui mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotwidget.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotwidget.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config_manager.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config_manager.pyc delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/guiconfig.pyc delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/leapmotion.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/leapmotion.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/wiimote.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/wiimote.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/zmqpull.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/zmqpull.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaderinterface.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaderinterface.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/linuxjsdev.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/linuxjsdev.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/pysdl2.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/pysdl2.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/__init__.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/__init__.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/nomux.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/nomux.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeovermux.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeovermux.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeoverselectivemux.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeoverselectivemux.pyc delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/joystick/__init__.pyc delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/joystick/linuxjsdev.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logconfigreader.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logconfigreader.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logdatawriter.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logdatawriter.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/periodictimer.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/periodictimer.pyc delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/pysdl2reader.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/singleton.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/singleton.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_led_driver.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_led_driver.pyc mode change 100755 => 100644 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_param.py delete mode 100755 pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_param.pyc diff --git a/pps_ws/src/d_fall_pps/crazyradio/CrazyRadio.py b/pps_ws/src/d_fall_pps/crazyradio/CrazyRadio.py index 1734c465..1ee59cb1 100755 --- a/pps_ws/src/d_fall_pps/crazyradio/CrazyRadio.py +++ b/pps_ws/src/d_fall_pps/crazyradio/CrazyRadio.py @@ -94,7 +94,7 @@ class PPSRadioClient: def motorCommandCallback(data): """Callback for motor controller actions""" - cf_client._send_to_commander(0, 0, 0, 0, data.cmd1 * 10000, data.cmd2 * 10000, data.cmd3 * 10000, data.cmd4 * 10000, CONTROLLER_MOTOR) + cf_client._send_to_commander(0, 0, 0, 0, data.cmd1 * 1000, data.cmd2 * 1000, data.cmd3 * 1000, data.cmd4 * 1000, CONTROLLER_MOTOR) rospy.loginfo("motor controller callback: %s, %s, %s, %s", data.cmd1, data.cmd2, data.cmd3, data.cmd4) def angleCommandCallback(data): @@ -121,13 +121,17 @@ if __name__ == '__main__': available=[] available = cflib.crtp.scan_interfaces() rospy.loginfo("Crazyflies found:") + for i in available: + rospy.loginfo("----------------------------------------------------------------") + rospy.loginfo(i[0]) for i in available: print i[0] if len(available) > 0: global cf_client #TODO: load address from parameters - cf_client = PPSRadioClient(available[0][0]) + cf_client = PPSRadioClient("radio://0/72/2M") + #cf_client = PPSRadioClient(available[0][0]) time.sleep(2.0) #TODO: change publisher name if not correct rospy.Subscriber("/PPSClient/MotorCommand", MotorCommand, motorCommandCallback) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/__init__.py old mode 100755 new mode 100644 index e3208939..bedfb2dc --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/__init__.py @@ -24,21 +24,28 @@ # this program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -from .cfclient import main +import os +from appdirs import AppDirs +import sys -try: - from .version import VERSION -except: - try: - import subprocess - VERSION = subprocess.check_output(["git", "describe"]) - except: - VERSION = "dev" +# Path used all over the application +if not hasattr(sys, 'frozen'): + module_path = os.path.dirname(__file__) +else: + module_path = os.path.dirname(sys.executable) +config_path = AppDirs("cfclient", "Bitcraze").user_config_dir +# Locate the sdl2 lib on Windows (should be in cfclient/thirst_party/) +if os.name == 'nt': + os.environ["PYSDL2_DLL_PATH"] = os.path.join(module_path, "third_party") + +if not hasattr(sys, 'frozen'): + import pkg_resources try: - import subprocess - ret = subprocess.call(["git", "diff", "--quiet", "HEAD"]) - if ret > 0: - VERSION += "+" - except: - VERSION += "+" + VERSION = pkg_resources.require("cfclient")[0].version + except pkg_resources.DistributionNotFound: + VERSION = "dev" +else: + import json + with open(os.path.join(module_path, "version.json")) as f: + VERSION = json.load(f)['version'] diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/__init__.pyc deleted file mode 100755 index 8c79f1b6984af0d16b764ba41f46662cedd7fbf9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 526 zcmZWk-AV#M7(L^zu9-rCHz9Nv2%=tg6H%a0HwFqSd$Z`yXp{S+JF~)G_X<5huhB)X z6!ZY~%~*8N{G8#OnRC8xoX<w>qvKCQ{ERZ4H?-9|0jI?f0WpKmz>21oN{C8`9rzB| zEO`NAthfMoz+FTxd>6vSQyH9A1?v)?$?jm5G|W@(8Imx}i@`rr#hR+%N8mNAU2F9q zJn&;|Tx72hRHu$hlL5?jZzl6kBR)6T)XJpYpg%}P&^Dl5f_Nd51M`SYhvUip!$^M7 z7-@%;wbZ&wCl@Nr<Wg9Xi@h~-xmqdX>vng!6xxb+!`p!*4cZjxw2j+FgsU);BGF@e zX>5CuDVZi?+f9uGl`pqh8VaR!ooM(d!cCCodYd1z!$lO?4l<$JCgu-Ri)gRckL0rd tTd5xeGLbq6dfURba22OKkHocktIi2dN)Br>hi09f5!Q&;S&Q~5v2TZ$VWa>6 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/cfclient.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/cfclient.pyc deleted file mode 100755 index 6054b91a78b93015ac313504f2b88b0f3a1b2edb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3443 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/config.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/config.json old mode 100755 new mode 100644 index c78d5b0e..bb92591e --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/config.json +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/config.json @@ -1,16 +1,16 @@ { "writable" : { - "input_device": "", - "link_uri": "", - "flightmode": "Normal", - "open_tabs": "Flight Control", - "trim_pitch": 0.0, - "slew_limit": 45, - "slew_rate": 30, - "trim_roll": 0.0, - "max_thrust": 80, - "min_thrust": 25, - "max_yaw": 200, + "input_device": "", + "link_uri": "", + "flightmode": "Normal", + "open_tabs": "Flight Control", + "trim_pitch": 0.0, + "slew_limit": 45, + "slew_rate": 30, + "trim_roll": 0.0, + "max_thrust": 80, + "min_thrust": 25, + "max_yaw": 200, "max_rp": 30, "client_side_xmode": false, "auto_reconnect": false, @@ -21,11 +21,11 @@ "enable_zmq_input": false }, "read-only" : { - "normal_slew_limit": 45, - "normal_slew_rate": 30, - "normal_max_thrust": 80, - "normal_min_thrust": 25, - "normal_max_yaw": 200, + "normal_slew_limit": 45, + "normal_slew_rate": 30, + "normal_max_thrust": 80, + "normal_min_thrust": 25, + "normal_max_yaw": 200, "normal_max_rp": 30, "default_cf_channel": 10, "default_cf_speed": 0, diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/Generic_OS_X.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/Generic_OS_X.json old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/Joystick.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/Joystick.json old mode 100755 new mode 100644 index 00e1a5ed..42299c4a --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/Joystick.json +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/Joystick.json @@ -1,95 +1,95 @@ -{ - "inputconfig": { - "inputdevice": { - "updateperiod": 10, - "springythrottle": false, - "name": "Joystick", - "axis": [ - { - "scale": -1.0, - "type": "Input.AXIS", - "id": 3, - "key": "thrust", - "name": "thrust" - }, - { - "scale": 1.0, - "type": "Input.AXIS", - "id": 2, - "key": "yaw", - "name": "yaw" - }, - { - "scale": 1.0, - "type": "Input.AXIS", - "id": 0, - "key": "roll", - "name": "roll" - }, - { - "scale": -1.0, - "type": "Input.AXIS", - "id": 1, - "key": "pitch", - "name": "pitch" - }, - { - "scale": 1.0, - "type": "Input.HAT", - "id": 0, - "key": "trim", - "name": "trim" - }, - { - "scale": -1.0, - "type": "Input.BUTTON", - "id": 4, - "key": "pitchNeg", - "name": "pitchNeg" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 5, - "key": "pitchPos", - "name": "pitchPos" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 1, - "key": "estop", - "name": "killswitch" - }, - { - "scale": -1.0, - "type": "Input.BUTTON", - "id": 2, - "key": "rollNeg", - "name": "rollNeg" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 3, - "key": "rollPos", - "name": "rollPos" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 0, - "key": "althold", - "name": "althold" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 6, - "key": "exit", - "name": "exitapp" - } - ] - } - } -} +{ + "inputconfig": { + "inputdevice": { + "updateperiod": 10, + "springythrottle": false, + "name": "Joystick", + "axis": [ + { + "scale": -1.0, + "type": "Input.AXIS", + "id": 3, + "key": "thrust", + "name": "thrust" + }, + { + "scale": 1.0, + "type": "Input.AXIS", + "id": 2, + "key": "yaw", + "name": "yaw" + }, + { + "scale": 1.0, + "type": "Input.AXIS", + "id": 0, + "key": "roll", + "name": "roll" + }, + { + "scale": -1.0, + "type": "Input.AXIS", + "id": 1, + "key": "pitch", + "name": "pitch" + }, + { + "scale": 1.0, + "type": "Input.HAT", + "id": 0, + "key": "trim", + "name": "trim" + }, + { + "scale": -1.0, + "type": "Input.BUTTON", + "id": 4, + "key": "pitchNeg", + "name": "pitchNeg" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": 5, + "key": "pitchPos", + "name": "pitchPos" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": 1, + "key": "estop", + "name": "killswitch" + }, + { + "scale": -1.0, + "type": "Input.BUTTON", + "id": 2, + "key": "rollNeg", + "name": "rollNeg" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": 3, + "key": "rollPos", + "name": "rollPos" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": 0, + "key": "althold", + "name": "althold" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": 6, + "key": "exit", + "name": "exitapp" + } + ] + } + } +} diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_1.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_1.json old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_2.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_2.json old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_3.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_3.json old mode 100755 new mode 100644 index 18fea844..2a55cb98 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_3.json +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS3_Mode_3.json @@ -1,83 +1,83 @@ { "inputconfig": { "inputdevice": { - "updateperiod": 10, - "name": "PS3_Mode_3", + "updateperiod": 10, + "name": "PS3_Mode_3", "axis": [ { - "scale": -1.0, - "type": "Input.AXIS", - "id": 1, - "key": "thrust", + "scale": -1.0, + "type": "Input.AXIS", + "id": 1, + "key": "thrust", "name": "thrust" - }, + }, { - "scale": 1.0, - "type": "Input.AXIS", + "scale": 1.0, + "type": "Input.AXIS", "ids": [ - 12, + 12, 13 - ], - "key": "yaw", + ], + "key": "yaw", "name": "yaw" - }, + }, { - "scale": 1.0, - "type": "Input.AXIS", - "id": 2, - "key": "roll", + "scale": 1.0, + "type": "Input.AXIS", + "id": 2, + "key": "roll", "name": "roll" - }, + }, { - "scale": -1.0, - "type": "Input.AXIS", - "id": 3, - "key": "pitch", + "scale": -1.0, + "type": "Input.AXIS", + "id": 3, + "key": "pitch", "name": "pitch" - }, + }, { - "scale": -1.0, - "type": "Input.BUTTON", - "id": 6, + "scale": -1.0, + "type": "Input.BUTTON", + "id": 6, "key": "pitchNeg", "name": "pitchNeg" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 4, + "scale": 1.0, + "type": "Input.BUTTON", + "id": 4, "key": "pitchPos", "name": "pitchPos" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 14, - "key": "estop", + "scale": 1.0, + "type": "Input.BUTTON", + "id": 14, + "key": "estop", "name": "killswitch" - }, + }, { - "scale": -1.0, - "type": "Input.BUTTON", - "id": 7, + "scale": -1.0, + "type": "Input.BUTTON", + "id": 7, "key": "rollNeg", "name": "rollNeg" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 5, + "scale": 1.0, + "type": "Input.BUTTON", + "id": 5, "key": "rollPos", "name": "rollPos" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 12, - "key": "exit", + "scale": 1.0, + "type": "Input.BUTTON", + "id": 12, + "key": "exit", "name": "exitapp" } ] } } -} \ No newline at end of file +} diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_1.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_1.json old mode 100755 new mode 100644 index 15e0010d..d8c58825 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_1.json +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_1.json @@ -1,87 +1,87 @@ { "inputconfig": { "inputdevice": { - "updateperiod": 10, - "name": "PS4_Mode_1", + "updateperiod": 10, + "name": "PS4_Mode_1", "axis": [ { - "scale": -1.0, - "type": "Input.AXIS", - "id": 5, - "key": "thrust", + "scale": -1.0, + "type": "Input.AXIS", + "id": 5, + "key": "thrust", "name": "thrust" - }, + }, { - "scale": 1.0, - "type": "Input.AXIS", - "id": 2, - "key": "yaw", + "scale": 1.0, + "type": "Input.AXIS", + "id": 2, + "key": "yaw", "name": "yaw" - }, + }, { - "scale": 1.0, - "type": "Input.AXIS", - "id": 0, - "key": "roll", + "scale": 1.0, + "type": "Input.AXIS", + "id": 0, + "key": "roll", "name": "roll" - }, + }, { - "scale": -1.0, - "type": "Input.AXIS", - "id": 1, - "key": "pitch", + "scale": -1.0, + "type": "Input.AXIS", + "id": 1, + "key": "pitch", "name": "pitch" - }, + }, { - "scale": -1.0, - "type": "Input.BUTTON", - "id": 1, + "scale": -1.0, + "type": "Input.BUTTON", + "id": 1, "key": "pitchNeg", "name": "pitchNeg" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 3, + "scale": 1.0, + "type": "Input.BUTTON", + "id": 3, "key": "pitchPos", "name": "pitchPos" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 12, - "key": "estop", + "scale": 1.0, + "type": "Input.BUTTON", + "id": 12, + "key": "estop", "name": "killswitch" - }, + }, { - "scale": -1.0, - "type": "Input.BUTTON", - "id": 0, + "scale": -1.0, + "type": "Input.BUTTON", + "id": 0, "key": "rollNeg", "name": "rollNeg" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 2, + "scale": 1.0, + "type": "Input.BUTTON", + "id": 2, "key": "rollPos", "name": "rollPos" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 5, - "key": "althold", + "scale": 1.0, + "type": "Input.BUTTON", + "id": 5, + "key": "althold", "name": "althold" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 8, - "key": "exit", + "scale": 1.0, + "type": "Input.BUTTON", + "id": 8, + "key": "exit", "name": "exitapp" } ] } } -} \ No newline at end of file +} diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_2.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_2.json old mode 100755 new mode 100644 index f369ebdc..6b9ef6a1 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_2.json +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_Mode_2.json @@ -1,87 +1,87 @@ { "inputconfig": { "inputdevice": { - "updateperiod": 10, - "name": "PS4_Mode_2", + "updateperiod": 10, + "name": "PS4_Mode_2", "axis": [ { - "scale": -1.0, - "type": "Input.AXIS", - "id": 1, - "key": "thrust", + "scale": -1.0, + "type": "Input.AXIS", + "id": 1, + "key": "thrust", "name": "thrust" - }, + }, { - "scale": 1.0, - "type": "Input.AXIS", - "id": 0, - "key": "yaw", + "scale": 1.0, + "type": "Input.AXIS", + "id": 0, + "key": "yaw", "name": "yaw" - }, + }, { - "scale": 1.0, - "type": "Input.AXIS", - "id": 2, - "key": "roll", + "scale": 1.0, + "type": "Input.AXIS", + "id": 2, + "key": "roll", "name": "roll" - }, + }, { - "scale": -1.0, - "type": "Input.AXIS", - "id": 5, - "key": "pitch", + "scale": -1.0, + "type": "Input.AXIS", + "id": 5, + "key": "pitch", "name": "pitch" - }, + }, { - "scale": -1.0, - "type": "Input.BUTTON", - "id": 1, + "scale": -1.0, + "type": "Input.BUTTON", + "id": 1, "key": "pitchNeg", "name": "pitchNeg" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 3, + "scale": 1.0, + "type": "Input.BUTTON", + "id": 3, "key": "pitchPos", "name": "pitchPos" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 7, - "key": "estop", + "scale": 1.0, + "type": "Input.BUTTON", + "id": 7, + "key": "estop", "name": "killswitch" - }, + }, { - "scale": -1.0, - "type": "Input.BUTTON", - "id": 0, + "scale": -1.0, + "type": "Input.BUTTON", + "id": 0, "key": "rollNeg", "name": "rollNeg" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 2, + "scale": 1.0, + "type": "Input.BUTTON", + "id": 2, "key": "rollPos", "name": "rollPos" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 4, - "key": "althold", + "scale": 1.0, + "type": "Input.BUTTON", + "id": 4, + "key": "althold", "name": "althold" - }, + }, { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 8, - "key": "exit", + "scale": 1.0, + "type": "Input.BUTTON", + "id": 8, + "key": "exit", "name": "exitapp" } ] } } -} \ No newline at end of file +} diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_shoulder_btns_yaw.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/PS4_shoulder_btns_yaw.json old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/xbox360_mode1.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/xbox360_mode1.json old mode 100755 new mode 100644 index 0ca5d032..57691456 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/xbox360_mode1.json +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/input/xbox360_mode1.json @@ -1,87 +1,87 @@ -{ - "inputconfig": { - "inputdevice": { - "updateperiod": 10, - "name": "xbox360_mode1_linux", - "axis": [ - { - "scale": -1.0, - "type": "Input.AXIS", - "id": 4, - "key": "thrust", - "name": "thrust" - }, - { - "scale": 1.0, - "type": "Input.AXIS", - "id": 3, - "key": "yaw", - "name": "yaw" - }, - { - "scale": 1.0, - "type": "Input.AXIS", - "id": 0, - "key": "roll", - "name": "roll" - }, - { - "scale": -1.0, - "type": "Input.AXIS", - "id": 1, - "key": "pitch", - "name": "pitch" - }, - { - "scale": -1.0, - "type": "Input.BUTTON", - "id": -1, - "key": "pitchNeg", - "name": "pitchNeg" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": -1, - "key": "pitchPos", - "name": "pitchPos" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": -1, - "key": "estop", - "name": "killswitch" - }, - { - "scale": -1.0, - "type": "Input.BUTTON", - "id": -1, - "key": "rollNeg", - "name": "rollNeg" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": -1, - "key": "rollPos", - "name": "rollPos" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": 5, - "key": "althold", - "name": "althold" - }, - { - "scale": 1.0, - "type": "Input.BUTTON", - "id": -1, - "key": "exit", - "name": "exitapp" - } - ] - } - } -} \ No newline at end of file +{ + "inputconfig": { + "inputdevice": { + "updateperiod": 10, + "name": "xbox360_mode1_linux", + "axis": [ + { + "scale": -1.0, + "type": "Input.AXIS", + "id": 4, + "key": "thrust", + "name": "thrust" + }, + { + "scale": 1.0, + "type": "Input.AXIS", + "id": 3, + "key": "yaw", + "name": "yaw" + }, + { + "scale": 1.0, + "type": "Input.AXIS", + "id": 0, + "key": "roll", + "name": "roll" + }, + { + "scale": -1.0, + "type": "Input.AXIS", + "id": 1, + "key": "pitch", + "name": "pitch" + }, + { + "scale": -1.0, + "type": "Input.BUTTON", + "id": -1, + "key": "pitchNeg", + "name": "pitchNeg" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": -1, + "key": "pitchPos", + "name": "pitchPos" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": -1, + "key": "estop", + "name": "killswitch" + }, + { + "scale": -1.0, + "type": "Input.BUTTON", + "id": -1, + "key": "rollNeg", + "name": "rollNeg" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": -1, + "key": "rollPos", + "name": "rollPos" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": 5, + "key": "althold", + "name": "althold" + }, + { + "scale": 1.0, + "type": "Input.BUTTON", + "id": -1, + "key": "exit", + "name": "exitapp" + } + ] + } + } +} diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/log/stabilizer.json b/pps_ws/src/d_fall_pps/crazyradio/cfclient/configs/log/stabilizer.json old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/cfclient.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/gui.py old mode 100755 new mode 100644 similarity index 75% rename from pps_ws/src/d_fall_pps/crazyradio/cfclient/cfclient.py rename to pps_ws/src/d_fall_pps/crazyradio/cfclient/gui.py index 81b3594b..7c0526e3 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/cfclient.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/gui.py @@ -26,9 +26,6 @@ """Initialization of the PC Client GUI.""" -__author__ = 'Bitcraze AB' -__all__ = [''] - import sys import os import argparse @@ -36,9 +33,13 @@ import datetime import logging +import cfclient -def main(): +__author__ = 'Bitcraze AB' +__all__ = [] + +def main(): """ Check starting conditions and start GUI. @@ -47,17 +48,17 @@ def main(): to stdout and start the GUI. """ - # Set ERROR level for PyQt4 logger - qtlogger = logging.getLogger('PyQt4') + # Set ERROR level for PyQt5 logger + qtlogger = logging.getLogger('PyQt5') qtlogger.setLevel(logging.ERROR) - parser = argparse.ArgumentParser(description="cfclient - " - "Crazyflie graphical control client") + parser = argparse.ArgumentParser( + description="cfclient - Crazyflie graphical control client") parser.add_argument('--debug', '-d', nargs=1, default='info', type=str, help="set debug level " - "[minimal, info, debug, debugfile]") + "[minimal, info, debug, debugfile]") args = parser.parse_args() - globals().update(vars(args)) + debug = args.debug cflogger = logging.getLogger('') @@ -80,28 +81,28 @@ def main(): logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) - - logger.debug("Using config path {}".format(sys.path[1])) + + logger.debug("Using config path {}".format(cfclient.config_path)) logger.debug("sys.path={}".format(sys.path)) # Try all the imports used in the project here to control what happens.... try: - import usb + import usb # noqa except ImportError: logger.critical("No pyusb installation found, exiting!") sys.exit(1) if not sys.platform.startswith('linux'): try: - import sdl2 + import sdl2 # noqa except ImportError: logger.critical("No pysdl2 installation found, exiting!") sys.exit(1) try: - import PyQt4 + import PyQt5 # noqa except ImportError: - logger.critical("No PyQT4 installation found, exiting!") + logger.critical("No PyQT5 installation found, exiting!") sys.exit(1) # Disable printouts from STL @@ -110,28 +111,49 @@ def main(): os.dup2(os.open('/dev/null', os.O_WRONLY), 1) sys.stdout = os.fdopen(stdout, 'w') logger.info("Disabling STL printouts") - + if os.name == 'nt': stdout = os.dup(1) os.dup2(os.open('NUL', os.O_WRONLY), 1) sys.stdout = os.fdopen(stdout, 'w') logger.info("Disabling STL printouts") + if sys.platform == 'darwin': + try: + import Foundation + bundle = Foundation.NSBundle.mainBundle() + if bundle: + info = (bundle.localizedInfoDictionary() or + bundle.infoDictionary()) + if info: + info['CFBundleName'] = 'Crazyflie' + except ImportError: + logger.info("Foundation not found. Menu will show python as " + "application name") + # Start up the main user-interface - from ui.main import MainUI - from PyQt4.QtGui import QApplication, QIcon + from .ui.main import MainUI + from PyQt5.QtWidgets import QApplication + from PyQt5.QtGui import QIcon + app = QApplication(sys.argv) - app.setWindowIcon(QIcon(sys.path[0] + "/cfclient/icon-256.png")) + app.setWindowIcon(QIcon(cfclient.module_path + "/icon-256.png")) # Make sure the right icon is set in Windows 7+ taskbar if os.name == 'nt': import ctypes + try: myappid = 'mycompany.myproduct.subproduct.version' - ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid) + ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID( + myappid) except Exception: pass - + main_window = MainUI() main_window.show() sys.exit(app.exec_()) + + +if __name__ == "__main__": + main() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/headless.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/headless.py new file mode 100644 index 00000000..29dca85e --- /dev/null +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/headless.py @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +# +# || ____ _ __ +# +------+ / __ )(_) /_______________ _____ ___ +# | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ +# +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ +# || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ +# +# Copyright (C) 2013 Bitcraze AB +# +# Crazyflie Nano Quadcopter Client +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +""" +Headless client for the Crazyflie. +""" +import logging +import os +import signal +import sys + +import cfclient.utils +import cflib.crtp +from cfclient.utils.input import JoystickReader +from cflib.crazyflie import Crazyflie + +if os.name == 'posix': + print('Disabling standard output for libraries!') + stdout = os.dup(1) + os.dup2(os.open('/dev/null', os.O_WRONLY), 1) + sys.stdout = os.fdopen(stdout, 'w') + +# set SDL to use the dummy NULL video driver, +# so it doesn't need a windowing system. +os.environ["SDL_VIDEODRIVER"] = "dummy" + + +class HeadlessClient(): + """Crazyflie headless client""" + + def __init__(self): + """Initialize the headless client and libraries""" + cflib.crtp.init_drivers() + + self._jr = JoystickReader(do_device_discovery=False) + + self._cf = Crazyflie(ro_cache=None, + rw_cache=cfclient.config_path + "/cache") + + signal.signal(signal.SIGINT, signal.SIG_DFL) + + self._devs = [] + + for d in self._jr.available_devices(): + self._devs.append(d.name) + + def setup_controller(self, input_config, input_device=0, xmode=False): + """Set up the device reader""" + # Set up the joystick reader + self._jr.device_error.add_callback(self._input_dev_error) + print("Client side X-mode: %s" % xmode) + if (xmode): + self._cf.commander.set_client_xmode(xmode) + + devs = self._jr.available_devices() # noqa, is this a bug? + print("Will use [%s] for input" % self._devs[input_device]) + self._jr.start_input(self._devs[input_device]) + self._jr.set_input_map(self._devs[input_device], input_config) + + def controller_connected(self): + """ Return True if a controller is connected""" + return True if (len(self._jr.available_devices()) > 0) else False + + def list_controllers(self): + """List the available controllers and input mapping""" + print("\nAvailable controllers:") + for i, dev in enumerate(self._devs): + print(" - Controller #{}: {}".format(i, dev)) + print("\nAvailable input mapping:") + for map in os.listdir(cfclient.config_path + '/input'): + print(" - " + map.split(".json")[0]) + + def connect_crazyflie(self, link_uri): + """Connect to a Crazyflie on the given link uri""" + self._cf.connection_failed.add_callback(self._connection_failed) + # 2014-11-25 chad: Add a callback for when we have a good connection. + self._cf.connected.add_callback(self._connected) + self._cf.param.add_update_callback( + group="imu_sensors", name="HMC5883L", cb=( + lambda name, found: self._jr.set_alt_hold_available( + eval(found)))) + self._jr.assisted_control_updated.add_callback( + lambda enabled: self._cf.param.set_value("flightmode.althold", + enabled)) + + self._cf.open_link(link_uri) + self._jr.input_updated.add_callback(self._cf.commander.send_setpoint) + + def _connected(self, link): + """Callback for a successful Crazyflie connection.""" + print("Connected to {}".format(link)) + + def _connection_failed(self, link, message): + """Callback for a failed Crazyflie connection""" + print("Connection failed on {}: {}".format(link, message)) + sys.exit(-1) + + def _input_dev_error(self, message): + """Callback for an input device error""" + print("Error when reading device: {}".format(message)) + sys.exit(-1) + + +def main(): + """Main Crazyflie headless application""" + import argparse + + parser = argparse.ArgumentParser(prog="cfheadless") + parser.add_argument("-u", "--uri", action="store", dest="uri", type=str, + default="radio://0/10/250K", + help="URI to use for connection to the Crazyradio" + " dongle, defaults to radio://0/10/250K") + parser.add_argument("-i", "--input", action="store", dest="input", + type=str, default="PS3_Mode_1", + help="Input mapping to use for the controller," + "defaults to PS3_Mode_1") + parser.add_argument("-d", "--debug", action="store_true", dest="debug", + help="Enable debug output") + parser.add_argument("-c", "--controller", action="store", type=int, + dest="controller", default=0, + help="Use controller with specified id," + " id defaults to 0") + parser.add_argument("--controllers", action="store_true", + dest="list_controllers", + help="Only display available controllers and exit") + parser.add_argument("-x", "--x-mode", action="store_true", + dest="xmode", + help="Enable client-side X-mode") + (args, unused) = parser.parse_known_args() + + if args.debug: + logging.basicConfig(level=logging.DEBUG) + else: + logging.basicConfig(level=logging.INFO) + + headless = HeadlessClient() + + if (args.list_controllers): + headless.list_controllers() + else: + if headless.controller_connected(): + headless.setup_controller(input_config=args.input, + input_device=args.controller, + xmode=args.xmode) + headless.connect_crazyflie(link_uri=args.uri) + else: + print("No input-device connected, exiting!") + + +if __name__ == "__main__": + main() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/icon-256.png b/pps_ws/src/d_fall_pps/crazyradio/cfclient/icon-256.png old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/resources/map.html b/pps_ws/src/d_fall_pps/crazyradio/cfclient/resources/map.html new file mode 100644 index 00000000..1bd5f016 --- /dev/null +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/resources/map.html @@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> +<head> + <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" /> + <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script> + <style> + body { padding: 0; margin: 0; } + html, body, #map { height: 100%; } + </style> +</head> +<body> + <div id="map"></div> +</body> +</html> diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/resources/map.js b/pps_ws/src/d_fall_pps/crazyradio/cfclient/resources/map.js new file mode 100644 index 00000000..8afb80b0 --- /dev/null +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/resources/map.js @@ -0,0 +1,25 @@ +var map = L.map('map').setView([55.607526, 13.018219], 16); +L.tileLayer('http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png', { + maxZoom: 18, + attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, ' + + 'tiles Courtesy of <a href="http://www.mapquest.com/" target="_blank">MapQuest</a>', + subdomains: '1',//'1234', +}).addTo(map); + +var cf = L.circle([55.607526, 13.018219], 1, { + color: 'blue', + fillColor: 'blue', + fillOpacity: 1 +}).addTo(map); + +var accuracy = L.circle([55.607526, 13.018219], 0, { + color: 'red', + fillColor: '#f03', + fillOpacity: 0.5 +}).addTo(map); + +if(typeof MainWindow != 'undefined') { + var onMapMove = function() { MainWindow.onMapMove(map.getCenter().lat, map.getCenter().lng) }; + map.on('move', onMapMove); + onMapMove(); +} diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/__init__.py old mode 100755 new mode 100644 index 51d3a306..d81873b0 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/__init__.py @@ -21,18 +21,18 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Create a plugin helper that is passed to all the tabs and toolboxes for easy # access to objects that are needed. """ +from cfclient.ui.pluginhelper import PluginHelper + __author__ = 'Bitcraze AB' __all__ = [] -from cfclient.ui.pluginhelper import PluginHelper - pluginhelper = PluginHelper() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/__init__.pyc deleted file mode 100755 index c104e7ddfe707c932c60f7d3a900cc8a2627a688..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 467 zcmYjMF;2uV5Oi|60|k&M=~#&-&BY%;2#$sVAp}&{SdP7SF>>N4b|j9Lj;HY*9suhE z1eQG+&p5lYv(KZv`FMX)>}RF)y`<wgfo5z?n6P!iw!~AWY0sFQu_j~dj3t<{H!|i- zXY8?<#~(dGe%+%C2ogFwY)uO_+75dNwG3c9bkcj&5FAKrNks^<@*vx&Ia|3G^ssR~ zp!7R9%cWB2eSGh#XH<b`tR#Dc7Ez-vbALd6S0<=lz9L+$%onX9Au${h+>beK#u#_S zBFcLNLTIOi2>Hn65Ng-cb+RZM@e{JtMp=VxC<jwc6HNm>kT=!;uNG1L1Aj|bUb_Z) z^^=cxy&LD?G45_d#g|hDzwCAtqUF|9{I@M13>U(*CJ0fIzfT3v8>a`07pKI16c*_s IS)|A5H!JmkbpQYW diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/__init__.py old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/__init__.pyc deleted file mode 100755 index 5f70eceb5bdffb7217e4898413ba04e8b69a74cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 171 zcmZSn%*&N~sw*U!0SXv_v;z<qvjB+{28Lh_kcgiKkYGR~ibH^6`WgATsrpHoCCNpJ zRjK*~Mfq8&$tA`5AZ}$^PG+iZGLXnCDb_8hEXl~v)6dCF(oar<2<n$+>ZfET=H#ar h>&M4u=4F<|$Lj&raR3dr$<0qG%}KQbSzipq3;<T1D-Qqw diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.py old mode 100755 new mode 100644 index b89b6176..4b5d4536 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.py @@ -20,37 +20,37 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ The about dialog. """ -__author__ = 'Bitcraze AB' -__all__ = ['AboutDialog'] - import sys -from PyQt4 import Qt, QtCore, QtGui, uic -from PyQt4.QtCore import * -from PyQt4.QtGui import * -from PyQt4.Qt import * - import cfclient - import cflib.crtp +from PyQt5.QtCore import QT_VERSION_STR +from PyQt5.QtCore import PYQT_VERSION_STR +from PyQt5 import QtWidgets +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal + +__author__ = 'Bitcraze AB' +__all__ = ['AboutDialog'] (about_widget_class, -about_widget_base_class) = (uic.loadUiType(sys.path[0] + - '/cfclient/ui/dialogs/about.ui')) + about_widget_base_class) = (uic.loadUiType(cfclient.module_path + + '/ui/dialogs/about.ui')) DEBUG_INFO_FORMAT = """ <b>Cfclient</b><br> Cfclient version: {version}<br> System: {system}<br> +Python: {pmajor}.{pminor}.{pmicro}<br> +Qt: {qt_version}<br> +PyQt: {pyqt_version}<br> <br> <b>Interface status</b><br> {interface_status} @@ -77,7 +77,7 @@ IMU_SENSORS_FORMAT = "{}: {}<br>" SENSOR_TESTS_FORMAT = "{}: {}<br>" FIRMWARE_FORMAT = "{:x}{:x} ({})" -CREDITS_FORMAT = U""" +CREDITS_FORMAT = """ <b>Contributions</b><br> {contribs} <br><br> @@ -91,47 +91,47 @@ CREDITS_FORMAT = U""" <a href="http://www.python.org/">Python</a><br> """ -class AboutDialog(QtGui.QWidget, about_widget_class): +class AboutDialog(QtWidgets.QWidget, about_widget_class): _disconnected_signal = pyqtSignal(str) """Crazyflie client About box for debugging and information""" + def __init__(self, helper, *args): super(AboutDialog, self).__init__(*args) self.setupUi(self) self._close_button.clicked.connect(self.close) self._name_label.setText( - self._name_label.text().replace('#version#', - cfclient.VERSION)) + self._name_label.text().replace('#version#', cfclient.VERSION)) self._interface_text = "" self._imu_sensors_text = "" self._imu_sensor_test_text = "" - self._uri = None + self._uri = None self._fw_rev0 = None self._fw_rev1 = None self._fw_modified = None self._helper = helper - helper.cf.param.add_update_callback(group="imu_sensors", - cb=self._imu_sensors_update) - helper.cf.param.add_update_callback(group="imu_tests", - cb=self._imu_sensor_tests_update) - helper.cf.param.add_update_callback(group="firmware", - cb=self._firmware_update) + helper.cf.param.add_update_callback( + group="imu_sensors", cb=self._imu_sensors_update) + helper.cf.param.add_update_callback( + group="imu_tests", cb=self._imu_sensor_tests_update) + helper.cf.param.add_update_callback( + group="firmware", cb=self._firmware_update) helper.cf.connected.add_callback(self._connected) self._disconnected_signal.connect(self._disconnected) helper.cf.disconnected.add_callback(self._disconnected_signal.emit) # Open the Credits file and show it in the UI - credits = U"" + credits = "" try: - with open("CREDITS.txt", 'r') as f: + with open("CREDITS.txt", encoding='utf-8', mode='r') as f: for line in f: - credits += U"{}<br>".format(line.decode("UTF-8")) + credits += "{}<br>".format(line) except IOError: - credits = U"" + credits = "" self._credits.setHtml( CREDITS_FORMAT.format(contribs=credits) @@ -141,42 +141,48 @@ class AboutDialog(QtGui.QWidget, about_widget_class): """Event when the about box is shown""" self._interface_text = "" interface_status = cflib.crtp.get_interfaces_status() - for key in interface_status.keys(): - self._interface_text += INTERFACE_FORMAT.format(key, - interface_status[key]) + for key in list(interface_status.keys()): + self._interface_text += INTERFACE_FORMAT.format( + key, interface_status[key]) firmware = None self._device_text = "" devs = self._helper.inputDeviceReader.available_devices() for d in devs: - self._device_text += DEVICE_FORMAT.format(d.reader_name, - d.id, - d.name) + self._device_text += DEVICE_FORMAT.format( + d.reader_name, d.id, d.name) if len(self._device_text) == 0: self._device_text = "None<br>" self._input_readers_text = "" - #readers = self._helper.inputDeviceReader.getAvailableDevices() + # readers = self._helper.inputDeviceReader.getAvailableDevices() for reader in cfclient.utils.input.inputreaders.initialized_readers: - self._input_readers_text += INPUT_READER_FORMAT.format(reader.name, - len(reader.devices())) + self._input_readers_text += INPUT_READER_FORMAT.format( + reader.name, len(reader.devices())) if len(self._input_readers_text) == 0: self._input_readers_text = "None<br>" if self._uri: - firmware = FIRMWARE_FORMAT.format(self._fw_rev0, self._fw_rev1, - "MODIFIED" if self._fw_modified else "CLEAN") + firmware = FIRMWARE_FORMAT.format( + self._fw_rev0, + self._fw_rev1, + "MODIFIED" if self._fw_modified else "CLEAN") self._debug_out.setHtml( - DEBUG_INFO_FORMAT.format(version=cfclient.VERSION, - system=sys.platform, - interface_status=self._interface_text, - input_devices=self._device_text, - input_readers=self._input_readers_text, - uri = self._uri, - firmware = firmware, - imu_sensors=self._imu_sensors_text, - imu_sensor_tests= - self._imu_sensor_test_text)) + DEBUG_INFO_FORMAT.format( + version=cfclient.VERSION, + system=sys.platform, + pmajor=sys.version_info.major, + pminor=sys.version_info.minor, + pmicro=sys.version_info.micro, + qt_version=QT_VERSION_STR, + pyqt_version=PYQT_VERSION_STR, + interface_status=self._interface_text, + input_devices=self._device_text, + input_readers=self._input_readers_text, + uri=self._uri, + firmware=firmware, + imu_sensors=self._imu_sensors_text, + imu_sensor_tests=self._imu_sensor_test_text)) def _connected(self, uri): """Callback when Crazyflie is connected""" @@ -194,16 +200,16 @@ class AboutDialog(QtGui.QWidget, about_widget_class): def _imu_sensors_update(self, name, value): """Callback for sensor found parameters""" param = name[name.index('.') + 1:] - if not param in self._imu_sensors_text: - self._imu_sensors_text += IMU_SENSORS_FORMAT.format(param, - eval(value)) + if param not in self._imu_sensors_text: + self._imu_sensors_text += IMU_SENSORS_FORMAT.format( + param, eval(value)) def _imu_sensor_tests_update(self, name, value): """Callback for sensor test parameters""" param = name[name.index('.') + 1:] - if not param in self._imu_sensor_test_text: - self._imu_sensor_test_text += SENSOR_TESTS_FORMAT.format(param, - eval(value)) + if param not in self._imu_sensor_test_text: + self._imu_sensor_test_text += SENSOR_TESTS_FORMAT.format( + param, eval(value)) def _disconnected(self, uri): """Callback for Crazyflie disconnected""" diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.pyc deleted file mode 100755 index ffef3f1194f284714b174e6d7a4759edd5e8822f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6672 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 MbIc$9P8D+h1&7@*+W-In diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/about.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.py old mode 100755 new mode 100644 index b593e11d..3fffdd15 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.py @@ -21,9 +21,9 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ The bootloader dialog is used to update the Crazyflie firmware and to @@ -31,27 +31,20 @@ read/write the configuration block in the Crazyflie flash. """ from cflib.bootloader import Bootloader -__author__ = 'Bitcraze AB' -__all__ = ['BootloaderDialog'] - -import struct -import sys -import time - import logging -logger = logging.getLogger(__name__) -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL +from PyQt5 import QtWidgets, uic +from PyQt5.QtCore import pyqtSlot, pyqtSignal, QThread -from cfclient.ui.tab import Tab +import cfclient -import cflib.crtp +__author__ = 'Bitcraze AB' +__all__ = ['BootloaderDialog'] -from cflib.bootloader.cloader import Cloader +logger = logging.getLogger(__name__) -service_dialog_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/dialogs/bootloader.ui")[0] +service_dialog_class = uic.loadUiType(cfclient.module_path + + "/ui/dialogs/bootloader.ui")[0] class UIState: @@ -63,9 +56,10 @@ class UIState: RESET = 4 -class BootloaderDialog(QtGui.QWidget, service_dialog_class): +class BootloaderDialog(QtWidgets.QWidget, service_dialog_class): """Tab for update the Crazyflie firmware and for reading/writing the config block in flash""" + def __init__(self, helper, *args): super(BootloaderDialog, self).__init__(*args) self.setupUi(self) @@ -93,13 +87,13 @@ class BootloaderDialog(QtGui.QWidget, service_dialog_class): self.clt.statusChanged.connect(self.statusUpdate) # self.clt.updateBootloaderStatusSignal.connect( # self.updateBootloaderStatus) - self.clt.connectingSignal.connect(lambda: - self.setUiState(UIState.CONNECTING)) - self.clt.connectedSignal.connect(lambda: - self.setUiState(UIState.COLD_CONNECT)) + self.clt.connectingSignal.connect( + lambda: self.setUiState(UIState.CONNECTING)) + self.clt.connectedSignal.connect( + lambda: self.setUiState(UIState.COLD_CONNECT)) self.clt.failed_signal.connect(lambda m: self._ui_connection_fail(m)) - self.clt.disconnectedSignal.connect(lambda: - self.setUiState(UIState.DISCONNECTED)) + self.clt.disconnectedSignal.connect( + lambda: self.setUiState(UIState.DISCONNECTED)) self.clt.start() @@ -165,7 +159,7 @@ class BootloaderDialog(QtGui.QWidget, service_dialog_class): def pathBrowse(self): filename = "" # Fix for crash in X on Ubuntu 14.04 - filename = QtGui.QFileDialog.getOpenFileName() + filename, _ = QtWidgets.QFileDialog.getOpenFileName() if filename != "": self.imagePathLine.setText(filename) pass @@ -180,7 +174,7 @@ class BootloaderDialog(QtGui.QWidget, service_dialog_class): self.clt.program.emit(self.imagePathLine.text(), self.verifyCheckBox.isChecked()) else: - msgBox = QtGui.QMessageBox() + msgBox = QtWidgets.QMessageBox() msgBox.setText("Please choose an image file to program.") msgBox.exec_() @@ -271,7 +265,7 @@ class CrazyloadThread(QThread): def programAction(self, filename, verify): targets = {} if str(filename).endswith("bin"): - targets["stm32"] = ("fw", ) + targets["stm32"] = ("fw",) try: self._bl.flash(str(filename), targets) self.programmed.emit(True) @@ -284,4 +278,4 @@ class CrazyloadThread(QThread): except Exception: pass self._bl.close() - self.disconnectedSignal.emit() \ No newline at end of file + self.disconnectedSignal.emit() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.pyc deleted file mode 100755 index 4acfd27a8b9a4ed140627350fa9c21415047d163..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11724 zcmd5?OLH7o6}~;A*T{PNotSv+#4rVp6d=5UF<7#kh$xEPl5H}9YG%5xq?UTRhwdKR z0;j0L6tI8-iYln0Sg>FVe*mf|_H5X(N%m~v2ZZlCw_j2yk}A-Eq`tcE$GPY6oqKQn zAJdbsxUb%GRrXWI|1aT7K5r@IDb+@3DX*piOZ951T~n4<SM9p;M%0d_+9Ogts)A9~ z9?j!psy&v+$5negk58!fgwhjguc7p$dV=OBq-ab9Q>r(u+S95xquMj7H>=vS7zrbf zt6)y`=2d%M^%hinLG@0m_DR({rP`-d@3d;4HuWY{a7Ojcs`gov#+1&f_Ic^Qp@OGW z?`hS3T3LEl?OjlMOznM0d6VkAcS4=TOc-rHqr55Q%`0zOeOIX`O1;s($c5?|wbxYo z8MR$g-b_(;NqMtMpHkasK3C*kR^F)EY%P$8-$5|BwX2)mC`yB<<LS8R`JEuzY5GZX zkZ7-&M$JLr>!iAwqTWi}`R2iP;OpkLANL-1V%_Y7tTY+xj<@tM_Ops^6mI)FgSeCW zQP}JTk-OjY!=rr!on&`$(tj5}E$pXCClM?cb4gAx>8CD6)y*5r>D-~>n=;dl7I`8a zLvSZuiDI3OO7!J{pR#1&yDjFVHOWpV@UMUHjdU}JQW;MY{!Z8l(s5SV+T~iL!_Bpq zH*Tz(sj;uEPS+$@am5hKM^q)35iGgeE=UumO9Ow&kTF>*DZ7XXvEALZ%@p)>*^WP4 z_%goaDgq6b#&#jZR)PV+$lz*lF_;?sJ0hG5ULIHWW{Yc<;e9U9XGcC)>2t3B2!a+@ zD@%5qu+!6yBTIIiUgQk|CZ|y0=Gx}U>l+)ZD_g5Kr94ZmZM>Y$pgc=Dw{EPhqXwI- zyuN<Z$?~QDTkAJAUtt4I#a`W9-D)AC${@Li<kD``(@WiKOPBg_w5Q!PS>g^0Up;Rq zm^|M<NOz-fDe$}RN7nv<%^7_TU&6?kRsI%4CPjqEZzFPq$dDyNXGVn7j0m+EfvOm# z^iWTXNo0az&zy$xCL}VcyoN+hC_P2VguJ2xRmgOnb0W`~$#bUi9Ej<Z(sQhz$u=6! z=hcivBWFRXouo`Z0ej5m%};0Y-9AIEm?t6LL;!AWZb$J4kYCm!)BE9$$T0qks2VAr zY~rU7;cW`7OEx1-`H`uUpMv{R{8{P;Sa(hB)zssf`XSgG>Akw-TB7=pc0?^RGO8X+ z3ujD0I6ydNPB4TL-kVf=CnOG<qA_!)E4ed8E|g|bSI8)J=PS7jMctE?To5wr_jD!q zOpyy)a5kUAxoYnDJol+;?$dehg=+4HnEQPtdbp;(Cu||}L+{U2%IZhTE>_A$j+8Yk zWur&RE|HFwr=aDjAvQ$oZ0h)d@0MDJ8+ei%N1aN-%HCnuK#)yQa+zYKN=|fo*B7lN zqGq#A3!gIDa73yE+mdyRaxRMITF~irz0UQob5O2ASuR8Ve9%SNXHeNJg?6x9ihVXu z9^*3Xa~PzHFP}aYH@{-~(@2;-c`V$LZwM=;+%;$5I}pwg$`kh0+3xs(*$UR^NpyHi z0jH@1pZZVsVHWNG7yAHPkncn5GU8&tl0jd`worQld5+_UehOnLnog&K{#|3r(@u8- zR#o`2r^A6HD090yKo2PwC6I|wA;T4Q<henbp2mN_*V)mxJL&Fn96e0*@*qv4P)30n zboaGq;%1`_SSc!}WD*$Aow(D>8dh>{2xEw;exPH2`yi`A18Fj{8no|j6nI2kSsh9@ z7wiM2te}VxCM6V$H55TssYtIx{S-?Tu5>%0s{<#;JTN0dPB)0qkcuRmZx1VD2U+rF z6dD@J%zPBGu9>EkabXES(;!*d?Swn1z;&3MyMj&y8s-ua?ra)7NBU=(+RO6T7v)8J zPGV|N1$cgPv?75FhKN%Em?BPg6L~4sT_@g2j<D--YK#jQauuH$(>h~K*BVx%-l$L2 z&mfiknt1&}4Zqffx)^Ed6n-mgeF*_H3UocJE-fDu7Hu`4GSgx-$oCs9u2Rq+wvMWQ zkgRvQI<P;+{LCn<hMg`5DHPd?2fD?Pgi^w|J)I<Aa6>1QsN*EjdGwEkse}_(*0lBB z<^K^Y!@>bmu;~4oihnHB09dJWS95}l9!ZO@m=}&q;Y3kcP)emS(r_BZj0$z92w8yM z^Y(DnkT!#bSFLP1vof7`KIn8ti|)*HvhLo_S2ri!P0Iu@`>`X{&FsV9<<;k<`d6j8 zAx61ALyR(w?ts%W);Tn~lXtfu-Tgivy=?n_gsyf+&OAgbarZY{4Q%d4LLuIW(q<vE z#tWkoGQ9dy^IG@%+RgRVYfIhh*l_R#C15K)5NsReE%86_D(>%9;9wE@Bd#jk;B2hq zBKld$Y%g(gRB7Hcnk6BO$m$p$I#-E0PM$@XO--6+Q^{TFtMI)`E!5&-3`U_Ev!7>h z9f7FSTb&@$_D7ia1qPH#`-?0s^eTjJ8QO~q9)oS^N9jF3@gc8bu8?)F6AZM}$BJ|L z&TSm)i-{?0)Vd#PL4Gzp44YchK82tn^qI;`ha~buaUs6svj~(mYt7+zT0+K7<~cRS zrpvU%@_L1upkWp*NqA<oB-8|)aLDKxa=a)<YPgMr6sR!Tm4s|2gg9h~qR>>bUq<~3 zokX{Sz{AmuWRM@>`&V#N7R+5V3x@k<T!5-2AYqOoX4;4nVahs=QMsp-`a;%!g2aDm zE!@W=X!+RJLU@&}1=#(TK#`yQyCpq`!h#>UJ>Yew#c1srTOhn?3^(zoeHlT@)d^-Z z7%c-pWIo;V)5?~L7!P+#?L|!E=lC*vJ!iSp9{dWpaubPS;g3rj3OfR+EDd&D(j}r9 zQJ@M=9}1x@2_w2Mj)Gt-_IoxVmGD*{CsMo25?~qQBqSoz40Rw-M>0118c>J27`k(1 z5XU&_TMIq?NRAgv)Z=CiMH#Y<eH(4;I|zm%@3I7QW(yO9Q`lc}$`c4wrWy;CS5UfS zu~GvV7TXhIlI4!FSm{HPeT3ue4aQzaP*HZIgMI*F4QKU)rs8m{a?D>NRdN{lfNL(+ zO~U~V|5gqPjdURiosazex{6;E76glpFq13=lOwcXFB|p^goXpCC&irJxdr#aoK6eB z?CA9Mz7Cm757B-F6_1((?$0(V@RW8agt9-35r2a(A;nZ}tTt;+!7{ozk+_@{mj41l zA%-|cCk-;@0Nu(oIOR|p&=JT}2uwour4wL0xnN-jc?HJh_zsny;07mrR)L9ulaV%i z0VtSbYFMaQQGv1tb<EA|K|(NeJJ6j(H{IO`9w)9Qnu1<%SrOp=B5G#-=3<LFxI|R; zGLr(Po@Gq-=T*ioBM?NCwG`eKNM*d!m0j)bFGr6=iTLnNk%Yi=R)!N^GcFLS$c77c z(~q?4R0M<yyO->s&TuxKqx=?MLI|hogi3SPY3rPIvNi?BQWzj-f)&;)@qqzEWPnlv zlIKvT0*2PIql2dL=3Ti0D)5ng3$+dNbBy6(2>YWL?hp8kI;g?mP=NDK7Wy@0K*;0s zCBH)paJk`JC97ol_w#6QjaRsqCBKRbP@&jubBaTEz>Ru+Aas3+1QUP#U)M8!hSX|} zW7Z{ED{M`Fpk(U`$FW5+a9uFxa9HjW81PRVl;<|kHDI+l>;U$FOz<Bt+dUp``G&^| z;{6{m+lyG%pYfH<MxDTK1fMV)ZDk70m-`q5EOnz<g{`3Qz>8<Sx?BKTD8{kD{-}z- zEUZ`sIk`omsXgqRym=-0TJv%9iYIre6<(5wkx=3}%SC})dE)MO2giBr$<y7zPKB{J zYk^GVftWN&#CsHEC2DeLT=i*8=r8yTxPg~<4i@aa97SiGCPrut3!jN}MT7A;K``D+ zOG_^-ef)(N%nC*O6XsM;LwQhYkhB3hL)KzfF`d8S%N(E<7iV++_6!2CRgU9DuH)Dj zn9E}^gY@N`V4ca=7%Vcl&)^LP;x!Nw*whH3Eag}a2N!`&@wLg)a-*K4vHbVL)aDl0 zoKvYsBzBC>pq$GuV@SDlAA>S!TxpCnF7h}Ozax#Y#>hfrVRm8k^ofPhbK~|U)OGR6 z4;fn;{|yn1J6ucYn$mTp;ZNYIeU!;3a_wvKq5X05n`Pp82rA=wh`bQtBN5!l<IWeE z;*PX&jcc0Y+Shd3kZy73Yw~f`Ya(-51@@1tUXzI%-uL#83t#DqHBZUg09^Q5y!^$5 zFSG<BXL-iR$T?~WM)0)6Tw6a?JQbj=E5xIY1SLB876RxY0DlMxNRWA$JP{VT!DTI_ zN5C2*Bgz?<oC#@=fk8P3W$}pu9|FQnN<{#<tQJo6Oco$q4k9Q(8wQa*ji_vw;a#K* z$2r}={uImTS{ypza@?-?JH6<E-ipi>i%m0bUtu7;yvs&Jd`HFDxGNNdA)f)r^8Su- z6AG;o;I&Ynh6c;<H)+C8HmE$0!iEU)1|~tw;|;H&9(Pv6^&5C(B9Vt3KOOR_a^-^? zAm?37DD%4}4bU1v4uwya^le1QEci2PIryTajp2hA0cld!Tk?h=xh_TEKUhkL3DMZJ zWC2~7*7w7!Y6QdYPpbHvXqTB$(*&*?I8{y$q^+gCB9!BVHUzli9aB#(t+KP-0gi;j z@^ty|5w9rTZ@nc4(e`K1hcKnxLrj<q)-X<sD==ImQrp;konq75lmS;Cxw_ArTd|*b zebMWra^X^*A_RW8f7f2KUAEyS56LU+W2idDlXn5QMyb`|8W69|;|$fUqx8^5zJ&}R z2v8g<#Q4Vs(16r&i@FGuhibYODs}LDxyMCqZVX&LqgbG1KoRcJ{qRz;qmPtjRVrk+ z7x^}lr#8eMbzzVw2-^<@z9ebylb<jmKow^;Y#%W}DmwI%hkm+iHjbUh!xsDFh?yM~ z^!$KH?qIn+_E(XVjWa%=ust>%UjC5KG_~4nxkqEzp=qmbowrW$+KbG>uMjp$+`+ui zzL2;3;XLSD6N!0_^bJAJOd>_`mjr)uSk(wn5N@AGzjD0jq>+<fV%S2l7f@us#6S*% zIGrJSderFWNuMc16eu$fx{Tm!iGeB5k}aMSS;B@UQpRpjHQ6*7#ySLu2|I1$4nLJ6 zRe9xTj@B|DC`|K7wh=2uIX9|7#GZ6W>1$UH<+8(A(lE>J57w%8)a9Au?I<z!Fk!zG zP-EA`a3NK}UdIW$E@7m1@ClRiw5S2J-LOvM(4Ya`fct2Zwx)2F)R+bkn`%swRaNU* z1U4NFb31|uq}|2xM$Bd%IcIg8&H&H;;_Rsfk^yW<=48YJH#PY4AQ2On`gnT5Eu_!F zw+0QwA%*MW!Wd8tO>egE_Q9R>MVsnDPG@XtF+mPeuxOr++LRdsg@rXHm}IYVjF&&} z#6!+Sy!@~yS-`-R1-WtB7fz96N~>)O%9SqSV3Ln)ZC=tzQ>O3wTL*nDOX}l!M|ui{ ziFvN&m}jJpi$`~fTn5U5@7(u2EL4!N;3Y$5v@^VLjBFsv^O|`+di^42`W%8WYmPV^ ZtbkvHvv`2ef{Q;TZvIUDWaGlG{t0}=4><q; diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/bootloader.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.py old mode 100755 new mode 100644 index c7635676..c4ecd003 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.py @@ -21,32 +21,35 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ The bootloader dialog is used to update the Crazyflie firmware and to read/write the configuration block in the Crazyflie flash. """ -__author__ = 'Bitcraze AB' -__all__ = ['Cf1ConfigDialog'] - import struct -import sys from cflib.bootloader import Bootloader import logging -logger = logging.getLogger(__name__) -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL +from PyQt5 import QtWidgets, uic +from PyQt5.QtCore import pyqtSlot, pyqtSignal, QThread +import cfclient from cfclient.utils.config import Config +from functools import reduce + +__author__ = 'Bitcraze AB' +__all__ = ['Cf1ConfigDialog'] + +logger = logging.getLogger(__name__) + +service_dialog_class = uic.loadUiType(cfclient.module_path + + "/ui/dialogs/cf1config.ui")[0] -service_dialog_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/dialogs/cf1config.ui")[0] class UIState: DISCONNECTED = 0 @@ -57,9 +60,10 @@ class UIState: RESET = 4 -class Cf1ConfigDialog(QtGui.QWidget, service_dialog_class): +class Cf1ConfigDialog(QtWidgets.QWidget, service_dialog_class): """Tab for update the Crazyflie firmware and for reading/writing the config block in flash""" + def __init__(self, helper, *args): super(Cf1ConfigDialog, self).__init__(*args) self.setupUi(self) @@ -80,13 +84,13 @@ class Cf1ConfigDialog(QtGui.QWidget, service_dialog_class): self._cancel_bootloading.clicked.connect(self.close) self.clt.statusChanged.connect(self.statusUpdate) - self.clt.connectingSignal.connect(lambda: - self.setUiState(UIState.CONNECTING)) - self.clt.connectedSignal.connect(lambda: - self.setUiState(UIState.COLD_CONNECT)) + self.clt.connectingSignal.connect( + lambda: self.setUiState(UIState.CONNECTING)) + self.clt.connectedSignal.connect( + lambda: self.setUiState(UIState.COLD_CONNECT)) self.clt.failed_signal.connect(lambda m: self._ui_connection_fail(m)) - self.clt.disconnectedSignal.connect(lambda: - self.setUiState(UIState.DISCONNECTED)) + self.clt.disconnectedSignal.connect( + lambda: self.setUiState(UIState.DISCONNECTED)) self.clt.updateConfigSignal.connect(self.updateConfig) self.clt.start() @@ -219,13 +223,13 @@ class CrazyloadThread(QThread): self.failed_signal.emit("{}".format(e)) def checksum256(self, st): - return reduce(lambda x, y: x + y, map(ord, st)) % 256 + return reduce(lambda x, y: x + y, list(st)) % 256 def writeConfigAction(self, channel, speed, rollTrim, pitchTrim): data = (0x00, channel, speed, pitchTrim, rollTrim) image = struct.pack("<BBBff", *data) # Adding some magic: - image = "0xBC" + image + image = bytearray("0xBC".encode('ISO-8859-1')) + image image += struct.pack("B", 256 - self.checksum256(image)) self._bl.write_cf1_config(image) @@ -234,7 +238,7 @@ class CrazyloadThread(QThread): self.statusChanged.emit("Reading config block...", 0) data = self._bl.read_cf1_config() if (data is not None): - if data[0:4] == "0xBC": + if data[0:4] == bytearray("0xBC".encode('ISO-8859-1')): # Skip 0xBC and version at the beginning [channel, speed, @@ -246,7 +250,8 @@ class CrazyloadThread(QThread): speed = Config().get("default_cf_speed") pitchTrim = Config().get("default_cf_trim") rollTrim = Config().get("default_cf_trim") - self.statusChanged.emit("Could not find config block, showing defaults", 100) + self.statusChanged.emit( + "Could not find config block, showing defaults", 100) self.updateConfigSignal.emit(channel, speed, rollTrim, pitchTrim) else: self.statusChanged.emit("Reading config block failed!", 0) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.pyc deleted file mode 100755 index ab6c2681b1fd88b2195c184b6971087ffc8feb73..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11202 zcmc&)TXP&o74F$xT~^jzmTV_ZvL-fcfg{<0BoK_TCCiS8YE4G6lWY>UMl-Y0NV7A_ z%&ct@yC|>=2$kZA2mU~+;F(7#;0I6?e*lVC9(c+#m+w10H*b;x3M3?TtM8Z7=klHI zseUvu_KN-LZCj;3Rs6q#5YHJ(IZCw=8>($6r=qrzs3@nZoSO2hs*QwB*HpVE=^^D0 zsot<^4=W?B8&T~M<&LP`QRUXvLkuw{O^20#O!dZ9dtCJ<RC_}8CRKY<cN<aul<G~Z z_O$BFsP>HN&8qgS>dmS4oa!A{?c=)LsPgAkZ$Y⪙KXQ-4n{Ksoj&xsjE}Ym^y*k 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 W8`FrV@M7PrOyf3dvNBgcefOVH0f6NI diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf1config.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.py old mode 100755 new mode 100644 index 236fb245..7b8f855f --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.py @@ -20,32 +20,32 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ The bootloader dialog is used to update the Crazyflie firmware and to read/write the configuration block in the Crazyflie flash. """ +import logging -__author__ = 'Bitcraze AB' -__all__ = ['CfConfig'] +import cfclient +from cflib.crazyflie.mem import MemoryElement -import sys -import logging +from PyQt5 import QtWidgets +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal + +__author__ = 'Bitcraze AB' +__all__ = ['Cf2ConfigDialog'] logger = logging.getLogger(__name__) -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL -from cflib.crazyflie.mem import MemoryElement +service_dialog_class = uic.loadUiType(cfclient.module_path + + "/ui/dialogs/cf2config.ui")[0] -service_dialog_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/dialogs/cf2config.ui")[0] -class Cf2ConfigDialog(QtGui.QWidget, service_dialog_class): +class Cf2ConfigDialog(QtWidgets.QWidget, service_dialog_class): """Tab for update the Crazyflie firmware and for reading/writing the config block in flash""" @@ -67,7 +67,8 @@ class Cf2ConfigDialog(QtGui.QWidget, service_dialog_class): self._write_data_btn.clicked.connect(self._write_data) def _write_done(self, mem, addr): - self._cf.mem.get_mems(MemoryElement.TYPE_I2C)[0].update(self._data_updated) + self._cf.mem.get_mems( + MemoryElement.TYPE_I2C)[0].update(self._data_updated) def _data_updated(self, mem): self._roll_trim.setValue(mem.elements["roll_trim"]) @@ -76,10 +77,9 @@ class Cf2ConfigDialog(QtGui.QWidget, service_dialog_class): self._radio_speed.setCurrentIndex(mem.elements["radio_speed"]) if "radio_address" in mem.elements: self._radio_address.setValue(mem.elements["radio_address"]) - self._radio_address.setEnabled(True) else: self._radio_address.setValue(int("0xE7E7E7E7E7", 0)) - self._radio_address.setEnabled(False) + self._radio_address.setEnabled(True) self._write_data_btn.setEnabled(True) def _set_ui_connected(self, link_uri): diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.pyc deleted file mode 100755 index ad60a1c0724d08baa3898ba4db38cf7d0467ec8c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4257 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 Lci<m*d;Wg_Nz<k{ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/cf2config.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.py deleted file mode 100755 index dff76f7b..00000000 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# || ____ _ __ -# +------+ / __ )(_) /_______________ _____ ___ -# | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ -# +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ -# || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ -# -# Copyright (C) 2011-2013 Bitcraze AB -# -# Crazyflie Nano Quadcopter Client -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License along with -# this program; if not, write to the Free Software Foundation, Inc., 51 -# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -""" -Dialogue that lists available Crazyflies, lets user choose which to connect to. -""" - -__author__ = 'Bitcraze AB' -__all__ = ['ConnectionDialogue'] - -import sys - -from PyQt4 import QtGui, uic -from PyQt4.QtCore import pyqtSignal, pyqtSlot, QThread - -import cflib.crtp - -(connect_widget_class, -connect_widget_base_class) = (uic.loadUiType(sys.path[0] + - '/cfclient/ui/dialogs/connectiondialogue.ui')) - - -class ConnectDialogue(QtGui.QWidget, connect_widget_class): - - # Outgoing signal for connecting a Crazyflie - requestConnectionSignal = pyqtSignal(str) - - def __init__(self, *args): - super(ConnectDialogue, self).__init__(*args) - self.setupUi(self) - - self.scanner = ScannerThread() - self.scanner.start() - - # Connect signals to slots - self.connectButton.clicked.connect(self.openConnection) - self.scanButton.clicked.connect(self.rescan) - self.cancelButton.clicked.connect(self.cancel) - self.interfaceList.itemDoubleClicked.connect(self.interfaceSelected) - self.scanner.interfaceFoundSignal.connect(self.foundInterfaces) - self.box = None - self.address.setValue(0xE7E7E7E7E7) - - self.available_interfaces = [] - - def rescan(self): - """Disable all buttons and scan signals from Crazyflies.""" - self.interfaceList.clear() - self.interfaceList.addItem("Scanning...") - self.scanButton.setEnabled(False) - self.cancelButton.setEnabled(False) - self.connectButton.setEnabled(False) - self.scanner.scanSignal.emit(self.address.value()) - - def foundInterfaces(self, interfaces): - """ - Add found interfaces to list and enable buttons in UI. - """ - self.interfaceList.clear() - self.available_interfaces = interfaces - for i in interfaces: - if (len(i[1]) > 0): - self.interfaceList.addItem("%s - %s" % (i[0], i[1])) - else: - self.interfaceList.addItem(i[0]) - if len(interfaces) > 0: - self.interfaceList.setCurrentRow(0) - self.connectButton.setEnabled(True) - self.cancelButton.setEnabled(True) - self.scanButton.setEnabled(True) - - def interfaceSelected(self, listItem): - self.requestConnectionSignal.emit( - self.available_interfaces[self.interfaceList.currentRow()][0]) - self.close() - - def openConnection(self): - self.interfaceSelected(self.interfaceList.currentItem()) - - def cancel(self): - self.close() - - def showEvent(self, ev): - self.rescan() - - -class ScannerThread(QThread): - - scanSignal = pyqtSignal(object) - interfaceFoundSignal = pyqtSignal(object) - - def __init__(self): - QThread.__init__(self) - self.moveToThread(self) - self.scanSignal.connect(self.scan) - - def scan(self, address): - self.interfaceFoundSignal.emit(cflib.crtp.scan_interfaces(address)) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.pyc deleted file mode 100755 index cbacbabb4c9977ebb812ac2b985d07e1c9071eaf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4769 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.ui deleted file mode 100755 index 3e1f25aa..00000000 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/connectiondialogue.ui +++ /dev/null @@ -1,102 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ui version="4.0"> - <class>Form</class> - <widget class="QWidget" name="Form"> - <property name="windowModality"> - <enum>Qt::ApplicationModal</enum> - </property> - <property name="geometry"> - <rect> - <x>0</x> - <y>0</y> - <width>551</width> - <height>350</height> - </rect> - </property> - <property name="windowTitle"> - <string>Connect Crazyflie</string> - </property> - <layout class="QHBoxLayout" name="horizontalLayout"> - <item> - <layout class="QVBoxLayout" name="verticalLayout"> - <item> - <widget class="QLabel" name="label"> - <property name="font"> - <font> - <pointsize>16</pointsize> - </font> - </property> - <property name="text"> - <string>Connect to Crazyflie</string> - </property> - <property name="alignment"> - <set>Qt::AlignHCenter|Qt::AlignTop</set> - </property> - </widget> - </item> - <item> - <widget class="QListWidget" name="interfaceList"/> - </item> - <item> - <layout class="QHBoxLayout" name="horizontalLayout_2"> - <item> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Address:</string> - </property> - </widget> - </item> - <item> - <widget class="HexSpinBox" name="address"> - <property name="sizePolicy"> - <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> - <horstretch>0</horstretch> - <verstretch>0</verstretch> - </sizepolicy> - </property> - </widget> - </item> - </layout> - </item> - <item> - <layout class="QGridLayout" name="gridLayout"> - <item row="1" column="0"> - <widget class="QPushButton" name="scanButton"> - <property name="enabled"> - <bool>true</bool> - </property> - <property name="text"> - <string>Scan</string> - </property> - </widget> - </item> - <item row="1" column="2"> - <widget class="QPushButton" name="connectButton"> - <property name="text"> - <string>Connect</string> - </property> - </widget> - </item> - <item row="1" column="1"> - <widget class="QPushButton" name="cancelButton"> - <property name="text"> - <string>Cancel</string> - </property> - </widget> - </item> - </layout> - </item> - </layout> - </item> - </layout> - </widget> - <customwidgets> - <customwidget> - <class>HexSpinBox</class> - <extends>QSpinBox</extends> - <header>cfclient.ui.widgets.hexspinbox</header> - </customwidget> - </customwidgets> - <resources/> - <connections/> -</ui> diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.py old mode 100755 new mode 100644 index ec8ed5ac..d1f9c68b --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.py @@ -7,7 +7,7 @@ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ # -# Copyright (C) 2011-2013 Bitcraze AB +# Copyright (C) 2011-2017 Bitcraze AB # # Crazyflie Nano Quadcopter Client # @@ -20,41 +20,37 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -Dialogue used to select and configure an inputdevice. This includes mapping buttons and -axis to match controls for the Crazyflie. +Dialogue used to select and configure an inputdevice. This includes mapping +buttons and axis to match controls for the Crazyflie. """ - -__author__ = 'Bitcraze AB' -__all__ = ['InputConfigDialogue'] - -import sys -import json import logging -logger = logging.getLogger(__name__) - +import cfclient +from PyQt5.QtCore import QThread +from PyQt5.QtCore import QTimer +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtWidgets import QMessageBox from cfclient.utils.config_manager import ConfigManager -from cflib.crtp.exceptions import CommunicationException +from PyQt5 import Qt +from PyQt5 import QtWidgets +from PyQt5 import uic +from PyQt5.Qt import * # noqa -from PyQt4 import Qt, QtCore, QtGui, uic -from PyQt4.QtCore import * -from PyQt4.QtGui import * -from PyQt4.Qt import * +__author__ = 'Bitcraze AB' +__all__ = ['InputConfigDialogue'] -from cfclient.utils.input import JoystickReader +logger = logging.getLogger(__name__) -(inputconfig_widget_class, -connect_widget_base_class) = (uic.loadUiType(sys.path[0] + - '/cfclient/ui/dialogs/inputconfigdialogue.ui')) +(inputconfig_widget_class, connect_widget_base_class) = ( + uic.loadUiType(cfclient.module_path + '/ui/dialogs/inputconfigdialogue.ui') +) -class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): +class InputConfigDialogue(QtWidgets.QWidget, inputconfig_widget_class): def __init__(self, joystickReader, *args): super(InputConfigDialogue, self).__init__(*args) @@ -64,42 +60,76 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): self._input_device_reader = DeviceReader(self._input) self._input_device_reader.start() - self._input_device_reader.raw_axis_data_signal.connect(self._detect_axis) - self._input_device_reader.raw_button_data_signal.connect(self._detect_button) - self._input_device_reader.mapped_values_signal.connect(self._update_mapped_values) + self._input_device_reader.raw_axis_data_signal.connect( + self._detect_axis) + self._input_device_reader.raw_button_data_signal.connect( + self._detect_button) + self._input_device_reader.mapped_values_signal.connect( + self._update_mapped_values) self.cancelButton.clicked.connect(self.close) self.saveButton.clicked.connect(self._save_config) - - self.detectPitch.clicked.connect(lambda : self._axis_detect("pitch", "Pitch axis", - "Center the pitch axis then do max %s pitch", ["forward", "backward"])) - self.detectRoll.clicked.connect(lambda : self._axis_detect("roll", "Roll axis", - "Center the roll axis and then do max %s roll", ["right", "left"])) - self.detectYaw.clicked.connect(lambda : self._axis_detect("yaw", "Yaw axis", - "Center the yaw axis and then do max %s yaw", ["right", "left"])) - self.detectThrust.clicked.connect(lambda : self._axis_detect("thrust", "Thrust axis", - "Center the thrust axis, and then do max thrust (also used to adjust target altitude in altitude hold mode)")) - self.detectPitchPos.clicked.connect(lambda : self._button_detect("pitchPos", "Pitch Cal Positive", - "Press the button for Pitch postive calibration")) - self.detectPitchNeg.clicked.connect(lambda : self._button_detect("pitchNeg", "Pitch Cal Negative", - "Press the button for Pitch negative calibration")) - self.detectRollPos.clicked.connect(lambda : self._button_detect("rollPos", "Roll Cal Positive", - "Press the button for Roll positive calibration")) - self.detectRollNeg.clicked.connect(lambda : self._button_detect("rollNeg", "Roll Cal Negative", - "Press the button for Roll negative calibration")) - self.detectKillswitch.clicked.connect(lambda : self._button_detect("killswitch", "Killswitch", - "Press the button for the killswitch (will disable motors)")) - self.detectAlt1.clicked.connect(lambda : self._button_detect("alt1", "Alternative function 1", - "The alternative function 1 that will do a callback")) - self.detectAlt2.clicked.connect(lambda : self._button_detect("alt2", "Alternative function 2", - "The alternative function 2 that will do a callback")) - self.detectExitapp.clicked.connect(lambda : self._button_detect("exitapp", "Exit application", - "Press the button for exiting the application")) - self.detectAltHold.clicked.connect(lambda : self._button_detect("althold", "Altitude hold", - "Press the button for altitude hold mode activation (releasing returns to manual mode)")) - self.detectMuxswitch.clicked.connect(lambda: self._button_detect("muxswitch", "Mux Switch", - "Press the button for mux switching")) + self.detectPitch.clicked.connect( + lambda: self._axis_detect( + "pitch", "Pitch axis", + "Center the pitch axis then do max %s pitch", + ["forward", "backward"])) + self.detectRoll.clicked.connect( + lambda: self._axis_detect( + "roll", "Roll axis", + "Center the roll axis and then do max %s roll", + ["right", "left"])) + self.detectYaw.clicked.connect( + lambda: self._axis_detect( + "yaw", "Yaw axis", + "Center the yaw axis and then do max %s yaw", + ["right", "left"])) + self.detectThrust.clicked.connect( + lambda: self._axis_detect( + "thrust", "Thrust axis", + "Center the thrust axis, and then do max thrust")) + self.detectPitchPos.clicked.connect( + lambda: self._button_detect( + "pitchPos", "Pitch Cal Positive", + "Press the button for Pitch postive calibration")) + self.detectPitchNeg.clicked.connect( + lambda: self._button_detect( + "pitchNeg", "Pitch Cal Negative", + "Press the button for Pitch negative calibration")) + self.detectRollPos.clicked.connect( + lambda: self._button_detect( + "rollPos", "Roll Cal Positive", + "Press the button for Roll positive calibration")) + self.detectRollNeg.clicked.connect( + lambda: self._button_detect( + "rollNeg", "Roll Cal Negative", + "Press the button for Roll negative calibration")) + self.detectKillswitch.clicked.connect( + lambda: self._button_detect( + "killswitch", "Killswitch", + "Press the button for the killswitch (will disable motors)")) + self.detectAlt1.clicked.connect( + lambda: self._button_detect( + "alt1", "Alternative function 1", + "The alternative function 1 that will do a callback")) + self.detectAlt2.clicked.connect( + lambda: self._button_detect( + "alt2", "Alternative function 2", + "The alternative function 2 that will do a callback")) + self.detectExitapp.clicked.connect( + lambda: self._button_detect( + "exitapp", "Exit application", + "Press the button for exiting the application")) + self._detect_assisted_control.clicked.connect( + lambda: self._button_detect( + "assistedControl", "Assisted control", + "Press the button for assisted control mode activation " + "(releasing returns to manual mode)")) + self.detectMuxswitch.clicked.connect( + lambda: self._button_detect( + "muxswitch", "Mux Switch", + "Press the button for mux switching")) self.configButton.clicked.connect(self._start_configuration) self.loadButton.clicked.connect(self._load_config_from_file) @@ -107,13 +137,14 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): self._popup = None self._combined_button = None - self._detection_buttons = [self.detectPitch, self.detectRoll, - self.detectYaw, self.detectThrust, - self.detectPitchPos, self.detectPitchNeg, - self.detectRollPos, self.detectRollNeg, - self.detectKillswitch, self.detectExitapp, - self.detectAltHold, self.detectAlt1, - self.detectAlt2, self.detectMuxswitch] + self._detection_buttons = [ + self.detectPitch, self.detectRoll, + self.detectYaw, self.detectThrust, + self.detectPitchPos, self.detectPitchNeg, + self.detectRollPos, self.detectRollNeg, + self.detectKillswitch, self.detectExitapp, + self._detect_assisted_control, self.detectAlt1, + self.detectAlt2, self.detectMuxswitch] self._button_to_detect = "" self._axis_to_detect = "" @@ -139,10 +170,10 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): @staticmethod def _scale(max_value, value): - return (value/max_value) * 100 + return (value / max_value) * 100 def _reset_mapping(self): - self._buttonindicators= { + self._buttonindicators = { "pitchPos": self.pitchPos, "pitchNeg": self.pitchNeg, "rollPos": self.rollPos, @@ -151,16 +182,16 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): "alt1": self.alt1, "alt2": self.alt2, "exitapp": self.exitapp, - "althold": self.althold, + "assistedControl": self._assisted_control, "muxswitch": self.muxswitch, - } + } self._axisindicators = { "pitch": self.pitchAxisValue, "roll": self.rollAxisValue, "yaw": self.yawAxisValue, "thrust": self.thrustAxisValue, - } + } def _cancel_config_popup(self, button): self._axis_to_detect = "" @@ -171,22 +202,25 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): self._mined_axis = [] self._popup = QMessageBox() self._popup.directions = directions - self._combined_button = QtGui.QPushButton('Combined Axis Detection') - self.cancelButton = QtGui.QPushButton('Cancel') + self._combined_button = QtWidgets.QPushButton('Combined Axis ' + + 'Detection') + self.cancelButton = QtWidgets.QPushButton('Cancel') self._popup.addButton(self.cancelButton, QMessageBox.DestructiveRole) self._popup.setWindowTitle(caption) - self._popup.setWindowFlags(Qt.Dialog|Qt.MSWindowsFixedSizeDialogHint) + self._popup.setWindowFlags(Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint) if len(directions) > 1: self._popup.originalMessage = message message = self._popup.originalMessage % directions[0] self._combined_button.setCheckable(True) self._combined_button.blockSignals(True) - self._popup.addButton(self._combined_button, QMessageBox.ActionRole) + self._popup.addButton(self._combined_button, + QMessageBox.ActionRole) self._popup.setText(message) self._popup.show() def _start_configuration(self): - self._input.enableRawReading(str(self.inputDeviceSelector.currentText())) + self._input.enableRawReading( + str(self.inputDeviceSelector.currentText())) self._input_device_reader.start_reading() self._populate_config_dropdown() self.profileCombo.setEnabled(True) @@ -195,19 +229,22 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): def _detect_axis(self, data): if (len(self._axis_to_detect) > 0): - if self._combined_button and self._combined_button.isChecked() and self.combinedDetection == 0: + if (self._combined_button and self._combined_button.isChecked() and + self.combinedDetection == 0): self._combined_button.setDisabled(True) self.combinedDetection = 1 for a in data: # Axis must go low and high before it's accepted as selected # otherwise maxed out axis (like gyro/acc) in some controllers - # will always be selected. Not enforcing negative values makes it - # possible to detect split axis (like bumpers on PS3 controller) + # will always be selected. Not enforcing negative values makes + # it possible to detect split axis (like bumpers on PS3 + # controller) if a not in self._maxed_axis and abs(data[a]) > 0.8: self._maxed_axis.append(a) if a not in self._mined_axis and abs(data[a]) < 0.1: self._mined_axis.append(a) - if a in self._maxed_axis and a in self._mined_axis and len(self._axis_to_detect) > 0: + if a in self._maxed_axis and a in self._mined_axis and len( + self._axis_to_detect) > 0: if self.combinedDetection == 0: if data[a] >= 0: self._map_axis(self._axis_to_detect, a, 1.0) @@ -215,21 +252,23 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): self._map_axis(self._axis_to_detect, a, -1.0) self._axis_to_detect = "" self._check_and_enable_saving() - if self._popup != None: + if self._popup is not None: self.cancelButton.click() - elif self.combinedDetection == 2: #finished detection - if self._prev_combined_id != a: # not the same axis again ... + elif self.combinedDetection == 2: # finished detection + # not the same axis again ... + if self._prev_combined_id != a: self._map_axis(self._axis_to_detect, a, -1.0) self._axis_to_detect = "" self._check_and_enable_saving() - if (self._popup != None): + if (self._popup is not None): self.cancelButton.click() self.combinedDetection = 0 elif self.combinedDetection == 1: self._map_axis(self._axis_to_detect, a, 1.0) self._prev_combined_id = a self.combinedDetection = 2 - message = self._popup.originalMessage % self._popup.directions[1] + message = (self._popup.originalMessage % + self._popup.directions[1]) self._popup.setText(message) def _update_mapped_values(self, mapped_data): @@ -242,7 +281,7 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): if v in self._axisindicators: # The sliders used are set to 0-100 and the values from the # input-layer is scaled according to the max settings in - # the input-layer. So scale the value and place 0 in the middle. + # the input-layer. So scale the value and place 0 in the middle scaled_value = mapped_data.get(v) if v == "thrust": scaled_value = InputConfigDialogue._scale( @@ -268,7 +307,8 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): self._input.set_raw_input_map(self._map) def _map_button(self, function, key_id): - # Duplicate buttons is not allowed, remove if there's already one mapped + # Duplicate buttons are not allowed, remove if there's already one + # mapped prev_button = None for m in self._map: if "key" in self._map[m] and self._map[m]["key"] == function: @@ -290,7 +330,7 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): self._map_button(self._button_to_detect, b) self._button_to_detect = "" self._check_and_enable_saving() - if self._popup != None: + if self._popup is not None: self._popup.close() def _check_and_enable_saving(self): @@ -322,7 +362,8 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): QMessageBox.critical(self, caption, message) def _load_config_from_file(self): - loaded_map = ConfigManager().get_config(self.profileCombo.currentText()) + loaded_map = ConfigManager().get_config( + self.profileCombo.currentText()) if loaded_map: self._input.set_raw_input_map(loaded_map) self._map = loaded_map @@ -330,69 +371,32 @@ class InputConfigDialogue(QtGui.QWidget, inputconfig_widget_class): logger.warning("Could not load configfile [%s]", self.profileCombo.currentText()) self._show_error("Could not load config", - "Could not load config [%s]" % - self.profileCombo.currentText()) + "Could not load config [%s]" % + self.profileCombo.currentText()) self._check_and_enable_saving() def _delete_configuration(self): logger.warning("deleteConfig not implemented") def _save_config(self): - configName = str(self.profileCombo.currentText()) - - mapping = {'inputconfig': {'inputdevice': {'axis': []}}} - - # Create intermediate structure for the configuration file - funcs = {} - for m in self._map: - key = self._map[m]["key"] - if not key in funcs: - funcs[key] = [] - funcs[key].append(self._map[m]) - - # Create a mapping for each axis, take care to handle - # split axis configurations - for a in funcs: - func = funcs[a] - axis = {} - # Check for split axis - if len(func) > 1: - axis["ids"] = [func[0]["id"], func[1]["id"]] - axis["scale"] = func[1]["scale"] - else: - axis["id"] = func[0]["id"] - axis["scale"] = func[0]["scale"] - axis["key"] = func[0]["key"] - axis["name"] = func[0]["key"] # Name isn't used... - axis["type"] =func[0]["type"] - mapping["inputconfig"]["inputdevice"]["axis"].append(axis) - - mapping["inputconfig"]['inputdevice']['name'] = configName - mapping["inputconfig"]['inputdevice']['updateperiod'] = 10 - - config_name = self.profileCombo.currentText() - filename = ConfigManager().configs_dir + "/%s.json" % config_name - logger.info("Saving config to [%s]", filename) - json_data = open(filename, 'w') - json_data.write(json.dumps(mapping, indent=2)) - json_data.close() - - ConfigManager().conf_needs_reload.call(config_name) + config_name = str(self.profileCombo.currentText()) + ConfigManager().save_config(self._map, config_name) self.close() def showEvent(self, event): """Called when dialog is opened""" - #self._saved_open_device = self._input.get_device_name() - #self._input.stop_input() + # self._saved_open_device = self._input.get_device_name() + # self._input.stop_input() self._input.pause_input() def closeEvent(self, event): """Called when dialog is closed""" self._input.stop_raw_reading() self._input_device_reader.stop_reading() - #self._input.start_input(self._saved_open_device) + # self._input.start_input(self._saved_open_device) self._input.resume_input() + class DeviceReader(QThread): """Used for polling data from the Input layer during configuration""" raw_axis_data_signal = pyqtSignal(object) @@ -406,7 +410,7 @@ class DeviceReader(QThread): self._read_timer = QTimer() self._read_timer.setInterval(25) - self.connect(self._read_timer, SIGNAL("timeout()"), self._read_input) + self._read_timer.timeout.connect(self._read_input) def stop_reading(self): """Stop polling data""" diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.pyc deleted file mode 100755 index 0b7a51788ba0f7690c7604f11af4892f6bb744af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19318 zcmd5^TW}o5b?w<*Jaz#PAVGoxUs@}a1-*cXwiPR;ERmpW(w1Oy0Esdzc|6z|00Zoc zGqVJ!kZ}~riDNsdRPq(O94E2!kyOelf2PV+`AJohO6B27<?)sORDPUF<u}ebr)PI( zA<!jLRUiRuqq}c+PxtNn>U(>(_&*bs%eBwGRx{a85&vJrCpqL86Bx6K)G@1$2?}Nd znSu$5CMcPD(X1k4^Ch!d>gI>c>W~SC%+|08N6b6uGAhuJsh3ToVpc20VYgvZA2W?{ zvpR0eBc?uK8i&m4A=8*NtCOZNWmcz5<FHvhY+H<)`Vq6jzQ|4Yaz|~hZ0g5MW5%q` z7$-bzwvL;yXto|QLB-4lW9B$!@<zd|&YIN|TuV4*woaOG)~sVi<K|ss-ZAF$tEWsb zVZzg99Sc6xt3AUNFV9U9FKA{emm<I3+USJUP7(&yv{g;QdRR-Velw`nTFv!nqZ5ZH zRikFRlLq0<s20vwS2m*rHMM#t2$O2VZ?~i7Ms=-|rmbeez7>BLEihcePivbTDUDn8 zq`KaUtLbJ~U5x#=Zmrj&aK4g^VICKww1%p%df{R^jq(*fZBftf&M^83ewOC2nI@e; zVxh12O@AYdZS{<*8;wpgs`+WuYQD5v3){@hmDsI-<XV~z>)&E44$~oJKi!E^l1nG5 z*@5_wCv5f*vY%<)O46vd?S_63#t~{v@+6Xl+IkIZXr>FDXdw_LlLaBlqRv)z!g&nL zPW<5<F5;8?2uTRC#QqrW4+s+b3=-uIg4jTZ1=SCc>eyh|Y=DMK=3PKXOfaNM(B!Z( zWfP1jQz2Qg{g?^L%8ZkCSTkWjK+GJ<NCni%F()+UR7NQv(_m7~j+kIdnQ0RoR_3S) zjwo}?1k=jQnBb@~$Bnx@cMPklag8N>h`SMdlD`IaQ~WvRt5{sYY!%Gyg87Cq4$50a z)jGzxEx1=Q*cSpyL<BP4u!_TG3w)S$LSfWwl?AA<orXf~ShsdOUpvvQJ=Ck6G+SUD zJHp{!?U7vVbg%YkR{QHl4CR<#(<bSe#|B}AJZxqVR?NeW55h`$*h7P`p*(DM5H_5L zofw3T<Y6ZVVWWB2sX<sd4?8^wtK?y424Q1)*u#Uc@jR?L2%E^mJ~RkBl!rZ%!AKoH z*V~=5x!Om2wI9yaKBn5hh?*WJ$C0d_5cM2YdQ9nz(&I`WQaY>jgwm5rPbqy^X;tZI zrDv3W$ZQ;9#(R=X#LQFO%+us1*35S&ut4r(&Cho;&lrdo)|~5RKEmSGM@9I%=T#_~ zt&g#M>CGq2ouau7_3*5TSBh--3uf!%s(DW7FOuDy8!JWpT~9wT&>c*J32m25`~!6b za?hLed7-Lly3hY)cd{=qvpjbg487D7XOyKB*vTm*e7>|SBo|~>01-B1HVWn)>KwLQ zlE7_4*l#8kl&>;ZrLIVxKyeYGG_(prZ3LmdXjTKNlHKZ~NmY=PVg<@%$B%<_6!|s3 zw#|YS+T*D4III_hDb(2<%Ep2ym!RX;Rh4)sEo`<L;lf&`ffm|vYYSbH1u7)zsHd%v zPo8eyN;g~0g?hC1z9m1paC+zKeq$~0KlvFxo#Juaxn~q|1yH8-q>PM<j78v6DCH2y z78ZY0<$G{Qptd58Ha63gBi6(9R2XuJygtHQ>e>TCmP?iKGCm&^Nkxot%il?e{LlM4 z`_dTTcf}B3?iBjEB=-jdFH4xpUc7MY#D7e_I>>+T6v1|Euq2Zw-Hba)DsyW^S&I~K zY@TjxD}kPp6__WT3^?c4lUC1S^n)#oTTT6VBZT2tPoorOA<V;mezR2%s*P3<KK_89 z@+ua6kEkR?Nd{eQCCL#KtPorD>s8c5X>>D8=2;zw2~1!ZyVfq2?Q7e%TQDbYhSi!6 zQ4-5iwZe(i@7d<>kzDtI5nW8@gJNkZ+}ML9)L_ZL(!x*2QZsA!9yGZ$G9{8MH66T! zTDf<`P;pWGl6ojxB*5Pv@u(?iM>O^TV&%0DjuleN09Ja$a#xlTRvutldHvq8LKA5_ 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.ui old mode 100755 new mode 100644 index a8032bbd..3d7d4467 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.ui +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/inputconfigdialogue.ui @@ -92,7 +92,7 @@ <property name="minimumSize"> <size> <width>0</width> - <height>350</height> + <height>365</height> </size> </property> <property name="maximumSize"> @@ -507,7 +507,7 @@ <x>600</x> <y>158</y> <width>292</width> - <height>194</height> + <height>202</height> </rect> </property> <layout class="QGridLayout" name="gridLayout_5"> @@ -581,12 +581,12 @@ </widget> </item> <item row="1" column="0"> - <widget class="QCheckBox" name="althold"> + <widget class="QCheckBox" name="_assisted_control"> <property name="enabled"> <bool>false</bool> </property> <property name="text"> - <string>Altitude hold</string> + <string>Assisted control</string> </property> <property name="checkable"> <bool>true</bool> @@ -594,7 +594,7 @@ </widget> </item> <item row="1" column="1"> - <widget class="QPushButton" name="detectAltHold"> + <widget class="QPushButton" name="_detect_assisted_control"> <property name="enabled"> <bool>false</bool> </property> diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.py old mode 100755 new mode 100644 index 31ac80bd..d3996ded --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.py @@ -21,9 +21,9 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ This dialogue is used to configure different log configurations that is used to @@ -31,25 +31,23 @@ enable logging of data from the Crazyflie. These can then be used in different views in the UI. """ -__author__ = 'Bitcraze AB' -__all__ = ['LogConfigDialogue'] - -import sys -import os import logging -logger = logging.getLogger(__name__) +import cfclient +from PyQt5 import Qt, QtWidgets, uic +from PyQt5.QtCore import * # noqa +from PyQt5.QtWidgets import * # noqa +from PyQt5.Qt import * # noqa + +from cflib.crazyflie.log import LogConfig -from PyQt4 import Qt, QtCore, QtGui, uic -from PyQt4.QtCore import * -from PyQt4.QtGui import * -from PyQt4.Qt import * +__author__ = 'Bitcraze AB' +__all__ = ['LogConfigDialogue'] -from cflib.crazyflie.log import Log, LogVariable, LogConfig +logger = logging.getLogger(__name__) -(logconfig_widget_class, -connect_widget_base_class) = (uic.loadUiType(sys.path[0] + - '/cfclient/ui/dialogs/logconfigdialogue.ui')) +(logconfig_widget_class, connect_widget_base_class) = ( + uic.loadUiType(cfclient.module_path + '/ui/dialogs/logconfigdialogue.ui')) NAME_FIELD = 0 ID_FIELD = 1 @@ -57,7 +55,7 @@ PTYPE_FIELD = 2 CTYPE_FIELD = 3 -class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): +class LogConfigDialogue(QtWidgets.QWidget, logconfig_widget_class): def __init__(self, helper, *args): super(LogConfigDialogue, self).__init__(*args) @@ -77,7 +75,7 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): self.loggingPeriod.textChanged.connect(self.periodChanged) - self.packetSize.setMaximum(30) + self.packetSize.setMaximum(26) self.currentSize = 0 self.packetSize.setValue(0) self.period = 0 @@ -118,7 +116,14 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): for leaf in self.getNodeChildren(node): self.currentSize = (self.currentSize + self.decodeSize(leaf.text(CTYPE_FIELD))) - self.packetSize.setValue(self.currentSize) + if self.currentSize > 26: + self.packetSize.setMaximum(self.currentSize / 26.0 * 100.0) + self.packetSize.setFormat("%v%") + self.packetSize.setValue(self.currentSize / 26.0 * 100.0) + else: + self.packetSize.setMaximum(26) + self.packetSize.setFormat("%p%") + self.packetSize.setValue(self.currentSize) def addNewVar(self, logTreeItem, target): parentName = logTreeItem.parent().text(NAME_FIELD) @@ -127,7 +132,7 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): item = logTreeItem.clone() if (len(varParent) == 0): - newParent = QtGui.QTreeWidgetItem() + newParent = QtWidgets.QTreeWidgetItem() newParent.setData(0, Qt.DisplayRole, parentName) newParent.addChild(item) target.addTopLevelItem(newParent) @@ -137,7 +142,7 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): parent.addChild(item) def moveNodeItem(self, source, target, item): - if (item.parent() == None): + if (item.parent() is None): children = self.getNodeChildren(item) for c in children: self.addNewVar(c, target) @@ -154,7 +159,7 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): self.checkAndEnableSaveButton() def checkAndEnableSaveButton(self): - if (self.currentSize > 0 and self.period > 0): + if self.currentSize > 0 and self.period > 0 and self.currentSize <= 26: self.saveButton.setEnabled(True) else: self.saveButton.setEnabled(False) @@ -171,7 +176,7 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): if (parent.child(n).text(NAME_FIELD) == itemName): node = parent.child(n) break - if (node != None): + if (node is not None): self.moveNodeItem(source, target, node) return True return False @@ -180,7 +185,7 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): self.updateToc() self.populateDropDown() toc = self.helper.cf.log.toc - if (len(toc.toc.keys()) > 0): + if (len(list(toc.toc.keys())) > 0): self.configNameCombo.setEnabled(True) else: self.configNameCombo.setEnabled(False) @@ -197,7 +202,7 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): self.period = 0 def showErrorPopup(self, caption, message): - self.box = QMessageBox() + self.box = QMessageBox() # noqa self.box.setWindowTitle(caption) self.box.setText(message) # self.box.setButtonText(1, "Ok") @@ -209,11 +214,11 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): toc = self.helper.cf.log.toc - for group in toc.toc.keys(): - groupItem = QtGui.QTreeWidgetItem() + for group in list(toc.toc.keys()): + groupItem = QtWidgets.QTreeWidgetItem() groupItem.setData(NAME_FIELD, Qt.DisplayRole, group) - for param in toc.toc[group].keys(): - item = QtGui.QTreeWidgetItem() + for param in list(toc.toc[group].keys()): + item = QtWidgets.QTreeWidgetItem() item.setData(NAME_FIELD, Qt.DisplayRole, param) item.setData(ID_FIELD, Qt.DisplayRole, toc.toc[group][param].ident) @@ -241,7 +246,7 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): for d in self.helper.logConfigReader.getLogConfigs(): if (d.name == cText): config = d - if (config == None): + if (config is None): logger.warning("Could not load config") else: self.resetTrees() @@ -252,11 +257,11 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): parts = v.name.split(".") varParent = parts[0] varName = parts[1] - if self.moveNodeByName(self.logTree, - self.varTree, - varParent, - varName) == False: - logger.warning("Could not find node %s.%s!!", varParent, varName) + if self.moveNodeByName( + self.logTree, self.varTree, varParent, + varName) is False: + logger.warning("Could not find node %s.%s!!", + varParent, varName) else: logger.warning("Error: Mem vars not supported!") @@ -280,4 +285,3 @@ class LogConfigDialogue(QtGui.QWidget, logconfig_widget_class): completeName = "%s.%s" % (parentName, varName) logconfig.add_variable(completeName, varType) return logconfig - diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.pyc deleted file mode 100755 index b40dc18a485fa00619560986b8b0610fc644e4df..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11145 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/dialogs/logconfigdialogue.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.py old mode 100755 new mode 100644 index 0c3b59b2..c33b9ba0 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.py @@ -20,59 +20,62 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., 51 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - """ The main file for the Crazyflie control application. """ -__author__ = 'Bitcraze AB' -__all__ = ['MainUI'] - -import sys import logging +import sys - -logger = logging.getLogger(__name__) - -import PyQt4 -from PyQt4 import QtGui, uic -from PyQt4.QtCore import pyqtSignal, Qt, pyqtSlot, QDir, QUrl -from PyQt4.QtGui import QLabel, QActionGroup, QMessageBox, QAction, QDesktopServices, QMenu - -from dialogs.connectiondialogue import ConnectDialogue -from dialogs.inputconfigdialogue import InputConfigDialogue -from dialogs.cf2config import Cf2ConfigDialog -from dialogs.cf1config import Cf1ConfigDialog -from cflib.crazyflie import Crazyflie -from dialogs.logconfigdialogue import LogConfigDialogue - -from cfclient.utils.input import JoystickReader -from cfclient.utils.zmq_param import ZMQParamAccess -from cfclient.utils.zmq_led_driver import ZMQLEDDriver -from cfclient.utils.config import Config -from cfclient.utils.logconfigreader import LogConfigReader -from cfclient.utils.config_manager import ConfigManager - -import cfclient.ui.toolboxes +import cfclient import cfclient.ui.tabs +import cfclient.ui.toolboxes import cflib.crtp +from cfclient.ui.dialogs.about import AboutDialog +from cfclient.ui.dialogs.bootloader import BootloaderDialog +from cfclient.utils.config import Config +from cfclient.utils.config_manager import ConfigManager +from cfclient.utils.input import JoystickReader +from cfclient.utils.logconfigreader import LogConfigReader +from cfclient.utils.zmq_led_driver import ZMQLEDDriver +from cfclient.utils.zmq_param import ZMQParamAccess +from cflib.crazyflie import Crazyflie +from cflib.crazyflie.log import LogConfig +from cflib.crazyflie.mem import MemoryElement +from PyQt5 import QtWidgets +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import pyqtSlot +from PyQt5.QtCore import QDir +from PyQt5.QtCore import QThread +from PyQt5.QtCore import QUrl +from PyQt5.QtWidgets import QAction +from PyQt5.QtWidgets import QActionGroup +from PyQt5.QtGui import QDesktopServices +from PyQt5.QtWidgets import QLabel +from PyQt5.QtWidgets import QMenu +from PyQt5.QtWidgets import QMessageBox + +from .dialogs.cf1config import Cf1ConfigDialog +from .dialogs.cf2config import Cf2ConfigDialog +from .dialogs.inputconfigdialogue import InputConfigDialogue +from .dialogs.logconfigdialogue import LogConfigDialogue -from cflib.crazyflie.log import Log, LogVariable, LogConfig +__author__ = 'Bitcraze AB' +__all__ = ['MainUI'] -from cfclient.ui.dialogs.bootloader import BootloaderDialog -from cfclient.ui.dialogs.about import AboutDialog +logger = logging.getLogger(__name__) -from cflib.crazyflie.mem import MemoryElement +INTERFACE_PROMPT_TEXT = 'Select an interface' (main_window_class, -main_windows_base_class) = (uic.loadUiType(sys.path[0] + - '/cfclient/ui/main.ui')) + main_windows_base_class) = (uic.loadUiType(cfclient.module_path + + '/ui/main.ui')) -class MyDockWidget(QtGui.QDockWidget): +class MyDockWidget(QtWidgets.QDockWidget): closed = pyqtSignal() def closeEvent(self, event): @@ -84,10 +87,32 @@ class UIState: DISCONNECTED = 0 CONNECTING = 1 CONNECTED = 2 + SCANNING = 3 + + +class BatteryStates: + BATTERY, CHARGING, CHARGED, LOW_POWER = list(range(4)) + + +COLOR_BLUE = '#3399ff' +COLOR_GREEN = '#00ff60' +COLOR_RED = '#cc0404' -class MainUI(QtGui.QMainWindow, main_window_class): +def progressbar_stylesheet(color): + return """ + QProgressBar { + border: 1px solid #333; + background-color: transparent; + } + QProgressBar::chunk { + background-color: """ + color + """; + } + """ + + +class MainUI(QtWidgets.QMainWindow, main_window_class): connectionLostSignal = pyqtSignal(str, str) connectionInitiatedSignal = pyqtSignal(str) batteryUpdatedSignal = pyqtSignal(int, object, object) @@ -103,46 +128,55 @@ class MainUI(QtGui.QMainWindow, main_window_class): def __init__(self, *args): super(MainUI, self).__init__(*args) self.setupUi(self) - + + # Restore window size if present in the config file + try: + size = Config().get("window_size") + self.resize(size[0], size[1]) + except KeyError: + pass + ###################################################### - ### By lxrocks - ### 'Skinny Progress Bar' tweak for Yosemite - ### Tweak progress bar - artistic I am not - so pick your own colors !!! - ### Only apply to Yosemite + # By lxrocks + # 'Skinny Progress Bar' tweak for Yosemite + # Tweak progress bar - artistic I am not - so pick your own colors !!! + # Only apply to Yosemite ###################################################### import platform + if platform.system() == 'Darwin': - - (Version,junk,machine) = platform.mac_ver() - logger.info("This is a MAC - checking if we can apply Progress Bar Stylesheet for Yosemite Skinny Bars ") - yosemite = (10,10,0) + + (Version, junk, machine) = platform.mac_ver() + logger.info("This is a MAC - checking if we can apply Progress " + "Bar Stylesheet for Yosemite Skinny Bars ") + yosemite = (10, 10, 0) tVersion = tuple(map(int, (Version.split(".")))) - + if tVersion >= yosemite: - logger.info( "Found Yosemite:") - + logger.info("Found Yosemite - applying stylesheet") + tcss = """ QProgressBar { - border: 2px solid grey; - border-radius: 5px; - text-align: center; - } - QProgressBar::chunk { - background-color: #05B8CC; - } + border: 1px solid grey; + border-radius: 5px; + text-align: center; + } + QProgressBar::chunk { + background-color: """ + COLOR_BLUE + """; + } """ self.setStyleSheet(tcss) - + else: - logger.info( "Pre-Yosemite") - + logger.info("Pre-Yosemite - skinny bar stylesheet not applied") + ###################################################### - - self.cf = Crazyflie(ro_cache=sys.path[0] + "/cflib/cache", - rw_cache=sys.path[1] + "/cache") + + self.cf = Crazyflie(ro_cache=None, + rw_cache=cfclient.config_path + "/cache") cflib.crtp.init_drivers(enable_debug_driver=Config() - .get("enable_debug_driver")) + .get("enable_debug_driver")) zmq_params = ZMQParamAccess(self.cf) zmq_params.start() @@ -150,8 +184,9 @@ class MainUI(QtGui.QMainWindow, main_window_class): zmq_leds = ZMQLEDDriver(self.cf) zmq_leds.start() - # Create the connection dialogue - self.connectDialogue = ConnectDialogue() + self.scanner = ScannerThread() + self.scanner.interfaceFoundSignal.connect(self.foundInterfaces) + self.scanner.start() # Create and start the Input Reader self._statusbar_label = QLabel("No input-device found, insert one to" @@ -160,70 +195,84 @@ class MainUI(QtGui.QMainWindow, main_window_class): self.joystickReader = JoystickReader() self._active_device = "" - #self.configGroup = QActionGroup(self._menu_mappings, exclusive=True) + # self.configGroup = QActionGroup(self._menu_mappings, exclusive=True) self._mux_group = QActionGroup(self._menu_inputdevice, exclusive=True) # TODO: Need to reload configs - #ConfigManager().conf_needs_reload.add_callback(self._reload_configs) - - # Connections for the Connect Dialogue - self.connectDialogue.requestConnectionSignal.connect(self.cf.open_link) + # ConfigManager().conf_needs_reload.add_callback(self._reload_configs) - self.cf.connection_failed.add_callback(self.connectionFailedSignal.emit) + self.cf.connection_failed.add_callback( + self.connectionFailedSignal.emit) self.connectionFailedSignal.connect(self._connection_failed) - - - self._input_device_error_signal.connect(self._display_input_device_error) + + self._input_device_error_signal.connect( + self._display_input_device_error) self.joystickReader.device_error.add_callback( - self._input_device_error_signal.emit) + self._input_device_error_signal.emit) self._input_discovery_signal.connect(self.device_discovery) self.joystickReader.device_discovery.add_callback( - self._input_discovery_signal.emit) + self._input_discovery_signal.emit) + + # Hide the 'File' menu on OS X, since its only item, 'Exit', gets + # merged into the application menu. + if sys.platform == 'darwin': + self.menuFile.menuAction().setVisible(False) # Connect UI signals - self.menuItemConnect.triggered.connect(self._connect) self.logConfigAction.triggered.connect(self._show_connect_dialog) + self.interfaceCombo.currentIndexChanged['QString'].connect( + self.interfaceChanged) self.connectButton.clicked.connect(self._connect) - self.quickConnectButton.clicked.connect(self._quick_connect) - self.menuItemQuickConnect.triggered.connect(self._quick_connect) - self.menuItemConfInputDevice.triggered.connect(self._show_input_device_config_dialog) + self.scanButton.clicked.connect(self._scan) + self.menuItemConnect.triggered.connect(self._connect) + self.menuItemConfInputDevice.triggered.connect( + self._show_input_device_config_dialog) self.menuItemExit.triggered.connect(self.closeAppRequest) - self.batteryUpdatedSignal.connect(self._update_vbatt) + self.batteryUpdatedSignal.connect(self._update_battery) self._menuitem_rescandevices.triggered.connect(self._rescan_devices) - self._menuItem_openconfigfolder.triggered.connect(self._open_config_folder) + self._menuItem_openconfigfolder.triggered.connect( + self._open_config_folder) + + self.address.setValue(0xE7E7E7E7E7) self._auto_reconnect_enabled = Config().get("auto_reconnect") self.autoReconnectCheckBox.toggled.connect( - self._auto_reconnect_changed) + self._auto_reconnect_changed) self.autoReconnectCheckBox.setChecked(Config().get("auto_reconnect")) - + self.joystickReader.input_updated.add_callback( - self.cf.commander.send_setpoint) + self.cf.commander.send_setpoint) + + self.joystickReader.assisted_input_updated.add_callback( + self.cf.commander.send_velocity_world_setpoint) # Connection callbacks and signal wrappers for UI protection self.cf.connected.add_callback(self.connectionDoneSignal.emit) self.connectionDoneSignal.connect(self._connected) self.cf.disconnected.add_callback(self.disconnectedSignal.emit) - self.disconnectedSignal.connect( - lambda linkURI: self._update_ui_state(UIState.DISCONNECTED, - linkURI)) + self.disconnectedSignal.connect(self._disconnected) self.cf.connection_lost.add_callback(self.connectionLostSignal.emit) self.connectionLostSignal.connect(self._connection_lost) self.cf.connection_requested.add_callback( - self.connectionInitiatedSignal.emit) - self.connectionInitiatedSignal.connect( - lambda linkURI: self._update_ui_state(UIState.CONNECTING, - linkURI)) + self.connectionInitiatedSignal.emit) + self.connectionInitiatedSignal.connect(self._connection_initiated) self._log_error_signal.connect(self._logging_error) + self.batteryBar.setTextVisible(False) + self.batteryBar.setStyleSheet(progressbar_stylesheet(COLOR_BLUE)) + + self.linkQualityBar.setTextVisible(False) + self.linkQualityBar.setStyleSheet(progressbar_stylesheet(COLOR_BLUE)) + # Connect link quality feedback self.cf.link_quality_updated.add_callback(self.linkQualitySignal.emit) self.linkQualitySignal.connect( - lambda percentage: self.linkQualityBar.setValue(percentage)) + lambda percentage: self.linkQualityBar.setValue(percentage)) - # Set UI state in disconnected buy default - self._update_ui_state(UIState.DISCONNECTED) + self._selected_interface = None + self._initial_scan = True + self._scan() # Parse the log configuration files self.logConfigReader = LogConfigReader(self.cf) @@ -249,39 +298,18 @@ class MainUI(QtGui.QMainWindow, main_window_class): self._menu_cf2_config.triggered.connect(self._cf2config_dialog.show) self._menu_cf1_config.triggered.connect(self._cf1config_dialog.show) - # Loading toolboxes (A bit of magic for a lot of automatic) - self.toolboxes = [] - self.toolboxesMenuItem.setMenu(QtGui.QMenu()) - for t_class in cfclient.ui.toolboxes.toolboxes: - toolbox = t_class(cfclient.ui.pluginhelper) - dockToolbox = MyDockWidget(toolbox.getName()) - dockToolbox.setWidget(toolbox) - self.toolboxes += [dockToolbox, ] - - # Add menu item for the toolbox - item = QtGui.QAction(toolbox.getName(), self) - item.setCheckable(True) - item.triggered.connect(self.toggleToolbox) - self.toolboxesMenuItem.menu().addAction(item) - - dockToolbox.closed.connect(lambda: self.toggleToolbox(False)) - - # Setup some introspection - item.dockToolbox = dockToolbox - item.menuItem = item - dockToolbox.dockToolbox = dockToolbox - dockToolbox.menuItem = item - # Load and connect tabs - self.tabsMenuItem.setMenu(QtGui.QMenu()) + self.tabsMenuItem = QMenu("Tabs", self.menuView, enabled=True) + self.menuView.addMenu(self.tabsMenuItem) + + # self.tabsMenuItem.setMenu(QtWidgets.QMenu()) tabItems = {} self.loadedTabs = [] for tabClass in cfclient.ui.tabs.available: tab = tabClass(self.tabs, cfclient.ui.pluginhelper) - item = QtGui.QAction(tab.getMenuName(), self) - item.setCheckable(True) + item = QtWidgets.QAction(tab.getMenuName(), self, checkable=True) item.toggled.connect(tab.toggleVisibility) - self.tabsMenuItem.menu().addAction(item) + self.tabsMenuItem.addAction(item) tabItems[tab.getTabName()] = item self.loadedTabs.append(tab) if not tab.enabled: @@ -291,12 +319,38 @@ class MainUI(QtGui.QMainWindow, main_window_class): try: for tName in Config().get("open_tabs").split(","): t = tabItems[tName] - if (t != None and t.isEnabled()): + if (t is not None and t.isEnabled()): # Toggle though menu so it's also marked as open there t.toggle() except Exception as e: logger.warning("Exception while opening tabs [{}]".format(e)) + # Loading toolboxes (A bit of magic for a lot of automatic) + self.toolboxesMenuItem = QMenu("Toolboxes", self.menuView, + enabled=True) + self.menuView.addMenu(self.toolboxesMenuItem) + + self.toolboxes = [] + for t_class in cfclient.ui.toolboxes.toolboxes: + toolbox = t_class(cfclient.ui.pluginhelper) + dockToolbox = MyDockWidget(toolbox.getName()) + dockToolbox.setWidget(toolbox) + self.toolboxes += [dockToolbox, ] + + # Add menu item for the toolbox + item = QtWidgets.QAction(toolbox.getName(), self) + item.setCheckable(True) + item.triggered.connect(self.toggleToolbox) + self.toolboxesMenuItem.addAction(item) + + dockToolbox.closed.connect(lambda: self.toggleToolbox(False)) + + # Setup some introspection + item.dockToolbox = dockToolbox + item.menuItem = item + dockToolbox.dockToolbox = dockToolbox + dockToolbox.menuItem = item + # References to all the device sub-menus in the "Input device" menu self._all_role_menus = () # Used to filter what new devices to add default mapping to @@ -315,54 +369,127 @@ class MainUI(QtGui.QMainWindow, main_window_class): node.toggled.connect(self._mux_selected) self._mux_group.addAction(node) self._menu_inputdevice.addAction(node) - self._all_mux_nodes += (node, ) + self._all_mux_nodes += (node,) mux_subnodes = () for name in m.supported_roles(): sub_node = QMenu(" {}".format(name), - self._menu_inputdevice, - enabled=False) + self._menu_inputdevice, + enabled=False) self._menu_inputdevice.addMenu(sub_node) - mux_subnodes += (sub_node, ) + mux_subnodes += (sub_node,) self._all_role_menus += ({"muxmenu": node, - "rolemenu": sub_node}, ) + "rolemenu": sub_node},) node.setData((m, mux_subnodes)) self._mapping_support = True - def _update_ui_state(self, newState, linkURI=""): - self.uiState = newState - if newState == UIState.DISCONNECTED: + def interfaceChanged(self, interface): + if interface == INTERFACE_PROMPT_TEXT: + self._selected_interface = None + else: + self._selected_interface = interface + self._update_ui_state() + + def foundInterfaces(self, interfaces): + selected_interface = self._selected_interface + + self.interfaceCombo.clear() + self.interfaceCombo.addItem(INTERFACE_PROMPT_TEXT) + + formatted_interfaces = [] + for i in interfaces: + if len(i[1]) > 0: + interface = "%s - %s" % (i[0], i[1]) + else: + interface = i[0] + formatted_interfaces.append(interface) + self.interfaceCombo.addItems(formatted_interfaces) + + if self._initial_scan: + self._initial_scan = False + + try: + if len(Config().get("link_uri")) > 0: + formatted_interfaces.index(Config().get("link_uri")) + selected_interface = Config().get("link_uri") + except KeyError: + # The configuration for link_uri was not found + pass + except ValueError: + # The saved URI was not found while scanning + pass + + if len(interfaces) == 1 and selected_interface is None: + selected_interface = interfaces[0][0] + + newIndex = 0 + if selected_interface is not None: + try: + newIndex = formatted_interfaces.index(selected_interface) + 1 + except ValueError: + pass + + self.interfaceCombo.setCurrentIndex(newIndex) + + self.uiState = UIState.DISCONNECTED + self._update_ui_state() + + def _update_ui_state(self): + if self.uiState == UIState.DISCONNECTED: self.setWindowTitle("Not connected") + canConnect = self._selected_interface is not None self.menuItemConnect.setText("Connect to Crazyflie") + self.menuItemConnect.setEnabled(canConnect) self.connectButton.setText("Connect") - self.menuItemQuickConnect.setEnabled(True) + self.connectButton.setToolTip( + "Connect to the Crazyflie on the selected interface") + self.connectButton.setEnabled(canConnect) + self.scanButton.setText("Scan") + self.scanButton.setEnabled(True) + self.address.setEnabled(True) self.batteryBar.setValue(3000) self._menu_cf2_config.setEnabled(False) self._menu_cf1_config.setEnabled(True) self.linkQualityBar.setValue(0) self.menuItemBootloader.setEnabled(True) self.logConfigAction.setEnabled(False) - if len(Config().get("link_uri")) > 0: - self.quickConnectButton.setEnabled(True) - if newState == UIState.CONNECTED: - s = "Connected on %s" % linkURI + self.interfaceCombo.setEnabled(True) + elif self.uiState == UIState.CONNECTED: + s = "Connected on %s" % self._selected_interface self.setWindowTitle(s) self.menuItemConnect.setText("Disconnect") + self.menuItemConnect.setEnabled(True) self.connectButton.setText("Disconnect") + self.connectButton.setToolTip("Disconnect from the Crazyflie") + self.scanButton.setEnabled(False) self.logConfigAction.setEnabled(True) # Find out if there's an I2C EEPROM, otherwise don't show the # dialog. if len(self.cf.mem.get_mems(MemoryElement.TYPE_I2C)) > 0: self._menu_cf2_config.setEnabled(True) self._menu_cf1_config.setEnabled(False) - if newState == UIState.CONNECTING: - s = "Connecting to {} ...".format(linkURI) + elif self.uiState == UIState.CONNECTING: + s = "Connecting to {} ...".format(self._selected_interface) self.setWindowTitle(s) self.menuItemConnect.setText("Cancel") + self.menuItemConnect.setEnabled(True) self.connectButton.setText("Cancel") - self.quickConnectButton.setEnabled(False) + self.connectButton.setToolTip("Cancel connecting to the Crazyflie") + self.scanButton.setEnabled(False) + self.address.setEnabled(False) self.menuItemBootloader.setEnabled(False) - self.menuItemQuickConnect.setEnabled(False) + self.interfaceCombo.setEnabled(False) + elif self.uiState == UIState.SCANNING: + self.setWindowTitle("Scanning ...") + self.connectButton.setText("Connect") + self.menuItemConnect.setEnabled(False) + self.connectButton.setText("Connect") + self.connectButton.setEnabled(False) + self.scanButton.setText("Scanning...") + self.scanButton.setEnabled(False) + self.address.setEnabled(False) + self.menuItemBootloader.setEnabled(False) + self.interfaceCombo.setEnabled(False) @pyqtSlot(bool) def toggleToolbox(self, display): @@ -386,34 +513,46 @@ class MainUI(QtGui.QMainWindow, main_window_class): self._active_device = "" self.joystickReader.stop_input() - #for c in self._menu_mappings.actions(): + # for c in self._menu_mappings.actions(): # c.setEnabled(False) - #devs = self.joystickReader.available_devices() - #if (len(devs) > 0): + # devs = self.joystickReader.available_devices() + # if (len(devs) > 0): # self.device_discovery(devs) def _show_input_device_config_dialog(self): self.inputConfig = InputConfigDialogue(self.joystickReader) self.inputConfig.show() - + def _auto_reconnect_changed(self, checked): - self._auto_reconnect_enabled = checked + self._auto_reconnect_enabled = checked Config().set("auto_reconnect", checked) logger.info("Auto reconnect enabled: {}".format(checked)) def _show_connect_dialog(self): self.logConfigDialogue.show() - def _update_vbatt(self, timestamp, data, logconf): + def _update_battery(self, timestamp, data, logconf): self.batteryBar.setValue(int(data["pm.vbat"] * 1000)) - def _connected(self, linkURI): - self._update_ui_state(UIState.CONNECTED, linkURI) + color = COLOR_BLUE + # TODO firmware reports fully-charged state as 'Battery', + # rather than 'Charged' + if data["pm.state"] in [BatteryStates.CHARGING, BatteryStates.CHARGED]: + color = COLOR_GREEN + elif data["pm.state"] == BatteryStates.LOW_POWER: + color = COLOR_RED - Config().set("link_uri", str(linkURI)) + self.batteryBar.setStyleSheet(progressbar_stylesheet(color)) + + def _connected(self): + self.uiState = UIState.CONNECTED + self._update_ui_state() + + Config().set("link_uri", str(self._selected_interface)) lg = LogConfig("Battery", 1000) lg.add_variable("pm.vbat", "float") + lg.add_variable("pm.state", "int8_t") try: self.cf.log.add_config(lg) lg.data_received_cb.add_callback(self.batteryUpdatedSignal.emit) @@ -422,23 +561,25 @@ class MainUI(QtGui.QMainWindow, main_window_class): except KeyError as e: logger.warning(str(e)) - mem = self.cf.mem.get_mems(MemoryElement.TYPE_DRIVER_LED)[0] - mem.write_data(self._led_write_done) + mems = self.cf.mem.get_mems(MemoryElement.TYPE_DRIVER_LED) + if len(mems) > 0: + mems[0].write_data(self._led_write_done) - #self._led_write_test = 0 + def _disconnected(self): + self.uiState = UIState.DISCONNECTED + self._update_ui_state() - #mem.leds[self._led_write_test] = [10, 20, 30] - #mem.write_data(self._led_write_done) + def _connection_initiated(self): + self.uiState = UIState.CONNECTING + self._update_ui_state() def _led_write_done(self, mem, addr): logger.info("LED write done callback") - #self._led_write_test += 1 - #mem.leds[self._led_write_test] = [10, 20, 30] - #mem.write_data(self._led_write_done) def _logging_error(self, log_conf, msg): QMessageBox.about(self, "Log error", "Error when starting log config" - " [{}]: {}".format(log_conf.name, msg)) + " [{}]: {}".format(log_conf.name, + msg)) def _connection_lost(self, linkURI, msg): if not self._auto_reconnect_enabled: @@ -446,32 +587,44 @@ class MainUI(QtGui.QMainWindow, main_window_class): warningCaption = "Communication failure" error = "Connection lost to {}: {}".format(linkURI, msg) QMessageBox.critical(self, warningCaption, error) - self._update_ui_state(UIState.DISCONNECTED, linkURI) + self.uiState = UIState.DISCONNECTED + self._update_ui_state() else: - self._quick_connect() + self._connect() def _connection_failed(self, linkURI, error): if not self._auto_reconnect_enabled: msg = "Failed to connect on {}: {}".format(linkURI, error) warningCaption = "Communication failure" QMessageBox.critical(self, warningCaption, msg) - self._update_ui_state(UIState.DISCONNECTED, linkURI) + self.uiState = UIState.DISCONNECTED + self._update_ui_state() else: - self._quick_connect() + self._connect() def closeEvent(self, event): self.hide() self.cf.close_link() Config().save_file() + def resizeEvent(self, event): + Config().set("window_size", [event.size().width(), + event.size().height()]) + def _connect(self): if self.uiState == UIState.CONNECTED: self.cf.close_link() elif self.uiState == UIState.CONNECTING: self.cf.close_link() - self._update_ui_state(UIState.DISCONNECTED) + self.uiState = UIState.DISCONNECTED + self._update_ui_state() else: - self.connectDialogue.show() + self.cf.open_link(self._selected_interface) + + def _scan(self): + self.uiState = UIState.SCANNING + self._update_ui_state() + self.scanner.scanSignal.emit(self.address.value()) def _display_input_device_error(self, error): self.cf.close_link() @@ -482,11 +635,11 @@ class MainUI(QtGui.QMainWindow, main_window_class): reference to the raw mux object as well as to the associated device sub-nodes""" if not checked: - (mux, sub_nodes) = self.sender().data().toPyObject() + (mux, sub_nodes) = self.sender().data() for s in sub_nodes: s.setEnabled(False) else: - (mux, sub_nodes) = self.sender().data().toPyObject() + (mux, sub_nodes) = self.sender().data() for s in sub_nodes: s.setEnabled(True) self.joystickReader.set_mux(mux=mux) @@ -518,13 +671,13 @@ class MainUI(QtGui.QMainWindow, main_window_class): if len(self.joystickReader.available_devices()) > 0: mux = self.joystickReader._selected_mux msg = "Using {} mux with ".format(mux.name) - for key in mux._devs.keys()[:-1]: + for key in list(mux._devs.keys())[:-1]: if mux._devs[key]: msg += "{}, ".format(self._get_dev_status(mux._devs[key])) else: msg += "N/A, " # Last item - key = mux._devs.keys()[-1] + key = list(mux._devs.keys())[-1] if mux._devs[key]: msg += "{}".format(self._get_dev_status(mux._devs[key])) else: @@ -537,22 +690,22 @@ class MainUI(QtGui.QMainWindow, main_window_class): """Called when a new input device has been selected from the menu. The data in the menu object is the associated map menu (directly under the item in the menu) and the raw device""" - (map_menu, device, mux_menu) = self.sender().data().toPyObject() + (map_menu, device, mux_menu) = self.sender().data() if not checked: if map_menu: map_menu.setEnabled(False) - # Do not close the device, since we don't know exactly - # how many devices the mux can have open. When selecting a - # new mux the old one will take care of this. + # Do not close the device, since we don't know exactly + # how many devices the mux can have open. When selecting a + # new mux the old one will take care of this. else: if map_menu: map_menu.setEnabled(True) - (mux, sub_nodes) = mux_menu.data().toPyObject() + (mux, sub_nodes) = mux_menu.data() for role_node in sub_nodes: for dev_node in role_node.children(): if type(dev_node) is QAction and dev_node.isChecked(): - if device.id == dev_node.data().toPyObject()[1].id \ + if device.id == dev_node.data()[1].id \ and dev_node is not self.sender(): dev_node.setChecked(False) @@ -562,8 +715,9 @@ class MainUI(QtGui.QMainWindow, main_window_class): Config().set("input_device", str(device.name)) - self._mapping_support = self.joystickReader.start_input(device.name, - role_in_mux) + self._mapping_support = self.joystickReader.start_input( + device.name, + role_in_mux) self._update_input_device_footer() def _inputconfig_selected(self, checked): @@ -574,7 +728,7 @@ class MainUI(QtGui.QMainWindow, main_window_class): return selected_mapping = str(self.sender().text()) - device = self.sender().data().toPyObject().data().toPyObject()[1] + device = self.sender().data().data()[1] self.joystickReader.set_input_map(device.name, selected_mapping) self._update_input_device_footer() @@ -612,7 +766,7 @@ class MainUI(QtGui.QMainWindow, main_window_class): # select the default mapping for it. if d not in self._available_devices: last_map = Config().get("device_config_mapping") - if last_map.has_key(d.name) and last_map[d.name] == c: + if d.name in last_map and last_map[d.name] == c: node.setChecked(True) role_menu.addMenu(map_node) dev_node.setData((map_node, d, mux_menu)) @@ -622,12 +776,12 @@ class MainUI(QtGui.QMainWindow, main_window_class): # a new one is inserted self._available_devices = () for d in devs: - self._available_devices += (d, ) + self._available_devices += (d,) # Only enable MUX nodes if we have enough devies to cover # the roles for mux_node in self._all_mux_nodes: - (mux, sub_nodes) = mux_node.data().toPyObject() + (mux, sub_nodes) = mux_node.data() if len(mux.supported_roles()) <= len(self._available_devices): mux_node.setEnabled(True) @@ -652,16 +806,25 @@ class MainUI(QtGui.QMainWindow, main_window_class): self._update_input_device_footer() - def _quick_connect(self): - try: - self.cf.open_link(Config().get("link_uri")) - except KeyError: - self.cf.open_link("") - def _open_config_folder(self): - QDesktopServices.openUrl(QUrl("file:///" + - QDir.toNativeSeparators(sys.path[1]))) + QDesktopServices.openUrl( + QUrl("file:///" + + QDir.toNativeSeparators(cfclient.config_path))) def closeAppRequest(self): self.close() sys.exit(0) + + +class ScannerThread(QThread): + + scanSignal = pyqtSignal(object) + interfaceFoundSignal = pyqtSignal(object) + + def __init__(self): + QThread.__init__(self) + self.moveToThread(self) + self.scanSignal.connect(self.scan) + + def scan(self, address): + self.interfaceFoundSignal.emit(cflib.crtp.scan_interfaces(address)) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.pyc deleted file mode 100755 index 354b7bcf1879459e213634c9b237de32a70a699e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22709 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 Ye;eYII)iYSpfrc4HGF*2H`@EZ0V+4lQ2+n{ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.ui old mode 100755 new mode 100644 index 25cd15f6..3e9d5270 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.ui +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/main.ui @@ -7,7 +7,7 @@ <x>0</x> <y>0</y> <width>872</width> - <height>641</height> + <height>671</height> </rect> </property> <property name="windowTitle"> @@ -22,16 +22,36 @@ <layout class="QVBoxLayout" name="verticalLayout_2"> <item> <layout class="QGridLayout" name="gridLayout_2"> - <item row="0" column="1"> - <widget class="QPushButton" name="quickConnectButton"> - <property name="enabled"> + <item row="0" column="0"> + <widget class="QComboBox" name="interfaceCombo"> + <property name="minimumSize"> + <size> + <width>160</width> + <height>0</height> + </size> + </property> + <property name="editable"> <bool>false</bool> </property> - <property name="toolTip"> - <string><html><head/><body><p>Quickconnect using the last connection parameters</p></body></html></string> + </widget> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="connectButton"> + <property name="minimumSize"> + <size> + <width>60</width> + <height>0</height> + </size> </property> - <property name="text"> - <string>Quick Connect</string> + </widget> + </item> + <item row="0" column="2"> + <widget class="QPushButton" name="scanButton"> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> </property> </widget> </item> @@ -48,11 +68,18 @@ </property> </spacer> </item> - <item row="0" column="5"> + <item row="0" column="6"> + <widget class="QLabel" name="linkQualityLabel"> + <property name="text"> + <string>Link Quality:</string> + </property> + </widget> + </item> + <item row="0" column="7"> <widget class="QProgressBar" name="linkQualityBar"> <property name="minimumSize"> <size> - <width>150</width> + <width>30</width> <height>0</height> </size> </property> @@ -76,27 +103,24 @@ </property> </widget> </item> - <item row="0" column="0"> - <widget class="QPushButton" name="connectButton"> - <property name="toolTip"> - <string><html><head/><body><p>Connect to a Crazyflie</p></body></html></string> - </property> + <item row="0" column="4"> + <widget class="QLabel" name="batteryLabel"> <property name="text"> - <string>Connect</string> + <string>Battery:</string> </property> </widget> </item> - <item row="0" column="4"> + <item row="0" column="5"> <widget class="QProgressBar" name="batteryBar"> <property name="minimumSize"> <size> - <width>150</width> + <width>30</width> <height>0</height> </size> </property> <property name="maximumSize"> <size> - <width>150</width> + <width>100</width> <height>16777215</height> </size> </property> @@ -123,26 +147,101 @@ </property> </widget> </item> - <item row="0" column="2"> - <widget class="QCheckBox" name="autoReconnectCheckBox"> - <property name="mouseTracking"> - <bool>false</bool> - </property> - <property name="text"> - <string>Auto Reconnect</string> - </property> - <property name="checked"> - <bool>false</bool> - </property> - </widget> - </item> </layout> </item> <item> - <widget class="QTabWidget" name="tabs"> - <property name="currentIndex"> - <number>-1</number> + <widget class="QGroupBox" name="groupBox"> + <layout class="QHBoxLayout" stretch="0,0,1"> + <item> + <widget class="QLabel" name="addressLabel"> + <property name="text"> + <string>Address:</string> + </property> + </widget> + </item> + <item> + <widget class="HexSpinBox" name="address"> + <property name="minimumSize"> + <size> + <width>140</width> + <height>0</height> + </size> + </property> + </widget> + </item> + <item> + <widget class="QCheckBox" name="autoReconnectCheckBox"> + <property name="mouseTracking"> + <bool>false</bool> + </property> + <property name="text"> + <string>Auto Reconnect</string> + </property> + <property name="checked"> + <bool>false</bool> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QScrollArea" name="scrollArea"> + <property name="autoFillBackground"> + <bool>false</bool> + </property> + <property name="frameShape"> + <enum>QFrame::NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>QFrame::Sunken</enum> + </property> + <property name="lineWidth"> + <number>1</number> + </property> + <property name="verticalScrollBarPolicy"> + <enum>Qt::ScrollBarAsNeeded</enum> </property> + <property name="widgetResizable"> + <bool>true</bool> + </property> + <widget class="QWidget" name="scrollAreaWidgetContents"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>852</width> + <height>500</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <layout class="QGridLayout" name="gridLayout_3"> + <property name="sizeConstraint"> + <enum>QLayout::SetNoConstraint</enum> + </property> + <property name="margin"> + <number>0</number> + </property> + <item row="0" column="0"> + <widget class="QTabWidget" name="tabs"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Expanding"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="currentIndex"> + <number>-1</number> + </property> + </widget> + </item> + </layout> + </widget> </widget> </item> </layout> @@ -169,8 +268,6 @@ <property name="title"> <string>View</string> </property> - <addaction name="tabsMenuItem"/> - <addaction name="toolboxesMenuItem"/> </widget> <widget class="QMenu" name="menuHelp"> <property name="title"> @@ -186,12 +283,11 @@ <addaction name="separator"/> <addaction name="_menuItem_openconfigfolder"/> </widget> - <widget class="QMenu" name="menuCrazyflie"> + <widget class="QMenu" name="menuConnect"> <property name="title"> - <string>Crazyflie</string> + <string>Connect</string> </property> <addaction name="menuItemConnect"/> - <addaction name="menuItemQuickConnect"/> <addaction name="menuItemBootloader"/> <addaction name="_menu_cf2_config"/> <addaction name="_menu_cf1_config"/> @@ -205,7 +301,7 @@ <addaction name="separator"/> </widget> <addaction name="menuFile"/> - <addaction name="menuCrazyflie"/> + <addaction name="menuConnect"/> <addaction name="_menu_inputdevice"/> <addaction name="menuSettings"/> <addaction name="menuView"/> @@ -221,9 +317,6 @@ <property name="text"> <string>Exit</string> </property> - <property name="menuRole"> - <enum>QAction::NoRole</enum> - </property> </action> <action name="menuItemRegulation"> <property name="checkable"> @@ -265,11 +358,6 @@ <enum>QAction::NoRole</enum> </property> </action> - <action name="menuItemQuickConnect"> - <property name="text"> - <string>Quick connect</string> - </property> - </action> <action name="menuItemConfInputDevice"> <property name="text"> <string>Configure device mapping</string> @@ -288,16 +376,6 @@ <string>Console</string> </property> </action> - <action name="toolboxesMenuItem"> - <property name="text"> - <string>Toolboxes</string> - </property> - </action> - <action name="tabsMenuItem"> - <property name="text"> - <string>Tabs</string> - </property> - </action> <action name="logConfigAction"> <property name="enabled"> <bool>false</bool> @@ -370,6 +448,13 @@ </property> </action> </widget> + <customwidgets> + <customwidget> + <class>HexSpinBox</class> + <extends>QSpinBox</extends> + <header>cfclient.ui.widgets.hexspinbox</header> + </customwidget> + </customwidgets> <resources/> <connections/> </ui> diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/pluginhelper.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/pluginhelper.py old mode 100755 new mode 100644 index 36cdde03..0fabf3db --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/pluginhelper.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/pluginhelper.py @@ -21,9 +21,9 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Used for passing objects to tabs and toolboxes. @@ -35,6 +35,7 @@ __all__ = ['PluginHelper'] class PluginHelper(): """Used for passing objects to tabs and toolboxes""" + def __init__(self): self.cf = None self.menu = None diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/pluginhelper.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/pluginhelper.pyc deleted file mode 100755 index 06a84b6b0cc14e0ab6ae757a2f890ea9d224a53a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 857 zcmcgpv2N5r5FMX`;SLZbUE(5&u1L<JM+lOJ>J&Lp<eHW3UHcZTcP;N)B8UzuK8@eW z5AbGvN@@zQHP18aH#5)A>HW)9|NGach7MPX=X-=d2S}nFFri&SazP!E1t;<e$&`K) z{UEyCr6iB&W}R`@8^G$bS2Azim=Bfr+IG3Czo;hoJh(hmwa+UnkvmhnugY&${yDlX zb!f)wo60|2h8L)>&D3f8QJF!F59$&oBK&KBf;#8|LQ%qUAf>!nFPN|a{GE=5hjVcM z6~dnYF#bD{h<iA}s`&(8P55eV*shO&fnn>c3Ot}`W8Et|g;%JJ>#m$_byuoNsxkIO zhF7LtgFq4dHL_ywdR5d1LyBQ^(Y}KHxoeG97Y)D$e=*#Jy|abUb<wo*VKM1qh~Dj^ zcN=h?VW<$=>LA1!a?k&Yk|pk0`b@A@uY?Gz$nKq-43|%1DP1E($$gJv|DECzd*~G5 v+0-n_lI^^f%W?@gsH`R!Fg~cPjDbqL{x2${uWx6g-W_9U^fg;#$uj)|`F7C( diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tab.py old mode 100755 new mode 100644 index 3913e341..ebcd60b9 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tab.py @@ -21,27 +21,28 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Superclass for all tabs that implements common functions. """ -__author__ = 'Bitcraze AB' -__all__ = ['Tab'] - import logging -logger = logging.getLogger(__name__) -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL +from PyQt5 import QtWidgets +from PyQt5.QtCore import pyqtSlot from cfclient.utils.config import Config +__author__ = 'Bitcraze AB' +__all__ = ['Tab'] + +logger = logging.getLogger(__name__) -class Tab(QtGui.QWidget): + +class Tab(QtWidgets.QWidget): """Superclass for all tabs that implements common functions.""" def __init__(self): @@ -60,7 +61,7 @@ class Tab(QtGui.QWidget): s = Config().get("open_tabs") if (len(s) > 0): s += "," - except Exception as e: + except Exception: logger.warning("Exception while adding tab to config and " "reading tab config") # Check this since tabs in config are opened when app is started @@ -72,7 +73,7 @@ class Tab(QtGui.QWidget): self.tabWidget.removeTab(self.tabWidget.indexOf(self)) try: parts = Config().get("open_tabs").split(",") - except Exception as e: + except Exception: logger.warning("Exception while removing tab from config and " "reading tab config") parts = [] @@ -90,3 +91,6 @@ class Tab(QtGui.QWidget): def getTabName(self): """Return the name of the tab that will be shown in the tab""" return self.tabName + + def is_visible(self): + return self.tabWidget.currentWidget() == self diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tab.pyc deleted file mode 100755 index a18916cffa5e79aa6b00b247f4326c0ec69183ce..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2814 zcmcIm>yFz*6h32Tvq`$?Zd+O|s;K*;B|_~+q98z^Lc5@XXcy|NS{eyOjy*{x>r3jH zunpS&Di6R9UV!)LTk!z!o#VJv`~Xz3j%PA+=JuWMT*m(I-Og9>HxFW3KR*6HN3p-5 zN{EK26%7?79!=5kDDf$2Q0mjrC+*X`L3)FpVW=rX8<cKR)}mpHvNjFdlyzv>A;rs@ zl%Aq&i-ud2b!ph8>@*EeQ?^aRZOV3NxKqvBr1T7BXK8pAeUEgT=I3Yv3@!SZ=o!(Y z;cE<H&}%c)Pf&FR%Y`oEG_p3B6lD;lY2c!<4cshpfyoxB&UEf<5Eofi<iTW_$IcYF z-R;;@Sby8NxQu?%!L8elIXH;M<_|pkJ?^<Cs{3xQD7D*==AEUHc}o-bSmHbpyB7Wy ztH*AT7S46*j+y3B>Na`G!K~C#A{!3AzO#SpZcjlh{k<Zem}!izJiOy=6nhhuhABV* zYFI!q4NQN{JxF3=Y9sLICKJSs7KH<WXg|h2uS`?SFu5=vdnoojR1UAAW1Q{L++))y zphJHIb61T9fijlBKX87J)!Mhb%YOe>k2w)aE!!_dkA%a~$mGV2MnW14xgTX(24Kad zbQ+j?P%gF1(0MdYby9K3BUY!A9`7cVy@OVNR%E(AUK_f<D2us{o$a&TSCiD}>oF?$ z$o0j_&5FFAnsGm#RKot!^Z{dcu?pE;`Y4udP3oL#;}^49>?Q0BLeH-t>sV3woRy#B z6*{;rJb^H#>ZwPo4+yRV>JUmWB&-M_b0+P?r^5!7kGKnqeu%N0=wTjE15R_;q4Jp2 zQ=b%gn71gASX8;9@A;@UFFV{66j<LBEN!~L+pG`m@S*P1`Z$L5_&FZ|?DiM6#=cc6 z(d7mp;#I3l^&U0w`Dw<;8Z-d$>I;Zh)XNYzW%ZPJ76Ywlc(O~!4f^7TtMpX-g|TnY zp-<%v#k#k+E5IM$P<S7*(0_@jHobBApVWd*Ne2$d_Os_v4Q9nrfLt*%iAJ74fq~)C za6!&1#X{#Jh^!G2`~Ee_HD5l7^@5W}a5OWi4x%J6`IJ`&u0Vp}C=Q}L2{_X0kxFdY zO|Dq`8UFshO{ufu$9nptEV6&uibLp%y=EBLes3GKzy^$mCYfp{IR)4bqOoKmh|uKN z30XZ!Up$TXN#XY_e1S<8r^R%tO9`-}sLX*a+^SdF^-AkXSt;l>pT!|<@<c!Rc2Y(5 zA~mkZu@Ua@Y95bgIzH41atCZ7b(L5bQR%Aw;$))N2?Xes>IcS}u>m#&AW(2RBfqKM zR88fpv-q7++v<#uqAqz&brI4_kaWEcW^~ayuU=O%Yfu-7dseTCnt`MvNxPwT%Q6=y z%VB_^nA8qeT~J2`_tjVj7A~0wrkcsAPPPcU*t2Re{1ak^;{yJ0Z=GNtpeyc5-hWW? zBg}p!CE>1>X6#uftz&orhv1W@R!qJh*7ptD1@{f#*`rZbB+Hb$Y|YUqDdN#c5`QR{ zJ>M|nqDaH5XoT-@#XJ9H7-{{lw+^<aYbcfhHdWJWH_u;gH+r1N!go=vkw;71UF8ep z_zqgPIhYZ_609)uU5V|GfrfAKa#rlS)qVGV$nG3+q6#@RI5vz7>{eeuA!{!@gc8(D zQP|>{jHSLXcbCqjcDG7<Rl?zk_p96_7ySv+B{u!Evf|CRajxaSX(Ei<-j>?-E~=il G<Npc0m~_|x diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ConsoleTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ConsoleTab.py old mode 100755 new mode 100644 index a90e1bed..88a6061e --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ConsoleTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ConsoleTab.py @@ -21,35 +21,36 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ The console tab is used as a console for printouts from the Crazyflie. """ -__author__ = 'Bitcraze AB' -__all__ = ['ConsoleTab'] - -import time -import sys - import logging -logger = logging.getLogger(__name__) -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import pyqtSlot, pyqtSignal +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal +import cfclient from cfclient.ui.tab import Tab -console_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/consoleTab.ui")[0] +__author__ = 'Bitcraze AB' +__all__ = ['ConsoleTab'] + +logger = logging.getLogger(__name__) + +console_tab_class = uic.loadUiType(cfclient.module_path + + "/ui/tabs/consoleTab.ui")[0] class ConsoleTab(Tab, console_tab_class): """Console tab for showing printouts from Crazyflie""" - update = pyqtSignal(str) + _connected_signal = pyqtSignal(str) + _disconnected_signal = pyqtSignal(str) + _update = pyqtSignal(str) def __init__(self, tabWidget, helper, *args): super(ConsoleTab, self).__init__(*args) @@ -59,14 +60,37 @@ class ConsoleTab(Tab, console_tab_class): self.menuName = "Console" self.tabWidget = tabWidget - self.helper = helper + self._helper = helper + + # Always wrap callbacks from Crazyflie API though QT Signal/Slots + # to avoid manipulating the UI when rendering it + self._connected_signal.connect(self._connected) + self._disconnected_signal.connect(self._disconnected) + self._update.connect(self.printText) - self.update.connect(self.printText) + self._helper.cf.console.receivedChar.add_callback(self._update.emit) + self._helper.cf.connected.add_callback(self._connected_signal.emit) + self._helper.cf.disconnected.add_callback( + self._disconnected_signal.emit) - self.helper.cf.console.receivedChar.add_callback(self.update.emit) + self._clearButton.clicked.connect(self.clear) + self._dumpSystemLoadButton.clicked.connect( + lambda enabled: + self._helper.cf.param.set_value("system.taskDump", '1')) def printText(self, text): # Make sure we get printouts from the Crazyflie into the log (such as # build version and test ok/fail) logger.debug("[%s]", text) self.console.insertPlainText(text) + + def clear(self): + self.console.clear() + + def _connected(self, link_uri): + """Callback when the Crazyflie has been connected""" + self._dumpSystemLoadButton.setEnabled(True) + + def _disconnected(self, link_uri): + """Callback for when the Crazyflie has been disconnected""" + self._dumpSystemLoadButton.setEnabled(False) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ConsoleTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ConsoleTab.pyc deleted file mode 100755 index 979bf106dc4e463400fc56259c980787123275fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1935 zcmcgsOONA35H35fNhYshmRVNfkpoCMuoHw3Cxl>vv>ecA*U1WDge=GIByIe{-3Ee& z({e)mEiU{WegJ$`P6i3iOO&ou^`lbteP4I$&(R?J<JWaW$4?8tpJ15ZVPYa5)*;`a z*rgpDm*N)1ZAx3@!)g3B`R$Y6A-_YaLrIrZk6z%&nJjfE?Nc@&e?Zwe`R9}k$sdx# zDY}%7C>xVMrffp~q?zqeI;HG_{0nl_kdjwOwJEuz_>3OKeR_!8?D`M5Hg!Sj0c}y< zfPNu*LG+dXDi^w%pL08(!wlAYHH(Ve6seloa5K|pRvQ)1LNg2R7q&$;D=VGbqPAwX zt%_`Bac)_KKOMHIR@Vc=8E>?WFr{Xn-q-=+Ws`RuZuDRH+|C(E+l6^%mqn#)N8Bg1 zw!Bj7XzuckGnn%5on57cl|&NgT^^=$hd1zU&Way0Z^100ZG<{<yQuX7ZJ5QeC+xaL zUf#$bPJe@8-i1-15_rJ^s}>{4)O46!z~y%tLw0)Pt)z7G9!?#b60jH-voC(o`R?EN z++!1Qv26_geS%?rhOziMbO%;kN?f{Y(QiZ!;-n?B4)~V!04i#n4&60Qm+o+aDCn_G z&M4`NGvN9qM~{+oN}!JsCF9eki7cbtm7siUd#K~s&3wu=F&(BZRpr5HXb1wGYa0Zz z*(h6=&$ajf`8LdyaFwaNmY~na!p)aD-YF|Y?^TL?;?`vxS|x`;POc(rdB5mtt$wtY z$%(e74Xj8z#8jmsrN3A4avxSQ5yo*4g=xA8qi-!Et1@lp>_}u(y7fkgyzyx&tafIO zfW(*;yv4rA)M9f~?4qoS1QkIyCrv+Y1Z5tV2fHuwMXERdRoM|fR#|!QxSbC%45LZT zl{0etPG82Q8*zI)SO-fC^EM20kU)bV)?q0Kdr$;KfS5&aPnY2azkbJj({#$WC@pq7 zfXlSSYE$pLOU^if(Ye9G(=^mMLo0-P4|!E!;wc0#8IBA5!)F*$Ikl$FoG-R0CJ1tf z2eRU4A_%e~u2T+Kl0gs`Q4o0CmfUn>E03EJd_B(kPw_98Q2Z6Wk72m*uG4jfZht(# zLg4YMbF4nBA&~06dMFdV;H+^$m~L}0(i#(nw?cG}8}fzl=e@!C9&tWy`RU=A{lMdA z&SSNBd|qTP3)jud>2dl7Ax7r(`r)a&#{KhH98z3bgz<B|K9oudDnq-s3?MEb->(3h tgD4G+ksJR%!72*)sNwwMH&Kmw4W{dMaaV?bc<4;r*PSbO>Q0?;>u)c4xyS$j diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ExampleTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ExampleTab.py old mode 100755 new mode 100644 index e34870a9..9c455d4f --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ExampleTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ExampleTab.py @@ -32,25 +32,23 @@ with the necessary QT Signals to wrap Crazyflie API callbacks and also connects the connected/disconnected callbacks. """ -__author__ = 'Bitcraze AB' -__all__ = ['ExampleTab'] - import logging -import sys - -logger = logging.getLogger(__name__) -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import pyqtSlot, pyqtSignal, QThread, Qt -from PyQt4.QtGui import QMessageBox +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtWidgets import QMessageBox +import cfclient from cfclient.ui.tab import Tab -from cflib.crazyflie.log import LogConfig, Log -from cflib.crazyflie.param import Param +__author__ = 'Bitcraze AB' +__all__ = ['ExampleTab'] + +logger = logging.getLogger(__name__) + +example_tab_class = uic.loadUiType(cfclient.module_path + + "/ui/tabs/exampleTab.ui")[0] -example_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/exampleTab.ui")[0] class ExampleTab(Tab, example_tab_class): """Tab for plotting logging data""" @@ -110,4 +108,4 @@ class ExampleTab(Tab, example_tab_class): QMessageBox.about(self, "Example error", "Error when using log config" - " [{0}]: {1}".format(log_conf.name, msg)) \ No newline at end of file + " [{0}]: {1}".format(log_conf.name, msg)) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ExampleTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ExampleTab.pyc deleted file mode 100755 index 8ef24d306d402aa0303d10941dfbb52747162bff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4045 zcmcgv-;dkI5gtl+x|8mQ&gb*lPMnr)fJQA~DGpK;2#O;1AqWDbhRr*pEsKDl#Fa#a z6jkmj&ehJ7`&9Jr>O)`p$Mmre?e`5S-B||uP{5Y7tJ&FE?(VnW%nqCXI_Tv8`0K?; z>Q58@pQG4+qe?_V)SiT%Bn_EBXh_nOWJ|K9gb*ruOTsNNO_^<rX~`>??P%AwWV@2L zC2ULHk+38Ao`ieiaac>TeaR0bJdpfQ!b8cs5_Tm&lJKaq*pcjp<i`>oSM6QNZc2V4 z;YrnQOLj~0QwdKczb)bIO52g_j^uYGyeppBli7P>wq*9cBztl<*_Yc`9mVh-cVte) z+><djbs&Ecc_s3P@B?n|ymv?t{*J2iaPFJ$<9v}B-x>VH&iLb^^kd(}LqDDSZfg9q zGXC@BI7=a+n!CRLmGehMZmhp3&HYg^AE%RLX_C(K)J=8B+>DI1ae3)Kz3|V|$vn=i z?+X8U885Cq@8OfL{85}`!+7+q_2YTs!>;JyiFkm+2+UqLOfpDPyKY<!>v!xPw(=-- zBdpW-4<ES>+Fw-Lx`>DAfAD$S<LSE=s;BO(D2>}z@yliE*t1MWy)9boqFP-3$(?6~ z(+6ooci?t7<YHQyIB^ZiuIF(K=YRTJZg^rI72j7%J{7a~Xz1FgzAh$b3YAWXR%OR^ zJc-LVPa%l?F{;66JW`|w%XEN)u!H)L@Vq`&N<)6Q;72I-Z>S6ijq^v1vu~0aBr90E zmRl<Ch}q@u6<FR@4Vo}+ki?a7-Q1&lfI8tm`9$G>)TeMrB2nl{vaP}qX-~}!3C?>& z%6@<fD^@}+2xmH<_*pTT@IQ%NJR(M0DE$8t#r_kO!_SkKplm~C4SCrVY|le`)>N$r zXVCs=i|ay1v@I_yO-o)@njPwAyE1F5&><N547g3D+Fz><R;t6bs=HDhtyMcRyCJh< zncZAH`edW;)~XM4RDFrS+qk*M%AJ~%%GX-<Ns&|Tnmn+}g((9F6%V5*ou@8}bg(sU zxp<bU3{E_bbE9O<&3vg1ats~6OOuIlY8FjRh6lPE=!w>@6WJ>^*GeV&m4!Rufa~tI z8gsDO;f|=mp+-E=mD%xY$`ZjK{mvxr7S#)KJz6ecZ<5sjMx@t!)WJq$^_=z6-9GH% zB#Bl*!;w8EPo4H$UvcHl?6xKw2R9+8_t%iHBQ7Vlhkwz^o<kZ;5!MF7I+hF;WiewQ z8ZfkI2)ti8roF$obkkx!$kO4P-g*^#`isk;i|2lhV(+06@6<bJv^{(q?X8=hew$tB zy55MPf`yDZL$U9nf;-IM*Pi-<N6L}PAb!Ox+oy3IL;dGdvl+9evGs=r>NSe?E{Cjk zbfss2e(}S#NJ(D>eaOtj43`rH5Z6N<I}K~Whg=^cW|q#sjh1El4&c0v>3)x5iIg<| zKhS=Op=;21;r%b*uG7l?h$Gk7UGMV8Ws$D|41NZ~;3HN9<qEIh=WL?9W!mwOzd>2y zL{hPk`ARN^=M8cpcp~V&&aY2t{|3KGGfAy8xb%H>Xam_t-1*4*wQE}jfoGMQ`!7EJ zLD}`7rq?DqTv){>E^p4*M%H~7XG`-Aup$&gloeK71Pj-oSbYd#6D#C|xR3x>a|5ya z9Q6iba3(*CF9A~>53N5p&-EVE3jq*)_TmA`C%}l4Z(tPs0=lY0SEJ!RMH1$aziAv~ z1g^Xh;TYaNeh0|Ck3~&TR><)nS(s>@QBOChki&(HD2BkrOC8~?0#EVtkXD@Q-t5O5 zxB^c-ib>!Vc<QJz($=zs+ZLnIvb2`h(&|Fh4xRQ3HPHb}Tjw5(cF0!!KLYM=KJx*1 z4fZbA$@7kf#nP$IR)}*qO3i?gR&%%9PToGWPVYp9U@Se-U1eB+C9=}o_gY?$9;OE# zMRXY?3e0??C@+#_#wOFSC`yV^6b0OyuHL#b;7uIdS!vR_)6iZFdD{hg>uAn^*{hlB zdph71rWabkFdQ((1azK&JP013x&lU}w|1*yD)|+P<t|!YtFiCxd&gea>o(eV+S}E) z$7mfeg4M{xOWfM!8X54cmTR0VfG(}39SCP%>kSxu!pA6+iQ<#Xr|#2$nSa1LC?G>L z|Im(p^?nhk3)4K{i3L0geNk8$;mspZ(lI|+CH%<l`^ez}b#CS?BfNJF`|I?hk97t- z<bdxSnow<8XgCg-DCwTFB2J#A7ncj8F=7$Bspf;GdOwOVTQtgIYXgjUSEr|>{dGmt h-~0sgYHrkOw2&3y92?!nJ@2R9QRAp_%Gx_@{1?|d$dCX4 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/FlightTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/FlightTab.py old mode 100755 new mode 100644 index 8995debb..6bc9fc99 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/FlightTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/FlightTab.py @@ -21,47 +21,45 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ The flight control tab shows telemetry data and flight settings. """ -__author__ = 'Bitcraze AB' -__all__ = ['FlightTab'] - -import sys - import logging -logger = logging.getLogger(__name__) - -from time import time -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QVariant -from PyQt4.QtGui import QMessageBox - -from cflib.crazyflie import Crazyflie +from PyQt5 import uic +from PyQt5.QtCore import Qt, pyqtSlot, pyqtSignal +from PyQt5.QtWidgets import QMessageBox +import cfclient from cfclient.ui.widgets.ai import AttitudeIndicator from cfclient.utils.config import Config -from cflib.crazyflie.log import Log, LogVariable, LogConfig +from cflib.crazyflie.log import LogConfig + +from cfclient.utils.input import JoystickReader from cfclient.ui.tab import Tab -from cflib.crazyflie.mem import MemoryElement +PARAM_NAME_ALT_HOLD_TARGET = "posCtlAlt.targetZ" +PARAM_NAME_ESTIMATED_Z = "posEstimatorAlt.estimatedZ" + +__author__ = 'Bitcraze AB' +__all__ = ['FlightTab'] + +logger = logging.getLogger(__name__) -flight_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/flightTab.ui")[0] +flight_tab_class = uic.loadUiType(cfclient.module_path + + "/ui/tabs/flightTab.ui")[0] MAX_THRUST = 65365.0 class FlightTab(Tab, flight_tab_class): - uiSetupReadySignal = pyqtSignal() _motor_data_signal = pyqtSignal(int, object, object) @@ -72,10 +70,11 @@ class FlightTab(Tab, flight_tab_class): _input_updated_signal = pyqtSignal(float, float, float, float) _rp_trim_updated_signal = pyqtSignal(float, float) _emergency_stop_updated_signal = pyqtSignal(bool) + _assisted_control_updated_signal = pyqtSignal(bool) _log_error_signal = pyqtSignal(object, str) - #UI_DATA_UPDATE_FPS = 10 + # UI_DATA_UPDATE_FPS = 10 connectionFinishedSignal = pyqtSignal(str) disconnectedSignal = pyqtSignal(str) @@ -101,16 +100,19 @@ class FlightTab(Tab, flight_tab_class): self._input_updated_signal.connect(self.updateInputControl) self.helper.inputDeviceReader.input_updated.add_callback( - self._input_updated_signal.emit) + self._input_updated_signal.emit) self._rp_trim_updated_signal.connect(self.calUpdateFromInput) self.helper.inputDeviceReader.rp_trim_updated.add_callback( - self._rp_trim_updated_signal.emit) + self._rp_trim_updated_signal.emit) self._emergency_stop_updated_signal.connect(self.updateEmergencyStop) self.helper.inputDeviceReader.emergency_stop_updated.add_callback( - self._emergency_stop_updated_signal.emit) - - self.helper.inputDeviceReader.althold_updated.add_callback( - lambda enabled: self.helper.cf.param.set_value("flightmode.althold", enabled)) + self._emergency_stop_updated_signal.emit) + + self.helper.inputDeviceReader.assisted_control_updated.add_callback( + self._assisted_control_updated_signal.emit) + + self._assisted_control_updated_signal.connect( + self._assisted_control_updated) self._imu_data_signal.connect(self._imu_data_received) self._baro_data_signal.connect(self._baro_data_received) @@ -121,12 +123,14 @@ class FlightTab(Tab, flight_tab_class): # Connect UI signals that are in this tab self.flightModeCombo.currentIndexChanged.connect(self.flightmodeChange) + self._assist_mode_combo.currentIndexChanged.connect( + self._assist_mode_changed) self.minThrust.valueChanged.connect(self.minMaxThrustChanged) self.maxThrust.valueChanged.connect(self.minMaxThrustChanged) self.thrustLoweringSlewRateLimit.valueChanged.connect( - self.thrustLoweringSlewRateLimitChanged) + self.thrustLoweringSlewRateLimitChanged) self.slewEnableLimit.valueChanged.connect( - self.thrustLoweringSlewRateLimitChanged) + self.thrustLoweringSlewRateLimitChanged) self.targetCalRoll.valueChanged.connect(self._trim_roll_changed) self.targetCalPitch.valueChanged.connect(self._trim_pitch_changed) self.maxAngle.valueChanged.connect(self.maxAngleChanged) @@ -139,73 +143,71 @@ class FlightTab(Tab, flight_tab_class): self.clientXModeCheckbox.setChecked(Config().get("client_side_xmode")) self.crazyflieXModeCheckbox.clicked.connect( - lambda enabled: - self.helper.cf.param.set_value("flightmode.x", - str(enabled))) + lambda enabled: + self.helper.cf.param.set_value("flightmode.x", + str(enabled))) self.helper.cf.param.add_update_callback( - group="flightmode", name="xmode", - cb=( lambda name, checked: - self.crazyflieXModeCheckbox.setChecked(eval(checked)))) + group="flightmode", name="xmode", + cb=(lambda name, checked: + self.crazyflieXModeCheckbox.setChecked(eval(checked)))) self.ratePidRadioButton.clicked.connect( - lambda enabled: - self.helper.cf.param.set_value("flightmode.ratepid", - str(enabled))) + lambda enabled: + self.helper.cf.param.set_value("flightmode.ratepid", + str(enabled))) self.angularPidRadioButton.clicked.connect( - lambda enabled: - self.helper.cf.param.set_value("flightmode.ratepid", - str(not enabled))) + lambda enabled: + self.helper.cf.param.set_value("flightmode.ratepid", + str(not enabled))) self._led_ring_headlight.clicked.connect( - lambda enabled: - self.helper.cf.param.set_value("ring.headlightEnable", - str(enabled))) + lambda enabled: + self.helper.cf.param.set_value("ring.headlightEnable", + str(enabled))) self.helper.cf.param.add_update_callback( - group="flightmode", name="ratepid", - cb=(lambda name, checked: - self.ratePidRadioButton.setChecked(eval(checked)))) + group="flightmode", name="ratepid", + cb=(lambda name, checked: + self.ratePidRadioButton.setChecked(eval(checked)))) self.helper.cf.param.add_update_callback( - group="cpu", name="flash", - cb=self._set_enable_client_xmode) + group="cpu", name="flash", + cb=self._set_enable_client_xmode) self.helper.cf.param.add_update_callback( - group="ring", name="headlightEnable", - cb=(lambda name, checked: - self._led_ring_headlight.setChecked(eval(checked)))) - - self.helper.cf.param.add_update_callback( - group="flightmode", name="althold", - cb=(lambda name, enabled: - self.helper.inputDeviceReader.enable_alt_hold(eval(enabled)))) + group="ring", name="headlightEnable", + cb=(lambda name, checked: + self._led_ring_headlight.setChecked(eval(checked)))) self._ledring_nbr_effects = 0 self.helper.cf.param.add_update_callback( - group="ring", - name="neffect", - cb=(lambda name, value: self._set_neffect(eval(value)))) + group="ring", + name="effect", + cb=self._ring_effect_updated) self.helper.cf.param.add_update_callback( - group="imu_sensors", - cb=self._set_available_sensors) + group="imu_sensors", + cb=self._set_available_sensors) - self.helper.cf.param.all_updated.add_callback(self._ring_populate_dropdown) + self.helper.cf.param.all_updated.add_callback( + self._ring_populate_dropdown) self.logBaro = None self.logAltHold = None self.ai = AttitudeIndicator() self.verticalLayout_4.addWidget(self.ai) - self.splitter.setSizes([1000,1]) + self.splitter.setSizes([1000, 1]) self.targetCalPitch.setValue(Config().get("trim_pitch")) self.targetCalRoll.setValue(Config().get("trim_roll")) - self.helper.inputDeviceReader.alt1_updated.add_callback(self.alt1_updated) - self.helper.inputDeviceReader.alt2_updated.add_callback(self.alt2_updated) + self.helper.inputDeviceReader.alt1_updated.add_callback( + self.alt1_updated) + self.helper.inputDeviceReader.alt2_updated.add_callback( + self.alt2_updated) self._tf_state = 0 self._ring_effect = 0 @@ -222,8 +224,8 @@ class FlightTab(Tab, flight_tab_class): self.clientXModeCheckbox.setChecked(False) def _set_limiting_enabled(self, rp_limiting_enabled, - yaw_limiting_enabled, - thrust_limiting_enabled): + yaw_limiting_enabled, + thrust_limiting_enabled): self.maxAngle.setEnabled(rp_limiting_enabled) self.targetCalRoll.setEnabled(rp_limiting_enabled) self.targetCalPitch.setEnabled(rp_limiting_enabled) @@ -233,15 +235,12 @@ class FlightTab(Tab, flight_tab_class): self.slewEnableLimit.setEnabled(thrust_limiting_enabled) self.thrustLoweringSlewRateLimit.setEnabled(thrust_limiting_enabled) - def _set_neffect(self, n): - self._ledring_nbr_effects = n - def thrustToPercentage(self, thrust): return ((thrust / MAX_THRUST) * 100.0) def uiSetupReady(self): flightComboIndex = self.flightModeCombo.findText( - Config().get("flightmode"), Qt.MatchFixedString) + Config().get("flightmode"), Qt.MatchFixedString) if (flightComboIndex < 0): self.flightModeCombo.setCurrentIndex(0) self.flightModeCombo.currentIndexChanged.emit(0) @@ -249,9 +248,19 @@ class FlightTab(Tab, flight_tab_class): self.flightModeCombo.setCurrentIndex(flightComboIndex) self.flightModeCombo.currentIndexChanged.emit(flightComboIndex) + try: + assistmodeComboIndex = Config().get("assistedControl") + self._assist_mode_combo.setCurrentIndex(assistmodeComboIndex) + self._assist_mode_combo.currentIndexChanged.emit( + assistmodeComboIndex) + except KeyError: + self._assist_mode_combo.setCurrentIndex(0) + self._assist_mode_combo.currentIndexChanged.emit(0) + def _logging_error(self, log_conf, msg): - QMessageBox.about(self, "Log error", "Error when starting log config" - " [%s]: %s" % (log_conf.name, msg)) + QMessageBox.about(self, "Log error", + "Error when starting log config [%s]: %s" % ( + log_conf.name, msg)) def _motor_data_received(self, timestamp, data, logconf): if self.isVisible(): @@ -259,25 +268,26 @@ class FlightTab(Tab, flight_tab_class): self.actualM2.setValue(data["motor.m2"]) self.actualM3.setValue(data["motor.m3"]) self.actualM4.setValue(data["motor.m4"]) - + def _baro_data_received(self, timestamp, data, logconf): if self.isVisible(): - self.actualASL.setText(("%.2f" % data["baro.aslLong"])) - self.ai.setBaro(data["baro.aslLong"]) - + estimated_z = data[PARAM_NAME_ESTIMATED_Z] + self.actualASL.setText(("%.2f" % estimated_z)) + self.ai.setBaro(estimated_z, self.is_visible()) + def _althold_data_received(self, timestamp, data, logconf): if self.isVisible(): - target = data["altHold.target"] - if target>0: + target = data[PARAM_NAME_ALT_HOLD_TARGET] + if target > 0: if not self.targetASL.isEnabled(): - self.targetASL.setEnabled(True) + self.targetASL.setEnabled(True) self.targetASL.setText(("%.2f" % target)) - self.ai.setHover(target) + self.ai.setHover(target, self.is_visible()) elif self.targetASL.isEnabled(): self.targetASL.setEnabled(False) - self.targetASL.setText("Not set") - self.ai.setHover(0) - + self.targetASL.setText("Not set") + self.ai.setHover(0, self.is_visible()) + def _imu_data_received(self, timestamp, data, logconf): if self.isVisible(): self.actualRoll.setText(("%.2f" % data["stabilizer.roll"])) @@ -285,10 +295,10 @@ class FlightTab(Tab, flight_tab_class): self.actualYaw.setText(("%.2f" % data["stabilizer.yaw"])) self.actualThrust.setText("%.2f%%" % self.thrustToPercentage( - data["stabilizer.thrust"])) - + data["stabilizer.thrust"])) + self.ai.setRollPitch(-data["stabilizer.roll"], - data["stabilizer.pitch"]) + data["stabilizer.pitch"], self.is_visible()) def connected(self, linkURI): # IMU & THRUST @@ -325,10 +335,6 @@ class FlightTab(Tab, flight_tab_class): except AttributeError as e: logger.warning(str(e)) - if self.helper.cf.mem.ow_search(vid=0xBC, pid=0x01): - self._led_ring_effect.setEnabled(True) - self._led_ring_headlight.setEnabled(True) - def _set_available_sensors(self, name, available): logger.info("[%s]: %s", name, available) available = eval(available) @@ -342,21 +348,22 @@ class FlightTab(Tab, flight_tab_class): if (not self.logBaro and not self.logAltHold): # The sensor is available, set up the logging self.logBaro = LogConfig("Baro", 200) - self.logBaro.add_variable("baro.aslLong", "float") + self.logBaro.add_variable(PARAM_NAME_ESTIMATED_Z, "float") try: self.helper.cf.log.add_config(self.logBaro) self.logBaro.data_received_cb.add_callback( - self._baro_data_signal.emit) + self._baro_data_signal.emit) self.logBaro.error_cb.add_callback( - self._log_error_signal.emit) + self._log_error_signal.emit) self.logBaro.start() except KeyError as e: logger.warning(str(e)) except AttributeError as e: logger.warning(str(e)) self.logAltHold = LogConfig("AltHold", 200) - self.logAltHold.add_variable("altHold.target", "float") + self.logAltHold.add_variable(PARAM_NAME_ALT_HOLD_TARGET, + "float") try: self.helper.cf.log.add_config(self.logAltHold) @@ -367,7 +374,7 @@ class FlightTab(Tab, flight_tab_class): self.logAltHold.start() except KeyError as e: logger.warning(str(e)) - except AttributeError: + except AttributeError as e: logger.warning(str(e)) def disconnected(self, linkURI): @@ -388,33 +395,42 @@ class FlightTab(Tab, flight_tab_class): self.logBaro = None self.logAltHold = None self._led_ring_effect.setEnabled(False) + self._led_ring_effect.clear() + try: + self._led_ring_effect.currentIndexChanged.disconnect( + self._ring_effect_changed) + except TypeError: + # Signal was not connected + pass + self._led_ring_effect.setCurrentIndex(-1) self._led_ring_headlight.setEnabled(False) - def minMaxThrustChanged(self): self.helper.inputDeviceReader.min_thrust = self.minThrust.value() self.helper.inputDeviceReader.max_thrust = self.maxThrust.value() - if (self.isInCrazyFlightmode == True): + if (self.isInCrazyFlightmode is True): Config().set("min_thrust", self.minThrust.value()) Config().set("max_thrust", self.maxThrust.value()) def thrustLoweringSlewRateLimitChanged(self): - self.helper.inputDeviceReader.thrust_slew_rate = self.thrustLoweringSlewRateLimit.value() - self.helper.inputDeviceReader.thrust_slew_limit = self.slewEnableLimit.value() - if (self.isInCrazyFlightmode == True): + self.helper.inputDeviceReader.thrust_slew_rate = ( + self.thrustLoweringSlewRateLimit.value()) + self.helper.inputDeviceReader.thrust_slew_limit = ( + self.slewEnableLimit.value()) + if (self.isInCrazyFlightmode is True): Config().set("slew_limit", self.slewEnableLimit.value()) Config().set("slew_rate", self.thrustLoweringSlewRateLimit.value()) def maxYawRateChanged(self): logger.debug("MaxYawrate changed to %d", self.maxYawRate.value()) self.helper.inputDeviceReader.max_yaw_rate = self.maxYawRate.value() - if (self.isInCrazyFlightmode == True): + if (self.isInCrazyFlightmode is True): Config().set("max_yaw", self.maxYawRate.value()) def maxAngleChanged(self): logger.debug("MaxAngle changed to %d", self.maxAngle.value()) self.helper.inputDeviceReader.max_rp_angle = self.maxAngle.value() - if (self.isInCrazyFlightmode == True): + if (self.isInCrazyFlightmode is True): Config().set("max_rp", self.maxAngle.value()) def _trim_pitch_changed(self, value): @@ -456,7 +472,7 @@ class FlightTab(Tab, flight_tab_class): if emergencyStop: self.setMotorLabelsEnabled(False) self.emergency_stop_label.setText( - self.emergencyStopStringWithText("Kill switch active")) + self.emergencyStopStringWithText("Kill switch active")) else: self.setMotorLabelsEnabled(True) self.emergency_stop_label.setText("") @@ -464,7 +480,7 @@ class FlightTab(Tab, flight_tab_class): def flightmodeChange(self, item): Config().set("flightmode", str(self.flightModeCombo.itemText(item))) logger.debug("Changed flightmode to %s", - self.flightModeCombo.itemText(item)) + self.flightModeCombo.itemText(item)) self.isInCrazyFlightmode = False if (item == 0): # Normal self.maxAngle.setValue(Config().get("normal_max_rp")) @@ -472,7 +488,7 @@ class FlightTab(Tab, flight_tab_class): self.minThrust.setValue(Config().get("normal_min_thrust")) self.slewEnableLimit.setValue(Config().get("normal_slew_limit")) self.thrustLoweringSlewRateLimit.setValue( - Config().get("normal_slew_rate")) + Config().get("normal_slew_rate")) self.maxYawRate.setValue(Config().get("normal_max_yaw")) if (item == 1): # Advanced self.maxAngle.setValue(Config().get("max_rp")) @@ -480,7 +496,7 @@ class FlightTab(Tab, flight_tab_class): self.minThrust.setValue(Config().get("min_thrust")) self.slewEnableLimit.setValue(Config().get("slew_limit")) self.thrustLoweringSlewRateLimit.setValue( - Config().get("slew_rate")) + Config().get("slew_rate")) self.maxYawRate.setValue(Config().get("max_yaw")) self.isInCrazyFlightmode = True @@ -495,6 +511,26 @@ class FlightTab(Tab, flight_tab_class): self.slewEnableLimit.setEnabled(newState) self.maxYawRate.setEnabled(newState) + def _assist_mode_changed(self, item): + mode = None + + if (item == 0): # Altitude hold + mode = JoystickReader.ASSISTED_CONTROL_ALTHOLD + if (item == 1): # Position hold + mode = JoystickReader.ASSISTED_CONTROL_POSHOLD + + self.helper.inputDeviceReader.set_assisted_control(mode) + Config().set("assistedControl", mode) + + def _assisted_control_updated(self, enabled): + if self.helper.inputDeviceReader.get_assisted_control() == \ + JoystickReader.ASSISTED_CONTROL_POSHOLD: + self.targetThrust.setEnabled(not enabled) + self.targetRoll.setEnabled(not enabled) + self.targetPitch.setEnabled(not enabled) + else: + self.helper.cf.param.set_value("flightmode.althold", str(enabled)) + @pyqtSlot(bool) def changeXmode(self, checked): self.helper.cf.commander.set_client_xmode(checked) @@ -503,10 +539,9 @@ class FlightTab(Tab, flight_tab_class): def alt1_updated(self, state): if state: - self._ring_effect += 1 - if self._ring_effect > self._ledring_nbr_effects: - self._ring_effect = 0 - self.helper.cf.param.set_value("ring.effect", str(self._ring_effect)) + new_index = (self._ring_effect+1) % (self._ledring_nbr_effects+1) + self.helper.cf.param.set_value("ring.effect", + str(new_index)) def alt2_updated(self, state): self.helper.cf.param.set_value("ring.headlightEnable", str(state)) @@ -518,6 +553,10 @@ class FlightTab(Tab, flight_tab_class): except KeyError: return + # Used only in alt1_updated function + self._ring_effect = current + self._ledring_nbr_effects = nbr + hardcoded_names = {0: "Off", 1: "White spinner", 2: "Color spinner", @@ -530,27 +569,33 @@ class FlightTab(Tab, flight_tab_class): 9: "Battery status", 10: "Boat lights", 11: "Alert", - 12: "Gravity"} + 12: "Gravity", + 13: "LED tab"} - for i in range(nbr+1): + for i in range(nbr + 1): name = "{}: ".format(i) if i in hardcoded_names: name += hardcoded_names[i] else: name += "N/A" - self._led_ring_effect.addItem(name, QVariant(i)) + self._led_ring_effect.addItem(name, i) + + self._led_ring_effect.currentIndexChanged.connect( + self._ring_effect_changed) self._led_ring_effect.setCurrentIndex(current) - self._led_ring_effect.currentIndexChanged.connect(self._ring_effect_changed) - self.helper.cf.param.add_update_callback(group="ring", - name="effect", - cb=self._ring_effect_updated) + if self.helper.cf.mem.ow_search(vid=0xBC, pid=0x01): + self._led_ring_effect.setEnabled(True) + self._led_ring_headlight.setEnabled(True) def _ring_effect_changed(self, index): - i = self._led_ring_effect.itemData(index).toInt()[0] - logger.info("Changed effect to {}".format(i)) - if i != self.helper.cf.param.values["ring"]["effect"]: - self.helper.cf.param.set_value("ring.effect", str(i)) + self._ring_effect = index + if index > -1: + i = self._led_ring_effect.itemData(index) + logger.info("Changed effect to {}".format(i)) + if i != int(self.helper.cf.param.values["ring"]["effect"]): + self.helper.cf.param.set_value("ring.effect", str(i)) def _ring_effect_updated(self, name, value): - self._led_ring_effect.setCurrentIndex(int(value)) + if self.helper.cf.param.is_updated: + self._led_ring_effect.setCurrentIndex(int(value)) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/FlightTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/FlightTab.pyc deleted file mode 100755 index 286da7cc9555d72815377df2eb0c6ba072978286..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22594 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/GpsTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/GpsTab.py old mode 100755 new mode 100644 index 613350a1..77a013ee --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/GpsTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/GpsTab.py @@ -20,54 +20,35 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, +# USA. """ This tab plots different logging data defined by configurations that has been pre-configured. """ -import math - -__author__ = 'Bitcraze AB' -__all__ = ['GpsTab'] - -import glob -import json import logging -import os -import sys - -logger = logging.getLogger(__name__) - -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import * -from PyQt4.QtGui import * - -from pprint import pprint -import datetime - -#from cfclient.ui.widgets.plotwidget import PlotWidget - -from cflib.crazyflie.log import Log, LogVariable, LogConfig +import cfclient +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtWidgets import QMessageBox from cfclient.ui.tab import Tab +from cflib.crazyflie.log import LogConfig +from PyQt5 import QtCore +from PyQt5 import QtGui +from PyQt5 import QtNetwork +from PyQt5 import QtWebKit +from PyQt5 import uic -from PyQt4.QtCore import * -from PyQt4.QtGui import * +__author__ = 'Bitcraze AB' +__all__ = ['GpsTab'] -try: - from PyKDE4.marble import * - should_enable_tab = True -except: - should_enable_tab = False +logger = logging.getLogger(__name__) -import sys +gps_tab_class = uic.loadUiType(cfclient.module_path + + "/ui/tabs/gpsTab.ui")[0] -gps_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/gpsTab.ui")[0] class GpsTab(Tab, gps_tab_class): """Tab for plotting logging data""" @@ -79,7 +60,6 @@ class GpsTab(Tab, gps_tab_class): _connected_signal = pyqtSignal(str) _console_signal = pyqtSignal(str) - def __init__(self, tabWidget, helper, *args): super(GpsTab, self).__init__(*args) self.setupUi(self) @@ -90,206 +70,105 @@ class GpsTab(Tab, gps_tab_class): self.tabWidget = tabWidget self.helper = helper self._cf = helper.cf - self._got_home_point = False - self._line = "" - - if not should_enable_tab: - self.enabled = False - - if self.enabled: - # create the marble widget - #self._marble = Marble.MarbleWidget() - self._marble = FancyMarbleWidget() - # Load the OpenStreetMap map - self._marble.setMapThemeId("earth/openstreetmap/openstreetmap.dgml") + view = self.view = QtWebKit.QWebView() - # Enable the cloud cover and enable the country borders - self._marble.setShowClouds(True) - self._marble.setShowBorders(True) + cache = QtNetwork.QNetworkDiskCache() + cache.setCacheDirectory(cfclient.config_path + "/cache") + view.page().networkAccessManager().setCache(cache) + view.page().networkAccessManager() - # Hide the FloatItems: Compass and StatusBar - self._marble.setShowOverviewMap(False) - self._marble.setShowScaleBar(False) - self._marble.setShowCompass(False) + view.page().mainFrame().addToJavaScriptWindowObject("MainWindow", self) + view.page().setLinkDelegationPolicy(QtWebKit.QWebPage.DelegateAllLinks) + view.load(QtCore.QUrl(cfclient.module_path + "/resources/map.html")) + view.loadFinished.connect(self.onLoadFinished) + view.linkClicked.connect(QtGui.QDesktopServices.openUrl) - self._marble.setShowGrid(False) - self._marble.setProjection(Marble.Mercator) + self.map_layout.addWidget(view) - # Change the map to center on Australia + self._reset_max_btn.clicked.connect(self._reset_max) - self._marble.zoomView(10) + # Connect the signals + self._log_data_signal.connect(self._log_data_received) + self._log_error_signal.connect(self._logging_error) + self._connected_signal.connect(self._connected) + self._disconnected_signal.connect(self._disconnected) - # create the slider - self.zoomSlider = QSlider(Qt.Horizontal) + # Connect the callbacks from the Crazyflie API + self.helper.cf.disconnected.add_callback( + self._disconnected_signal.emit) + self.helper.cf.connected.add_callback( + self._connected_signal.emit) - self._reset_max_btn.clicked.connect(self._reset_max) - - # add all the components - #self.gpslayout.addWidget(self._marble) - self.map_layout.addWidget(self._marble) - # Connect the signals - self._log_data_signal.connect(self._log_data_received) - self._log_error_signal.connect(self._logging_error) - self._connected_signal.connect(self._connected) - self._disconnected_signal.connect(self._disconnected) + self._max_speed = 0.0 + self._lat = 0 + self._long = 0 - # Connect the callbacks from the Crazyflie API - self.helper.cf.disconnected.add_callback( - self._disconnected_signal.emit) - self.helper.cf.connected.add_callback( - self._connected_signal.emit) + def onLoadFinished(self): + with open(cfclient.module_path + "/resources/map.js", 'r') as f: + frame = self.view.page().mainFrame() + frame.evaluateJavaScript(f.read()) - else: - logger.warning("GPS tab not enabled since no Python" - "bindings for Marble was found") + @QtCore.pyqtSlot(float, float) + def onMapMove(self, lat, lng): + return - self._max_speed = 0.0 + def panMap(self, lng, lat): + frame = self.view.page().mainFrame() + frame.evaluateJavaScript('map.panTo(L.latLng({}, {}));'.format(lat, + lng)) - self._fix_types = { - 0: "No fix", - 1: "Dead reckoning only", - 2: "2D-fix", - 3: "3D-fix", - 4: "GNSS+dead", - 5: "Time only fix" - } + def _place_cf(self, lng, lat, acc): + frame = self.view.page().mainFrame() + frame.evaluateJavaScript('cf.setLatLng([{}, {}]);'.format(lat, lng)) def _connected(self, link_uri): - lg = LogConfig("GPS", 100) + lg = LogConfig("GPS", 1000) lg.add_variable("gps.lat") lg.add_variable("gps.lon") - lg.add_variable("gps.hMSL") - lg.add_variable("gps.heading") - lg.add_variable("gps.gSpeed") lg.add_variable("gps.hAcc") - lg.add_variable("gps.fixType") - try: - self._cf.log.add_config(lg) + lg.add_variable("gps.hMSL") + lg.add_variable("gps.nsat") + self._cf.log.add_config(lg) + if lg.valid: lg.data_received_cb.add_callback(self._log_data_signal.emit) lg.error_cb.add_callback(self._log_error_signal.emit) lg.start() - except KeyError as e: - logger.warning(str(e)) - except AttributeError as e: - logger.warning(str(e)) + else: + logger.warning("Could not setup logging block for GPS!") self._max_speed = 0.0 def _disconnected(self, link_uri): """Callback for when the Crazyflie has been disconnected""" - self._got_home_point = False return def _logging_error(self, log_conf, msg): """Callback from the log layer when an error occurs""" QMessageBox.about(self, "Plot error", "Error when starting log config" - " [%s]: %s" % (log_conf.name, msg)) + " [%s]: %s" % (log_conf.name, msg)) def _reset_max(self): """Callback from reset button""" self._max_speed = 0.0 self._speed_max.setText(str(self._max_speed)) - self._marble.clear_data() - self._long.setText("") self._lat.setText("") self._height.setText("") - self._speed.setText("") self._heading.setText("") self._accuracy.setText("") - self._fix_type.setText("") - def _log_data_received(self, timestamp, data, logconf): """Callback when the log layer receives new data""" - - long = float(data["gps.lon"])/10000000.0 - lat = float(data["gps.lat"])/10000000.0 - alt = float(data["gps.hMSL"])/1000.0 - speed = float(data["gps.gSpeed"])/1000.0 - accuracy = float(data["gps.hAcc"])/1000.0 - fix_type = float(data["gps.fixType"]) - heading = float(data["gps.heading"]) - - self._long.setText(str(long)) - self._lat.setText(str(lat)) - self._height.setText(str(alt)) - - self._speed.setText(str(speed)) - self._heading.setText(str(heading)) - self._accuracy.setText(str(accuracy)) - if speed > self._max_speed: - self._max_speed = speed - self._speed_max.setText(str(self._max_speed)) - - self._fix_type.setText(self._fix_types[fix_type]) - - - point = Marble.GeoDataCoordinates(long, lat, alt, - Marble.GeoDataCoordinates.Degree) - if not self._got_home_point: - self._got_home_point = True - - self._marble.centerOn(point, True) - self._marble.zoomView(4000, Marble.Jump) - - self._marble.add_data(long, lat, alt, accuracy, - True if fix_type == 3 else False) - -# If Marble is not installed then do not create MarbleWidget subclass -if should_enable_tab: - class FancyMarbleWidget(Marble.MarbleWidget): - def __init__(self): - Marble.MarbleWidget.__init__(self) - self._points = [] - self._lat = None - self._long = None - self._height = None - self._accu = None - - def clear_data(self): - self._points = [] - self._lat = None - self._long = None - self._height = None - self._accu = None - - def add_data(self, long, lat, height, accu, locked): - self._points.append([long, lat, height, accu, locked]) + long = float(data["gps.lon"]) / 10000000.0 + lat = float(data["gps.lat"]) / 10000000.0 + + if self._lat != lat or self._long != long: + self._long.setText("{:.6f}".format(long)) + self._lat.setText("{:.6f}".format(lat)) + self._nbr_locked_sats.setText(str(data["gps.nsat"])) + self._height.setText("{:.2f}".format(float(data["gps.hMSL"]))) + self._place_cf(long, lat, 1) self._lat = lat self._long = long - self._height = height - self._accu = accu - self.update() - - def customPaint(self, painter): - if self._lat: - current = Marble.GeoDataCoordinates(self._long, - self._lat, - self._height, - Marble.GeoDataCoordinates.Degree) - - #Paint data points - for p in self._points: - pos = Marble.GeoDataCoordinates(p[0], - p[1], - p[2], - Marble.GeoDataCoordinates.Degree) - if p[4]: - painter.setPen(Qt.green) - else: - painter.setPen(Qt.red) - painter.drawEllipse(pos, 1, 1) - - # Paint accuracy - painter.setPen(Qt.blue) - painter.setBrush(QtGui.QBrush(QtGui.QColor(0, 0, 255, 64))) - pixel_per_meter = self.radiusFromDistance(self.distance())/(6371.0*1000) - painter.drawEllipse(current, self._accu*pixel_per_meter, self._accu*pixel_per_meter, False) - - #Paint Crazyflie - painter.setPen(Qt.black) - painter.setBrush(Qt.NoBrush) - painter.drawText(current, "Crazyflie") diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/GpsTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/GpsTab.pyc deleted file mode 100755 index b3788bae74fe8f0f52ba0fc1fd4c7819e244ff81..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8654 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 WsjOAlt`g&*t~7vOscipr-uYhv3_p_q diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LEDTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LEDTab.py old mode 100755 new mode 100644 index b51292e6..11893e87 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LEDTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LEDTab.py @@ -30,24 +30,24 @@ Basic tab to be able to set (and test) colors in the LED-ring. """ -__author__ = 'Bitcraze AB' -__all__ = ['LEDTab'] - import logging -import sys - -logger = logging.getLogger(__name__) -from PyQt4 import QtGui, uic -from PyQt4.QtCore import pyqtSignal -from PyQt4.QtGui import QColorDialog +from PyQt5 import QtGui, uic +from PyQt5.QtCore import pyqtSignal +import cfclient from cfclient.ui.tab import Tab from cflib.crazyflie.mem import MemoryElement -led_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/ledTab.ui")[0] +__author__ = 'Bitcraze AB' +__all__ = ['LEDTab'] + +logger = logging.getLogger(__name__) + +led_tab_class = uic.loadUiType(cfclient.module_path + + "/ui/tabs/ledTab.ui")[0] + class LEDTab(Tab, led_tab_class): """Tab for plotting logging data""" @@ -90,7 +90,7 @@ class LEDTab(Tab, led_tab_class): self._u11, self._u12] - self._intensity = 1 + self._intensity = self._intensity_slider.value() self._u1.clicked.connect(lambda: self._select(0)) self._u2.clicked.connect(lambda: self._select(1)) @@ -114,8 +114,14 @@ class LEDTab(Tab, led_tab_class): self._intensity_slider.setValue) def _select(self, nbr): - col = QColorDialog() - col = QtGui.QColorDialog.getColor() + col = QtGui.QColor() # default to invalid + + if self._mem: + led = self._mem.leds[nbr] + col = QtGui.QColor.fromRgb(led.r, led.g, led.b) + + col = QtGui.QColorDialog.getColor(col) + if col.isValid() and self._mem: logger.info(col.red()) self._mem.leds[nbr].set(r=col.red(), g=col.green(), b=col.blue()) @@ -141,9 +147,11 @@ class LEDTab(Tab, led_tab_class): def _connected(self, link_uri): """Callback when the Crazyflie has been connected""" - self._mem = self._helper.cf.mem.get_mems( - MemoryElement.TYPE_DRIVER_LED)[0] - logger.info(self._mem) + mems = self._helper.cf.mem.get_mems(MemoryElement.TYPE_DRIVER_LED) + if len(mems) > 0: + self._mem = mems[0] + logger.info(self._mem) + if self._mem: for btn in self._btns: btn.setEnabled(True) @@ -158,4 +166,4 @@ class LEDTab(Tab, led_tab_class): btn.setStyleSheet("background-color: none") self._intensity_slider.setEnabled(False) self._intensity_spin.setEnabled(False) - self._intensity_slider.setValue(100) \ No newline at end of file + self._intensity_slider.setValue(100) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LEDTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LEDTab.pyc deleted file mode 100755 index 6687928d80f5b2fa0155ed7409e097da94404bfe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7144 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockDebugTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockDebugTab.py old mode 100755 new mode 100644 index 7437823c..4a42a543 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockDebugTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockDebugTab.py @@ -21,28 +21,27 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Shows all the parameters available in the Crazyflie and also gives the ability to edit them. """ -__author__ = 'Bitcraze AB' -__all__ = ['LogBlockTab'] +from PyQt5 import QtCore, QtWidgets, uic +from PyQt5.QtCore import Qt, pyqtSignal -import time -import sys +import cfclient +from cfclient.ui.tab import Tab -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL +__author__ = 'Bitcraze AB' +__all__ = ['LogBlockDebugTab'] -from cfclient.ui.tab import Tab +logblock_tab_class = uic.loadUiType(cfclient.module_path + + "/ui/tabs/logBlockDebugTab.ui")[0] -logblock_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/logBlockDebugTab.ui")[0] class LogBlockDebugTab(Tab, logblock_tab_class): """ @@ -64,10 +63,13 @@ class LogBlockDebugTab(Tab, logblock_tab_class): self._helper.cf.log.block_added_cb.add_callback(self._block_added) self._disconnected_signal.connect(self._disconnected) - self._helper.cf.disconnected.add_callback(self._disconnected_signal.emit) + self._helper.cf.disconnected.add_callback( + self._disconnected_signal.emit) self._blocks_updated_signal.connect(self._update_tree) - self._block_tree.setHeaderLabels(['Id', 'Name', 'Period (ms)', 'Added', 'Started', 'Error', 'Contents']) + self._block_tree.setHeaderLabels( + ['Id', 'Name', 'Period (ms)', 'Added', 'Started', 'Error', + 'Contents']) self._block_tree.sortItems(0, QtCore.Qt.AscendingOrder) def _block_added(self, block): @@ -79,7 +81,7 @@ class LogBlockDebugTab(Tab, logblock_tab_class): """Update the block tree""" self._block_tree.clear() for block in self._helper.cf.log.log_blocks: - item = QtGui.QTreeWidgetItem() + item = QtWidgets.QTreeWidgetItem() item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) item.setData(0, Qt.DisplayRole, block.id) @@ -89,15 +91,15 @@ class LogBlockDebugTab(Tab, logblock_tab_class): item.setData(4, Qt.EditRole, block.started) item.setData(5, Qt.EditRole, block.err_no) for var in block.variables: - subItem = QtGui.QTreeWidgetItem() + subItem = QtWidgets.QTreeWidgetItem() subItem.setFlags(Qt.ItemIsEnabled | - Qt.ItemIsSelectable) + Qt.ItemIsSelectable) subItem.setData(6, Qt.EditRole, var.name) - item.addChild(subItem) + item.addChild(subItem) self._block_tree.addTopLevelItem(item) self._block_tree.expandItem(item) def _disconnected(self, link_uri): """Callback when the Crazyflie is disconnected""" - self._block_tree.clear() \ No newline at end of file + self._block_tree.clear() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockDebugTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockDebugTab.pyc deleted file mode 100755 index 072ba320bb399515f2283559891157209c168abd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3746 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 NH=K^!Mk;N%{{XvRS2zFw diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockTab.py old mode 100755 new mode 100644 index 98eb6ce9..b5a21c31 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockTab.py @@ -31,34 +31,33 @@ This tab shows all log blocks that are registered and can be used to start the logging and also to write the logging data to file. """ -__author__ = 'Bitcraze AB' -__all__ = ['LogBlockTab'] - -import sys - -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL +from PyQt5 import uic +from PyQt5.QtCore import Qt, pyqtSignal +import cfclient from cfclient.ui.tab import Tab -logblock_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/logBlockTab.ui")[0] - import logging -logger = logging.getLogger(__name__) -from PyQt4.QtGui import QApplication, QStyledItemDelegate, QAbstractItemView -from PyQt4.QtGui import QStyleOptionButton, QStyle -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import pyqtSlot, pyqtSignal, QThread -from PyQt4.QtCore import QAbstractItemModel, QModelIndex, QString, QVariant +from PyQt5.QtWidgets import QApplication, QStyledItemDelegate +from PyQt5.QtWidgets import QAbstractItemView, QStyleOptionButton, QStyle +from PyQt5.QtCore import QAbstractItemModel, QModelIndex from cfclient.utils.logdatawriter import LogWriter +__author__ = 'Bitcraze AB' +__all__ = ['LogBlockTab'] + +logblock_tab_class = uic.loadUiType( + cfclient.module_path + "/ui/tabs/logBlockTab.ui")[0] + +logger = logging.getLogger(__name__) + class LogBlockChildItem(object): """Class that acts as a child in the tree and represents one variable in a log block""" + def __init__(self, parent, name): """Initialize the node""" self.parent = parent @@ -100,7 +99,9 @@ class LogBlockItem(object): self._doing_transaction = False def _log_error(self, logconfig, msg): - """Callback when there's an error starting the block in the Crazyflie""" + """ + Callback when there's an error starting the block in the Crazyflie + """ # Do nothing here, a pop-up will notify the user that the # starting failed self._doing_transaction = False @@ -109,9 +110,9 @@ class LogBlockItem(object): """Callback when a block has been started in the Crazyflie""" logger.debug("%s started: %s", self.name, started) if started: - self._block_started = True + self._block_started = True else: - self._block_started = False + self._block_started = False self._doing_transaction = False self._model.refresh() @@ -163,6 +164,7 @@ class LogBlockItem(object): class LogBlockModel(QAbstractItemModel): + def __init__(self, view, parent=None): super(LogBlockModel, self).__init__(parent) self._nodes = [] @@ -180,7 +182,9 @@ class LogBlockModel(QAbstractItemModel): self.layoutChanged.emit() def clicked(self, index): - """Callback when a cell has been clicked (mouse down/up on same cell)""" + """ + Callback when a cell has been clicked (mouse down/up on same cell) + """ node = index.internalPointer() if not node.parent and index.column() == 3: if node.logging_started(): @@ -217,7 +221,7 @@ class LogBlockModel(QAbstractItemModel): def headerData(self, section, orientation, role): """Re-implemented method to get the headers""" if role == Qt.DisplayRole: - return QString(self._column_headers[section]) + return self._column_headers[section] def rowCount(self, parent): """Re-implemented method to get the number of rows for a given index""" @@ -261,7 +265,7 @@ class LogBlockModel(QAbstractItemModel): (index.column() == 4 or index.column() == 3): return Qt.AlignHCenter | Qt.AlignVCenter - return QVariant() + return None def reset(self): """Reset the model""" @@ -282,7 +286,7 @@ class CheckboxDelegate(QStyledItemDelegate): col = index.column() if not item.parent and (col == 3 or col == 4): s = QStyleOptionButton() - checkbox_rect = QApplication.style().\ + checkbox_rect = QApplication.style(). \ subElementRect(QStyle.SE_CheckBoxIndicator, option) s.rect = option.rect center_offset = s.rect.width() / 2 - checkbox_rect.width() / 2 @@ -342,4 +346,6 @@ class LogBlockTab(Tab, logblock_tab_class): def _disconnected(self, link_uri): """Callback when the Crazyflie is disconnected""" - self._model.reset() \ No newline at end of file + self._model.beginResetModel() + self._model.reset() + self._model.endResetModel() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogBlockTab.pyc deleted file mode 100755 index c71e399d654417ad5df9fb3c9cbc87ec96f9b9b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14996 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogTab.py old mode 100755 new mode 100644 index 629b452f..7db1f804 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogTab.py @@ -20,30 +20,26 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Shows the Log TOC of available variables in the Crazyflie. """ +import cfclient +from cfclient.ui.tab import Tab +from PyQt5 import QtWidgets +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import pyqtSlot +from PyQt5.QtCore import Qt + __author__ = 'Bitcraze AB' __all__ = ['LogTab'] -import time -import sys - -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL - -from cflib.crazyflie import Crazyflie - -from cfclient.ui.tab import Tab - -param_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/logTab.ui")[0] +param_tab_class = uic.loadUiType(cfclient.module_path + + "/ui/tabs/logTab.ui")[0] class LogTab(Tab, param_tab_class): @@ -82,11 +78,11 @@ class LogTab(Tab, param_tab_class): toc = self.cf.log.toc - for group in toc.toc.keys(): - groupItem = QtGui.QTreeWidgetItem() + for group in list(toc.toc.keys()): + groupItem = QtWidgets.QTreeWidgetItem() groupItem.setData(0, Qt.DisplayRole, group) - for param in toc.toc[group].keys(): - item = QtGui.QTreeWidgetItem() + for param in list(toc.toc[group].keys()): + item = QtWidgets.QTreeWidgetItem() item.setData(0, Qt.DisplayRole, param) item.setData(1, Qt.DisplayRole, toc.toc[group][param].ident) item.setData(2, Qt.DisplayRole, toc.toc[group][param].pytype) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/LogTab.pyc deleted file mode 100755 index e9ffc7219c6f8354eb9c3150ad53016588c9790b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2830 zcmcguUvC>l5TCpA|2T=0HYtG$EP;?8Xe=c9Rw3F%YNJLeIVV({gihzXjlJ%j&%Irj z8YNHVkuSlQ;7h=_;RC>L<{T#oUW@G=@6OK7&Y$1Ro%iQ@>skE#yO@?A5C7j_m_I-g zq5#yPz@fyY5hgAr9wik@Jqj=>=M@SnGOtovrL0Cljj}ogb;=qPG{|AO8l_FjS`@S> zTcco&vNi>6%GN1Zr)-0QjZ&^o=_X|z3OePwLFpD{+Z1e*qZ%~1L#jfPyOcC(FKN-e zcd!l9V24dq+oX2r0#>fk&qVKtz7KZU-a)U;UOfV74aWJ8rfbKldz_EDXD<%A`9(K+ z6X`S>rmFiUDl|__S5HOipoo52T%=m<x6B$8Jkd4=OLZSVu{Err<t!TNzwkNfaR7yT zY7g>4*(%nj_UT+(-kIyT#~kYl+cxkwTfDY|G`F^Oz0jj+l-fFroQ(?=C8BU}^z`KM zanAwUHbGWql`K}zX5f#^M<D(9B8JgZ+n?*cjfSS5ilO^3f`$0QW<0?#0}zFDJERar zj}TSl^k!aVFd(AHtg164IP9*(7?KTUmZy+v4m_Am@&~;N^u}x&PuTOP80L2ni=RW6 zkacO|(xpeg5II;+JmES>zwC#=RynECB?O7W8eNv0I&&rsVG5lzY0_fLN@ylk8dcaD zQ4I8~(WK4NlXaSGtTwRN6z<xJ1=-HE?AC2rEK1pq$R-4AF$zu$Cv1r*%kG{;nUX{w z9ZCYvr?V)2C3zj#yog4sx6Ogzu$cKw6+R{;m<U5X)iw-8*eE-nooksRkD``=ld0)k z7JU6!rO+V2fXqvsjFgqj;|n>+xi6Hmn~;UVXF!!Ij-#PUjU0;e=~Ts5C6)^%N|G>+ z(salM^O4o|paduTr!s9t_i|HCCfclIExUJ{Q63ghNQ8_^FZ>+{`FBBt6%`}X!-9mE z7nt?Od8YcqW!3d(MLvP0rq4wvb@`ygxp^>K*l|AXr+WBr@RwD(KU?@6=zNG_J^&$S z*I9R)PE$tPyYKEfcf37E96KG@LQh9AmkAH9y#oxh1;Qx852b(&fdOxy^jOfp2O^1$ zQxz2@ugg46T&kz9rU1u#_VZ(0^&G>nMdXSXj8Puq#X}hU4=;Fudh%#ep(~f(ZaZ9F zXtz~%^6&@8x$?NXP3pY9s?a6&8eE>h5b6#^{LUli?Qc?+*!F1e`s}ZCRlRi<B@8{c z&*Bc8U2@%PjdDNhxvWAL>hnehrj)n-Q>J}ert;r1>!l2=-(WkqLA)N*%VjW7-#1MI zA?aMNUw=U_CDUB8C(>#)CtY)dwFlB;WJvb?PkFWrBAp-gC;v8&1?R8S!uWhl%IlPC zvn<*pt1<x}s`N0jk<X=O`MGnb%`A-;ex8<(6`i2DOJ@P@7qgNX%ZyQm8a^27G?5Fi zILl|p>Wxa}0)E!0x3g%P@Uq8{@Vg*ouK+&J{UiT#X0WTHBA?HsO~_0%Fn<;mQ6}za z)&kCZEZaS3=XPN3^F8jmyXo#aZIthaLO*l(yXAJA9y_;eqg-Zaqs$4zEKlYsmOeL3 z$%e6o&(BK#6DHgkeD=%d(((Di8=qwMUiuNPp)WBETUmoMZMV6*Q|U<$;mm|#lE*7A zqB)vev3xd!A-Xi?0uqhq4TI1ujHK<`#i{+uXMhUQeBP5LEgSpg8;ano^qRxs3ltbX zW#7kp&v1X$X?=e2SZ<U}7jF~$c;NUFb0%pXCFlB#@yJHaB0H7?f|U@WVVp+B$g}Q$ gh_2w^QJML#Ijx3EvgX#%@j24>ou1p_ue0I(4VbN2DF6Tf diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ParamTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ParamTab.py old mode 100755 new mode 100644 index 7ac7fada..a3c97891 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ParamTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ParamTab.py @@ -21,35 +21,37 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Shows all the parameters available in the Crazyflie and also gives the ability to edit them. """ -__author__ = 'Bitcraze AB' -__all__ = ['ParamTab'] +import logging -import sys -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL -from PyQt4.QtCore import QAbstractItemModel, QModelIndex, QString, QVariant -from PyQt4.QtGui import QApplication, QStyledItemDelegate, QAbstractItemView, QBrush, QColor -from PyQt4.QtGui import QSortFilterProxyModel +from PyQt5 import uic +from PyQt5.QtCore import Qt, pyqtSignal +from PyQt5.QtCore import QAbstractItemModel, QModelIndex +from PyQt5.QtGui import QBrush, QColor +import cfclient from cfclient.ui.tab import Tab -param_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/paramTab.ui")[0] +__author__ = 'Bitcraze AB' +__all__ = ['ParamTab'] + +param_tab_class = uic.loadUiType( + cfclient.module_path + "/ui/tabs/paramTab.ui")[0] -import logging logger = logging.getLogger(__name__) + class ParamChildItem(object): """Represents a leaf-node in the tree-view (one parameter)""" + def __init__(self, parent, name, crazyflie): """Initialize the node""" self.parent = parent @@ -81,6 +83,7 @@ class ParamChildItem(object): class ParamGroupItem(object): """Represents a parameter group in the tree-view""" + def __init__(self, name, model): """Initialize the parent node""" super(ParamGroupItem, self).__init__() @@ -93,8 +96,10 @@ class ParamGroupItem(object): """Return the number of children this node has""" return len(self.children) + class ParamBlockModel(QAbstractItemModel): """Model for handling the parameters in the tree-view""" + def __init__(self, parent): """Create the empty model""" super(ParamBlockModel, self).__init__(parent) @@ -142,7 +147,7 @@ class ParamBlockModel(QAbstractItemModel): def headerData(self, section, orientation, role): """Re-implemented method to get the headers""" if role == Qt.DisplayRole: - return QString(self._column_headers[section]) + return self._column_headers[section] def rowCount(self, parent): """Re-implemented method to get the number of rows for a given index""" @@ -184,37 +189,36 @@ class ParamBlockModel(QAbstractItemModel): return node.value elif role == Qt.EditRole and index.column() == 3: return node.value - elif (role == Qt.BackgroundRole and index.column() == 3 - and node.is_updating): + elif (role == Qt.BackgroundRole and index.column() == 3 and + node.is_updating): return self._red_brush - return QVariant() + return None def setData(self, index, value, role): """Re-implemented function called when a value has been edited""" node = index.internalPointer() if role == Qt.EditRole: - new_val = str(value.toString()) + new_val = str(value) # This will not update the value, only trigger a setting and # reading of the parameter from the Crazyflie node.set_value(new_val) return True return False - def flags(self, index): """Re-implemented function for getting the flags for a certain index""" flag = super(ParamBlockModel, self).flags(index) node = index.internalPointer() - if index.column() == 3 and node.parent and node.access=="RW": + if index.column() == 3 and node.parent and node.access == "RW": flag |= Qt.ItemIsEditable return flag - def reset(self): """Reset the model""" + super(ParamBlockModel, self).beginResetModel() self._nodes = [] - super(ParamBlockModel, self).reset() + super(ParamBlockModel, self).endResetModel() self.layoutChanged.emit() @@ -252,4 +256,6 @@ class ParamTab(Tab, param_tab_class): self.paramTree.expandAll() def _disconnected(self, link_uri): + self._model.beginResetModel() self._model.reset() + self._model.endResetModel() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ParamTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ParamTab.pyc deleted file mode 100755 index 68c20f7541dca74cae5f9e4f4c2fd3595f495658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10768 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 Xj`J3-jT-(r>-5fR+iz^IZ$JG%ulRQ^ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/PlotTab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/PlotTab.py old mode 100755 new mode 100644 index b6cd3e19..42cbb02a --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/PlotTab.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/PlotTab.py @@ -20,47 +20,39 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ This tab plots different logging data defined by configurations that has been pre-configured. """ -__author__ = 'Bitcraze AB' -__all__ = ['PlotTab'] - -import glob -import json import logging -import os -import sys - -logger = logging.getLogger(__name__) -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import pyqtSlot, pyqtSignal, QThread, Qt -from PyQt4.QtGui import QMessageBox -from PyQt4.QtGui import QApplication, QStyledItemDelegate, QAbstractItemView -from PyQt4.QtCore import QAbstractItemModel, QModelIndex, QString, QVariant +from cfclient.ui.tab import Tab +from cfclient.ui.widgets.plotwidget import PlotWidget +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import QAbstractItemModel +from PyQt5.QtCore import QModelIndex +from PyQt5.QtCore import Qt +from PyQt5.QtWidgets import QMessageBox -from pprint import pprint -import datetime +import cfclient -from cfclient.ui.widgets.plotwidget import PlotWidget +__author__ = 'Bitcraze AB' +__all__ = ['PlotTab'] -from cflib.crazyflie.log import Log +logger = logging.getLogger(__name__) -from cfclient.ui.tab import Tab +plot_tab_class = uic.loadUiType(cfclient.module_path + + "/ui/tabs/plotTab.ui")[0] -plot_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/tabs/plotTab.ui")[0] class LogConfigModel(QAbstractItemModel): """Model for log configurations in the ComboBox""" + def __init__(self, parent=None): super(LogConfigModel, self).__init__(parent) self._nodes = [] @@ -85,7 +77,7 @@ class LogConfigModel(QAbstractItemModel): """Re-implemented method to get the number of rows for a given index""" parent_item = parent.internalPointer() if parent.isValid(): - parent_item = parent.internalPointer() + parent_item = parent.internalPointer() # noqa return 0 else: return len(self._nodes) @@ -104,12 +96,12 @@ class LogConfigModel(QAbstractItemModel): def data(self, index, role): """Re-implemented method to get the data for a given index and role""" - node = index.internalPointer() - if not index.isValid() or not 0 <= index.row() < len(self._nodes): - return QVariant() + node = index.internalPointer() # noqa + if not index.isValid() or not 0 <= index.row() < len(self._nodes): + return None if role == Qt.DisplayRole: return self._nodes[index.row()].name - return QVariant() + return None def reset(self): """Reset the model""" @@ -119,6 +111,7 @@ class LogConfigModel(QAbstractItemModel): def get_config(self, i): return self._nodes[i] + class PlotTab(Tab, plot_tab_class): """Tab for plotting logging data""" @@ -127,7 +120,17 @@ class PlotTab(Tab, plot_tab_class): _disconnected_signal = pyqtSignal(str) _connected_signal = pyqtSignal(str) - colors = ['g', 'b', 'm', 'r', 'y', 'c'] + colors = [ + (60, 200, 60), # green + (40, 100, 255), # blue + (255, 130, 240), # magenta + (255, 26, 28), # red + (255, 170, 0), # orange + (40, 180, 240), # cyan + (153, 153, 153), # grey + (176, 96, 50), # brown + (180, 60, 240), # purple + ] def __init__(self, tabWidget, helper, *args): super(PlotTab, self).__init__(*args) @@ -174,7 +177,9 @@ class PlotTab(Tab, plot_tab_class): def _disconnected(self, link_uri): """Callback for when the Crazyflie has been disconnected""" + self._model.beginResetModel() self._model.reset() + self._model.endResetModel() self.dataSelector.setCurrentIndex(-1) self._previous_config = None self._started_previous = False @@ -204,7 +209,7 @@ class PlotTab(Tab, plot_tab_class): # First check if we need to stop the old block if self._started_previous and self._previous_config: logger.debug("Should stop config [%s], stopping!", - self._previous_config.name) + self._previous_config.name) self._previous_config.delete() # Remove our callback for the previous config @@ -227,8 +232,8 @@ class PlotTab(Tab, plot_tab_class): self._plot.set_title(lg.name) for d in lg.variables: - self._plot.add_curve(d.name, - self.colors[color_selector % len(self.colors)]) + self._plot.add_curve(d.name, self.colors[ + color_selector % len(self.colors)]) color_selector += 1 lg.data_received_cb.add_callback(self._log_data_signal_wrapper) lg.error_cb.add_callback(self._log_error_signal_wrapper) @@ -242,8 +247,9 @@ class PlotTab(Tab, plot_tab_class): def _logging_error(self, log_conf, msg): """Callback from the log layer when an error occurs""" - QMessageBox.about(self, "Plot error", "Error when starting log config" - " [%s]: %s" % (log_conf.name, msg)) + QMessageBox.about( + self, "Plot error", "Error when starting log config [%s]: %s" % ( + log_conf.name, msg)) def _log_data_received(self, timestamp, data, logconf): """Callback when the log layer receives new data""" diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/PlotTab.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/PlotTab.pyc deleted file mode 100755 index 6177d2525e46ab08df538999f586baf6b8b331ad..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9626 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/__init__.py old mode 100755 new mode 100644 index e9bfba63..d07aa572 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/__init__.py @@ -7,7 +7,7 @@ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ # -# Copyright (C) 2011-2013 Bitcraze AB +# Copyright (C) 2011-2017 Bitcraze AB # # Crazyflie Nano Quadcopter Client # @@ -20,38 +20,38 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Find all the available tabs so they can be loaded. Dropping a new .py file into this directory will automatically list and load it into the UI when it is started. """ +from .ConsoleTab import ConsoleTab +# from .ExampleTab import ExampleTab +from .FlightTab import FlightTab +# from .GpsTab import GpsTab +from .LEDTab import LEDTab +from .LogBlockTab import LogBlockTab +from .LogTab import LogTab +from .ParamTab import ParamTab +from .PlotTab import PlotTab +from .locopositioning_tab import LocoPositioningTab __author__ = 'Bitcraze AB' __all__ = [] -import os -import glob -import logging - -logger = logging.getLogger(__name__) - -found_tabs = [os.path.splitext(os.path.basename(f))[0] for - f in glob.glob(os.path.dirname(__file__) + "/[A-Za-z]*Tab.py")] -if len(found_tabs) == 0: - found_tabs = [os.path.splitext(os.path.basename(f))[0] for - f in glob.glob(os.path.dirname(__file__) + - "/[A-Za-z]*Tab.pyc")] - -logger.debug("Found tabs: %s", found_tabs) - -available = [] - -for tab in found_tabs: - tabModule = __import__(tab, globals(), locals(), [tab], -1) - available.append(getattr(tabModule, tab)) +available = [ + ConsoleTab, + # ExampleTab, + FlightTab, + # GpsTab, + LEDTab, + LogBlockTab, + LogTab, + ParamTab, + PlotTab, + LocoPositioningTab, +] diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/__init__.pyc deleted file mode 100755 index 229ceb2b231e511d54ef38e37ed32371bd1adde2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1101 zcmb7CO>fgc5S_J?v`xQTN`ccB2`NHKeFg!dRjGvdkPt;6qhhV?NwUGQUGIiAz2?UM z;HPlm?;vr7w{8L#IN-#yGjC>g-pttlzS<sr`+Snn>{-D17_WIJh*F{uQcx(U58a~_ zf1fg+LVvC|C~VC2CWTGnCJkG}3p7RIqD$lk4I9Kh4VP%xCSG=~v_ZQ#j!ruiuFRdQ zb7hTq#YMTmCf)qt(HT>?PP{?9K0`lxRQ>q({jLAJ|Es${2irv&Zc@5X7xGBB&bR2| ziL;MRA5yqYe2o}#ho%U>UdwIjgQ`bU%wU&zi-tFdZxTb_rYUei;%r;I#rR%#7Ttuu zK(vo_o=TNv(hgXvPfBMh&RAL%8)*uMPGq8T8MDj^m2$e@ZXZ=eS?atmmCX5E?w1qU z(@4^}bs5^oR9BqXqMFEajl0#@79(YKf<hCSX=9~AS$APu+j$<#H&5mHfOF|El((v~ zuAo^4(?e~ON?o!%IMhG!yfhm?gZBsBP<1a)@1Cd_L^Lomn}6{nW)0|ZF-Bq6-F<n- zbZ!B%?vsn6v`C`Jwrd@H2So+*$_3WYJ-7;E8#ww|5!b$~==U)QyW~K&&tY<9-E^ZU zS0hGR3x*2=?ovx-2X!h&<RWIlZhi>HH&4A9GG(SMU)b7+mEk(r(d)SuBG-cT-QAqq zCeD=O@fDHZTde&EoOPu~Wl`B#SFQz>nHfDS#?(z9`bCkBGp-$~EIChWy68?>TXj&0 z{s{95W-us59K^Hz1Z7nWv3wJ_bxnGi=57L!ThlEkm}?$nIu4TF6&Q?l;Ccz7Naq^t tu*ACO2cw$DqdinGw;@_yOSHTdfuFbT`Qn+_6290G_q+|S<*kZ6@e4O62crN0 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/consoleTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/consoleTab.ui old mode 100755 new mode 100644 index 39f514a8..6011683b --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/consoleTab.ui +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/consoleTab.ui @@ -13,12 +13,49 @@ <property name="windowTitle"> <string>Form</string> </property> - <layout class="QVBoxLayout" name="verticalLayout"> + <layout class="QHBoxLayout" name="horizontalLayout"> <item> - <layout class="QGridLayout" name="gridLayout"> - <item row="0" column="0"> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> <widget class="QTextEdit" name="console"/> </item> + <item> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QPushButton" name="_clearButton"> + <property name="text"> + <string>Clear</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="_dumpSystemLoadButton"> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Task dump</string> + </property> + <property name="checkable"> + <bool>false</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> </layout> </item> </layout> diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/exampleTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/exampleTab.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/flightTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/flightTab.ui old mode 100755 new mode 100644 index 5653fb73..28e4ae86 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/flightTab.ui +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/flightTab.ui @@ -34,7 +34,7 @@ </property> <property name="minimumSize"> <size> - <width>320</width> + <width>160</width> <height>0</height> </size> </property> @@ -54,16 +54,10 @@ <widget class="QComboBox" name="flightModeCombo"> <property name="minimumSize"> <size> - <width>150</width> + <width>0</width> <height>0</height> </size> </property> - <property name="maximumSize"> - <size> - <width>150</width> - <height>16777215</height> - </size> - </property> <property name="toolTip"> <string><html><head/><body><p>Select what flightmode to use:</p><p> * Safe prevents crashing</p><p> * Crazy does not prevent crashing :)</p></body></html></string> </property> @@ -104,23 +98,23 @@ <item row="2" column="0"> <widget class="QLabel" name="label_5"> <property name="text"> - <string>Thrust mode</string> + <string>Assist mode</string> </property> </widget> </item> <item row="2" column="1"> - <widget class="QComboBox" name="thrustModeCombo"> + <widget class="QComboBox" name="_assist_mode_combo"> <property name="enabled"> - <bool>false</bool> + <bool>true</bool> </property> <item> <property name="text"> - <string>Linear</string> + <string>Altitude hold</string> </property> </item> <item> <property name="text"> - <string>Quadratic</string> + <string>Position hold</string> </property> </item> </widget> @@ -236,7 +230,7 @@ </property> <property name="minimumSize"> <size> - <width>320</width> + <width>160</width> <height>0</height> </size> </property> @@ -347,7 +341,7 @@ <widget class="QGroupBox" name="groupBox_4"> <property name="minimumSize"> <size> - <width>320</width> + <width>160</width> <height>0</height> </size> </property> diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/gpsTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/gpsTab.ui old mode 100755 new mode 100644 index da2c503d..d9af9747 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/gpsTab.ui +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/gpsTab.ui @@ -30,18 +30,29 @@ <property name="sizeConstraint"> <enum>QLayout::SetDefaultConstraint</enum> </property> - <item row="0" column="5"> - <widget class="QLabel" name="label_6"> + <item row="2" column="2"> + <widget class="QLabel" name="label_7"> <property name="text"> - <string>Accuracy</string> + <string>Fix Type</string> </property> </widget> </item> - <item row="1" column="0"> - <widget class="QLineEdit" name="_lat"> - <property name="enabled"> + <item row="0" column="3"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Ground speed</string> + </property> + </widget> + </item> + <item row="1" column="4"> + <widget class="QLineEdit" name="_height"> + <property name="readOnly"> <bool>true</bool> </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLineEdit" name="_speed"> <property name="readOnly"> <bool>true</bool> </property> @@ -54,46 +65,42 @@ </property> </widget> </item> - <item row="0" column="1"> - <widget class="QLabel" name="label_2"> - <property name="text"> - <string>Long</string> + <item row="1" column="0"> + <widget class="QLineEdit" name="_lat"> + <property name="enabled"> + <bool>true</bool> </property> - </widget> - </item> - <item row="2" column="0"> - <widget class="QLineEdit" name="_speed_max"> <property name="readOnly"> <bool>true</bool> </property> </widget> </item> - <item row="1" column="5"> - <widget class="QLineEdit" name="_accuracy"/> - </item> - <item row="2" column="2"> - <widget class="QLineEdit" name="_fix_type"> - <property name="readOnly"> - <bool>true</bool> + <item row="0" column="1"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Long</string> </property> </widget> </item> - <item row="0" column="3"> - <widget class="QLabel" name="label_4"> + <item row="0" column="5"> + <widget class="QLabel" name="label_6"> <property name="text"> - <string>Ground speed</string> + <string>Accuracy</string> </property> </widget> </item> - <item row="1" column="4"> - <widget class="QLineEdit" name="_height"> + <item row="1" column="5"> + <widget class="QLineEdit" name="_accuracy"/> + </item> + <item row="3" column="0"> + <widget class="QLineEdit" name="_speed_max"> <property name="readOnly"> <bool>true</bool> </property> </widget> </item> - <item row="1" column="3"> - <widget class="QLineEdit" name="_speed"> + <item row="3" column="2"> + <widget class="QLineEdit" name="_fix_type"> <property name="readOnly"> <bool>true</bool> </property> @@ -127,13 +134,30 @@ </property> </widget> </item> - <item row="2" column="1"> + <item row="3" column="1"> <widget class="QPushButton" name="_reset_max_btn"> <property name="text"> <string>Reset all</string> </property> </widget> </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_8"> + <property name="text"> + <string>Max speed</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QLabel" name="label_9"> + <property name="text"> + <string>Locked sats</string> + </property> + </widget> + </item> + <item row="3" column="3"> + <widget class="QLineEdit" name="_nbr_locked_sats"/> + </item> </layout> </item> <item> diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ledTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/ledTab.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/locopositioning_tab.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/locopositioning_tab.py new file mode 100644 index 00000000..b5885f27 --- /dev/null +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/locopositioning_tab.py @@ -0,0 +1,671 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# || ____ _ __ +# +------+ / __ )(_) /_______________ _____ ___ +# | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ +# +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ +# || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ +# +# Copyright (C) 2011-2017 Bitcraze AB +# +# Crazyflie Nano Quadcopter Client +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +""" +Shows data for the Loco Positioning system +""" + +import logging +from enum import Enum +from collections import namedtuple + +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal, QTimer +from PyQt5.QtGui import QFont +from PyQt5.QtGui import QMessageBox + +import cfclient +from cfclient.ui.tab import Tab + +from cflib.crazyflie.log import LogConfig +from cflib.crazyflie.mem import MemoryElement +from lpslib.lopoanchor import LoPoAnchor + +import copy +import sys + +__author__ = 'Bitcraze AB' +__all__ = ['LocoPositioningTab'] + +logger = logging.getLogger(__name__) + +locopositioning_tab_class = uic.loadUiType( + cfclient.module_path + "/ui/tabs/locopositioning_tab.ui")[0] + +# Try the imports for PyQtGraph to see if it is installed +try: + import pyqtgraph as pg + from pyqtgraph import ViewBox # noqa + import pyqtgraph.console # noqa + import numpy as np # noqa + + _pyqtgraph_found = True +except Exception: + import traceback + + logger.warning("PyQtGraph (or dependency) failed to import:\n%s", + traceback.format_exc()) + _pyqtgraph_found = False + + +class Anchor: + def __init__(self, x=0.0, y=0.0, z=0.0, distance=0.0): + self.x = x + self.y = y + self.z = z + self.distance = distance + + def set_position(self, position): + """Sets the position.""" + self.x = position[0] + self.y = position[1] + self.z = position[2] + + def get_position(self): + """Returns the position as a vector""" + return (self.x, self.y, self.z) + + +class AxisScaleStep: + def __init__(self, from_view, from_axis, to_view, to_axis, + center_only=False): + self.from_view = from_view.view + self.from_axis = from_axis + self.to_view = to_view.view + self.to_axis = to_axis + self.center_only = center_only + + +class PlotWrapper: + XAxis = 0 + YAxis = 1 + _refs = [] + _change_lock = False + + axis_dict = {'x': 0, 'y': 1, 'z': 2} + + ANCHOR_BRUSH = (60, 60, 60) + HIGHLIGHT_ANCHOR_BRUSH = (0, 255, 0) + POSITION_BRUSH = (0, 0, 255) + + VICINITY_DISTANCE = 2.5 + HIGHLIGHT_DISTANCE = 0.5 + + LABEL_SIZE = 15 + LABEL_HIGHLIGHT_SIZE = 30 + + ANCHOR_SIZE = 10 + HIGHLIGHT_SIZE = 20 + + def __init__(self, title, horizontal, vertical): + self._horizontal = horizontal + self._vertical = vertical + self._depth = self._find_missing_axis(horizontal, vertical) + self._title = title + self.widget = pg.PlotWidget(title=title, enableMenu=False) + self.widget.getPlotItem().hideButtons() + self._axis_scale_steps = [] + + self.widget.setLabel('left', self._vertical, units='m') + self.widget.setLabel('bottom', self._horizontal, units='m') + + self.widget.setAspectLocked(True, 1) + self.widget.getViewBox().sigRangeChanged.connect(self._view_changed) + self.view = self.widget.getViewBox() + + def update(self, anchors, pos, display_mode): + self.widget.clear() + + # Sort anchors in depth order to add the one closes last + for (i, anchor) in sorted( + anchors.items(), + key=lambda item: getattr(item[1], self._depth), reverse=True): + anchor_v = getattr(anchor, self._horizontal) + anchor_h = getattr(anchor, self._vertical) + self._plot_anchor(anchor_v, anchor_h, i, anchor.distance, + display_mode) + + if display_mode is DisplayMode.estimated_position: + cf_h = pos[PlotWrapper.axis_dict[self._horizontal]] + cf_v = pos[PlotWrapper.axis_dict[self._vertical]] + self.widget.plot([cf_h], [cf_v], pen=None, + symbolBrush=PlotWrapper.POSITION_BRUSH) + + def _find_missing_axis(self, axis1, axis2): + all = set(self.axis_dict.keys()) + all.remove(axis1) + all.remove(axis2) + + return list(all)[0] + + def _plot_anchor(self, x, y, anchor_id, distance, display_mode): + brush = PlotWrapper.ANCHOR_BRUSH + size = PlotWrapper.ANCHOR_SIZE + font_size = self.LABEL_SIZE + if display_mode is DisplayMode.identify_anchor: + if distance < PlotWrapper.VICINITY_DISTANCE: + brush = self._mix_brushes( + brush, + PlotWrapper.HIGHLIGHT_ANCHOR_BRUSH, + distance / PlotWrapper.VICINITY_DISTANCE) + + if distance < PlotWrapper.HIGHLIGHT_DISTANCE: + brush = PlotWrapper.HIGHLIGHT_ANCHOR_BRUSH + size = PlotWrapper.HIGHLIGHT_SIZE + font_size = self.LABEL_HIGHLIGHT_SIZE + + self.widget.plot([x], [y], pen=None, symbolBrush=brush, + symbolSize=size) + + text = pg.TextItem(text="{}".format(anchor_id)) + font = QFont("Helvetica", font_size) + text.setFont(font) + self.widget.addItem(text) + text.setPos(x, y) + + def _mix_brushes(self, brush1, brush2, mix): + if mix < 0.0: + return brush1 + if mix > 1.0: + return brush2 + + b1 = mix + b2 = 1.0 - mix + return ( + brush1[0] * b1 + brush2[0] * b2, + brush1[1] * b1 + brush2[1] * b2, + brush1[2] * b1 + brush2[2] * b2, + ) + + def _view_changed(self, view, settings): + # Ignore all callbacks until this change is processed + if PlotWrapper._change_lock: + return + PlotWrapper._change_lock = True + + for step in self._axis_scale_steps: + range = step.from_view.viewRange()[step.from_axis] + new_range = range + + if step.center_only: + center = (range[0] + range[1]) / 2 + current_range = step.to_view.viewRange()[step.to_axis] + current_center = (current_range[0] + current_range[1]) / 2 + delta = center - current_center + new_range = [current_range[0] + delta, + current_range[1] + delta] + + if step.to_axis is PlotWrapper.XAxis: + step.to_view.setRange(xRange=new_range, padding=0.0, + update=True) + else: + step.to_view.setRange(yRange=new_range, padding=0.0, + update=True) + + PlotWrapper._change_lock = False + + def set_scale_steps(self, steps): + self._axis_scale_steps = steps + + +class DisplayMode(Enum): + identify_anchor = 1 + estimated_position = 2 + + +Range = namedtuple('Range', ['min', 'max']) + + +class AnchorPosWrapper(): + """Wraps the UI elements of one anchor position""" + def __init__(self, x, y, z): + self._x = x + self._y = y + self._z = z + + def get_position(self): + """Get the position from the UI elements""" + return (self._x.value(), self._y.value(), self._z.value()) + + def set_position(self, position): + """Set the position in the UI elements""" + self._x.setValue(position[0]) + self._y.setValue(position[1]) + self._z.setValue(position[2]) + + def enable(self, enabled): + """Enable/disable all UI elements for the position""" + self._x.setEnabled(enabled) + self._y.setEnabled(enabled) + self._z.setEnabled(enabled) + + +class LocoPositioningTab(Tab, locopositioning_tab_class): + """Tab for plotting Loco Positioning data""" + + # Update period of log data in ms + UPDATE_PERIOD_LOG = 100 + + # Update period of anchor position data + UPDATE_PERIOD_ANCHOR_POS = 5000 + + # Frame rate (updates per second) + FPS = 2 + + _connected_signal = pyqtSignal(str) + _disconnected_signal = pyqtSignal(str) + _log_error_signal = pyqtSignal(object, str) + _anchor_range_signal = pyqtSignal(int, object, object) + _position_signal = pyqtSignal(int, object, object) + _anchor_position_signal = pyqtSignal(object) + + def __init__(self, tabWidget, helper, *args): + super(LocoPositioningTab, self).__init__(*args) + self.setupUi(self) + + self.tabName = "Loco Positioning" + self.menuName = "Loco Positioning Tab" + self.tabWidget = tabWidget + + self._helper = helper + + self._anchors = {} + self._position = [] + self._clear_state() + self._refs = [] + + self._display_mode = DisplayMode.estimated_position + + # Always wrap callbacks from Crazyflie API though QT Signal/Slots + # to avoid manipulating the UI when rendering it + self._connected_signal.connect(self._connected) + self._disconnected_signal.connect(self._disconnected) + self._anchor_range_signal.connect(self._anchor_range_received) + self._position_signal.connect(self._position_received) + self._anchor_position_signal.connect(self._anchor_positions_updated) + + self._id_anchor_button.clicked.connect( + lambda enabled: + self._set_display_mode(DisplayMode.identify_anchor) + ) + + self._estimated_postion_button.clicked.connect( + lambda enabled: + self._set_display_mode(DisplayMode.estimated_position) + ) + + self._anchor_pos_ui = {} + for anchor_nr in range(0, 8): + self._register_anchor_pos_ui(anchor_nr) + + self._write_pos_to_anhors_button.clicked.connect( + lambda enabled: + self._write_positions_to_anchors() + ) + + self._read_pos_from_anhors_button.clicked.connect( + lambda enabled: + self._read_positions_from_anchors() + ) + + self._show_all_button.clicked.connect(self._scale_and_center_graphs) + + # Connect the Crazyflie API callbacks to the signals + self._helper.cf.connected.add_callback( + self._connected_signal.emit) + + self._helper.cf.disconnected.add_callback( + self._disconnected_signal.emit) + + self._set_up_plots() + + self._graph_timer = QTimer() + self._graph_timer.setInterval(1000 / self.FPS) + self._graph_timer.timeout.connect(self._update_graphics) + self._graph_timer.start() + + self._anchor_pos_timer = QTimer() + self._anchor_pos_timer.setInterval(self.UPDATE_PERIOD_ANCHOR_POS) + self._anchor_pos_timer.timeout.connect(self._poll_anchor_positions) + + def _register_anchor_pos_ui(self, nr): + x_spin = getattr(self, 'spin_a{}x'.format(nr)) + y_spin = getattr(self, 'spin_a{}y'.format(nr)) + z_spin = getattr(self, 'spin_a{}z'.format(nr)) + self._anchor_pos_ui[nr] = AnchorPosWrapper(x_spin, y_spin, z_spin) + + def _write_positions_to_anchors(self): + lopo = LoPoAnchor(self._helper.cf) + + for id, anchor_pos in self._anchor_pos_ui.items(): + if id in self._anchors: + position = anchor_pos.get_position() + lopo.set_position(id, position) + + def _read_positions_from_anchors(self): + for id, anchor_pos in self._anchor_pos_ui.items(): + position = (0.0, 0.0, 0.0) + if id in self._anchors: + position = self._anchors[id].get_position() + + anchor_pos.set_position(position) + + def _enable_anchor_pos_ui(self): + for id, anchor_pos in self._anchor_pos_ui.items(): + exists = id in self._anchors + anchor_pos.enable(exists) + + def _set_up_plots(self): + self._plot_xy = PlotWrapper("Top view (X/Y)", "x", "y") + self._plot_top_left_layout.addWidget(self._plot_xy.widget) + self._plot_xz = PlotWrapper("Front view (X/Z)", "x", "z") + self._plot_bottom_left_layout.addWidget(self._plot_xz.widget) + self._plot_yz = PlotWrapper("Right view (Y/Z)", "y", "z") + self._plot_bottom_right_layout.addWidget(self._plot_yz.widget) + self._plot_xy.set_scale_steps([ + AxisScaleStep(self._plot_xy, PlotWrapper.XAxis, + self._plot_xz, PlotWrapper.XAxis), + AxisScaleStep(self._plot_xz, PlotWrapper.YAxis, + self._plot_yz, PlotWrapper.YAxis), + AxisScaleStep(self._plot_xy, PlotWrapper.YAxis, + self._plot_yz, PlotWrapper.XAxis, center_only=True) + ]) + self._plot_xz.set_scale_steps([ + AxisScaleStep(self._plot_xz, PlotWrapper.XAxis, + self._plot_xy, PlotWrapper.XAxis), + AxisScaleStep(self._plot_xz, PlotWrapper.YAxis, + self._plot_yz, PlotWrapper.YAxis), + AxisScaleStep(self._plot_xy, PlotWrapper.YAxis, + self._plot_yz, PlotWrapper.XAxis, center_only=True) + ]) + self._plot_yz.set_scale_steps([ + AxisScaleStep(self._plot_yz, PlotWrapper.YAxis, + self._plot_xz, PlotWrapper.YAxis), + AxisScaleStep(self._plot_xz, PlotWrapper.XAxis, + self._plot_xy, PlotWrapper.XAxis), + AxisScaleStep(self._plot_yz, PlotWrapper.XAxis, + self._plot_xy, PlotWrapper.YAxis, center_only=True) + ]) + + self._plot_xy.view.setRange(xRange=(0.0, 5.0)) + + def _set_display_mode(self, display_mode): + self._display_mode = display_mode + + def _clear_state(self): + self._anchors = {} + self._position = [0.0, 0.0, 0.0] + + def _scale_and_center_graphs(self): + start_bounds = Range(sys.float_info.max, -sys.float_info.max) + bounds = {"x": start_bounds, "y": start_bounds, + "z": start_bounds} + for a in self._anchors.values(): + bounds = self._find_min_max_data_range(bounds, [a.x, a.y, a.z]) + bounds = self._find_min_max_data_range(bounds, self._position) + + bounds = self._pad_bounds(bounds) + self._center_all_data_in_graphs(bounds) + self._rescale_to_fit_data(bounds) + + def _rescale_to_fit_data(self, bounds): + [[xy_xmin, xy_xmax], + [xy_ymin, xy_ymax]] = self._plot_xy.view.viewRange() + [[yz_xmin, yz_xmax], + [yz_ymin, yz_ymax]] = self._plot_yz.view.viewRange() + if not self._is_data_visibile(bounds, self._position): + if self._will_new_range_zoom_in(Range(xy_xmin, xy_xmax), + bounds["x"]): + self._plot_xy.view.setRange(xRange=bounds["x"], + padding=0.0, update=True) + + if not self._is_data_visibile(bounds, self._position): + if self._will_new_range_zoom_in(Range(xy_ymin, xy_ymax), + bounds["y"]): + self._plot_xy.view.setRange(yRange=bounds["y"], + padding=0.0, update=True) + + if not self._is_data_visibile(bounds, self._position): + if self._will_new_range_zoom_in(Range(yz_xmin, yz_xmax), + bounds["y"]): + self._plot_yz.view.setRange(yRange=bounds["y"], + padding=0.0, update=True) + + if not self._is_data_visibile(bounds, self._position): + if self._will_new_range_zoom_in(Range(yz_ymin, yz_ymax), + bounds["z"]): + self._plot_yz.view.setRange(yRange=bounds["z"], padding=0.0, + update=True) + + def _pad_bounds(self, ranges): + new_ranges = ranges + + new_ranges["x"] = Range(new_ranges["x"].min - 1.0, + new_ranges["x"].max + 1.0) + + new_ranges["y"] = Range(new_ranges["y"].min - 1.0, + new_ranges["y"].max + 1.0) + + new_ranges["z"] = Range(new_ranges["z"].min - 1.0, + new_ranges["z"].max + 1.0) + + return new_ranges + + def _center_all_data_in_graphs(self, ranges): + # Will center data in graphs without taking care of scaling + self._plot_xy.view.setRange(xRange=ranges["x"], yRange=ranges["y"], + padding=0.0, update=True) + self._plot_yz.view.setRange(yRange=ranges["z"], padding=0.0, + update=True) + + def _will_new_range_zoom_in(self, old_range, new_range): + return old_range.min > new_range.min + + def _is_data_visibile(self, ranges, point): + [[xy_xmin, xy_xmax], + [xy_ymin, xy_ymax]] = self._plot_xy.view.viewRange() + [[yz_xmin, yz_xmax], + [yz_ymin, yz_ymax]] = self._plot_yz.view.viewRange() + [[xz_xmin, xz_xmax], + [xz_ymin, xz_ymax]] = self._plot_xz.view.viewRange() + + allVisible = True + + if ranges["x"].min < xy_xmin or ranges["x"].max > xy_xmax: + allVisible = False + + if ranges["z"].min < yz_ymin or ranges["z"].max > yz_ymax: + allVisible = False + + if ranges["y"].min < yz_xmin or ranges["y"].max > yz_xmax: + allVisible = False + + if ranges["y"].min < xy_ymin or ranges["y"].max > xy_ymax: + allVisible = False + + return allVisible + + def _find_min_max_data_range(self, ranges, point): + result = ranges + + result["x"] = Range(min(ranges["x"].min, point[0]), + max(ranges["x"].max, point[0])) + + result["y"] = Range(min(ranges["y"].min, point[1]), + max(ranges["y"].max, point[1])) + + result["z"] = Range(min(ranges["z"].min, point[2]), + max(ranges["z"].max, point[2])) + + return result + + def _connected(self, link_uri): + """Callback when the Crazyflie has been connected""" + logger.debug("Crazyflie connected to {}".format(link_uri)) + + self._clear_state() + + try: + self._register_logblock( + "LoPoTab0", + [ + ("ranging", "distance0", "float"), + ("ranging", "distance1", "float"), + ("ranging", "distance2", "float"), + ("ranging", "distance3", "float"), + ], + self._anchor_range_signal.emit, + self._log_error_signal.emit) + + self._register_logblock( + "LoPoTab1", + [ + ("ranging", "distance4", "float"), + ("ranging", "distance5", "float"), + ("ranging", "distance6", "float"), + ("ranging", "distance7", "float"), + ], + self._anchor_range_signal.emit, + self._log_error_signal.emit), + + self._register_logblock( + "LoPoTab2", + [ + ("kalman", "stateX", "float"), + ("kalman", "stateY", "float"), + ("kalman", "stateZ", "float"), + ], + self._position_signal.emit, + self._log_error_signal.emit), + except KeyError as e: + logger.warning(str(e)) + except AttributeError as e: + logger.warning(str(e)) + + self._start_polling_anchor_pos(self._helper.cf) + + def _disconnected(self, link_uri): + """Callback for when the Crazyflie has been disconnected""" + logger.debug("Crazyflie disconnected from {}".format(link_uri)) + self._stop_polling_anchor_pos() + + def _register_logblock(self, logblock_name, variables, data_cb, error_cb): + """Register log data to listen for. One logblock can contain a limited + number of parameters (6 for floats).""" + lg = LogConfig(logblock_name, self.UPDATE_PERIOD_LOG) + for variable in variables: + if self._is_in_toc(variable): + lg.add_variable('{}.{}'.format(variable[0], variable[1]), + variable[2]) + + self._helper.cf.log.add_config(lg) + lg.data_received_cb.add_callback(data_cb) + lg.error_cb.add_callback(error_cb) + lg.start() + return lg + + def _is_in_toc(self, variable): + toc = self._helper.cf.log.toc + group = variable[0] + param = variable[1] + return group in toc.toc and param in toc.toc[group] + + def _anchor_range_received(self, timestamp, data, logconf): + """Callback from the logging system when a range is updated.""" + for name, value in data.items(): + valid, anchor_number = self._parse_range_param_name(name) + if valid: + self._get_anchor(anchor_number).distance = float(value) + + def _position_received(self, timestamp, data, logconf): + """Callback from the logging system when the position is updated.""" + for name, value in data.items(): + valid, axis = self._parse_position_param_name(name) + if valid: + self._position[axis] = float(value) + + def _logging_error(self, log_conf, msg): + """Callback from the log layer when an error occurs""" + QMessageBox.about(self, "LocoPositioningTab error", + "Error when using log config", + " [{0}]: {1}".format(log_conf.name, msg)) + + def _start_polling_anchor_pos(self, crazyflie): + """Set up a timer to poll anchor positions from the memory sub + system""" + self._anchor_pos_timer.start() + + def _stop_polling_anchor_pos(self): + self._anchor_pos_timer.stop() + + def _poll_anchor_positions(self): + mems = self._helper.cf.mem.get_mems(MemoryElement.TYPE_LOCO) + if len(mems) > 0: + mems[0].update(self._anchor_position_signal.emit) + + def _anchor_positions_updated(self, mem): + """Callback from the memory sub system when the anchor positions + are updated""" + for anchor_number, anchor_data in enumerate(mem.anchor_data): + if anchor_data.is_valid: + anchor = self._get_anchor(anchor_number) + anchor.set_position(anchor_data.position) + + def _parse_range_param_name(self, name): + """Parse a parameter name for a ranging distance and return the number + of the anchor. The name is on the format 'ranging.distance4' """ + valid = False + anchor = 0 + if name.startswith('ranging.distance'): + anchor = int(name[-1]) + valid = True + return (valid, anchor) + + def _parse_position_param_name(self, name): + """Parse a parameter name for a position and return the + axis (0=x, 1=y, 2=z). + The param name is on the format 'kalman.stateY' """ + valid = False + axis = 0 + if name.startswith('kalman.state'): + axis = {'X': 0, 'Y': 1, 'Z': 2}[name[-1]] + valid = True + return (valid, axis) + + def _get_anchor(self, anchor_number): + if anchor_number not in self._anchors: + self._anchors[anchor_number] = Anchor() + return self._anchors[anchor_number] + + def _update_graphics(self): + if self.is_visible(): + anchors = copy.deepcopy(self._anchors) + self._plot_yz.update(anchors, self._position, self._display_mode) + self._plot_xy.update(anchors, self._position, self._display_mode) + self._plot_xz.update(anchors, self._position, self._display_mode) + self._enable_anchor_pos_ui() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/locopositioning_tab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/locopositioning_tab.ui new file mode 100644 index 00000000..9c9fe234 --- /dev/null +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/locopositioning_tab.ui @@ -0,0 +1,338 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>Form</class> + <widget class="QWidget" name="Form"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>850</width> + <height>595</height> + </rect> + </property> + <property name="windowTitle"> + <string>Plot</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout" rowstretch="0,0" columnstretch="0,0"> + <property name="leftMargin"> + <number>0</number> + </property> + <item row="1" column="0"> + <layout class="QVBoxLayout" name="_plot_bottom_left_layout"/> + </item> + <item row="0" column="0"> + <layout class="QVBoxLayout" name="_plot_top_left_layout"/> + </item> + <item row="0" column="1"> + <layout class="QVBoxLayout" name="_inputLayout"> + <item> + <widget class="QGroupBox" name="groupBox_2"> + <property name="title"> + <string>Mode</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout_2"> + <item> + <widget class="QRadioButton" name="_estimated_postion_button"> + <property name="text"> + <string>Position estimate</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QRadioButton" name="_id_anchor_button"> + <property name="text"> + <string>Anchor identification</string> + </property> + </widget> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>13</height> + </size> + </property> + <property name="title"> + <string>Anchor Positions</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="anchor_block_0"> + <item> + <layout class="QHBoxLayout" name="block_a0"> + <item> + <widget class="QLabel" name="labela0"> + <property name="text"> + <string>Anchor 0</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a0x"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a0y"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a0z"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="block_a1"> + <item> + <widget class="QLabel" name="labela1"> + <property name="text"> + <string>Anchor 1</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a1x"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a1y"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a1z"/> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="anchor_block_1"> + <item> + <layout class="QHBoxLayout" name="block_a2"> + <item> + <widget class="QLabel" name="labela2"> + <property name="text"> + <string>Anchor 2</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a2x"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a2y"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a2z"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="block_a3"> + <item> + <widget class="QLabel" name="labela3"> + <property name="text"> + <string>Anchor 3</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a3x"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a3y"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a3z"/> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="anchor_block_2"> + <item> + <layout class="QHBoxLayout" name="block_a4"> + <item> + <widget class="QLabel" name="labela4"> + <property name="text"> + <string>Anchor 4</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a4x"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a4y"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a4z"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="block_a5"> + <item> + <widget class="QLabel" name="labela5"> + <property name="text"> + <string>Anchor 5</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a5x"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a5y"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a5z"/> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="anchor_block_3"> + <item> + <layout class="QHBoxLayout" name="block_a6"> + <item> + <widget class="QLabel" name="labela6"> + <property name="text"> + <string>Anchor 6</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a6x"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a6y"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a6z"/> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="block_a7"> + <item> + <widget class="QLabel" name="labela7"> + <property name="text"> + <string>Anchor 7</string> + </property> + </widget> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a7x"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a7y"/> + </item> + <item> + <widget class="QDoubleSpinBox" name="spin_a7z"/> + </item> + </layout> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_2"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="_read_pos_from_anhors_button"> + <property name="text"> + <string>Get from anchors</string> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="_write_pos_to_anhors_button"> + <property name="text"> + <string>Write to anchors</string> + </property> + </widget> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <widget class="QGroupBox" name="groupBox_3"> + <property name="title"> + <string>Graph settings</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout_5"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout_4"> + <item> + <widget class="QPushButton" name="_show_all_button"> + <property name="text"> + <string>Show all</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + </layout> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item row="1" column="1"> + <layout class="QVBoxLayout" name="_plot_bottom_right_layout"/> + </item> + </layout> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logBlockDebugTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logBlockDebugTab.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logBlockTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logBlockTab.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/logTab.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/paramTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/paramTab.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/plotTab.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/tabs/plotTab.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/ConsoleToolbox.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/ConsoleToolbox.py old mode 100755 new mode 100644 index 79c8f010..7dae68fa --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/ConsoleToolbox.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/ConsoleToolbox.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# || ____ _ __ -# +------+ / __ )(_) /_______________ _____ ___ +# || ____ _ __ +# +------+ / __ )(_) /_______________ _____ ___ # | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ @@ -15,51 +15,55 @@ # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ A detachable toolbox for showing console printouts from the Crazyflie """ +from PyQt5 import QtWidgets +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import Qt + +import cfclient __author__ = 'Bitcraze AB' __all__ = ['ConsoleToolbox'] -import sys, time +console_class = uic.loadUiType( + cfclient.module_path + "/ui/toolboxes/consoleToolbox.ui")[0] -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal - -console_class = uic.loadUiType(sys.path[0] + "/cfclient/ui/toolboxes/consoleToolbox.ui")[0] -class ConsoleToolbox(QtGui.QWidget, console_class): +class ConsoleToolbox(QtWidgets.QWidget, console_class): """Console toolbox for showing printouts from the Crazyflie""" update = pyqtSignal(str) def __init__(self, helper, *args): super(ConsoleToolbox, self).__init__(*args) self.setupUi(self) - + self.update.connect(self.console.insertPlainText) - + self.helper = helper def getName(self): return 'Console' - + + def _console_updated(self, data): + self.update.emit(data) + def enable(self): - self.helper.cf.console.receivedChar.add_callback(self.update.emit) - + self.helper.cf.console.receivedChar.add_callback(self._console_updated) + def disable(self): - self.helper.cf.console.receivedChar.remove_callback(self.update.emit) - + self.helper.cf.console.receivedChar.remove_callback( + self._console_updated) + def preferedDockArea(self): return Qt.BottomDockWidgetArea - diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/ConsoleToolbox.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/ConsoleToolbox.pyc deleted file mode 100755 index 0635198045bcde4805aa3c02761f9db148a5ce56..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2448 zcmc&#+m75s5G{M|v%A@F(T0d98i|)tr0l#P1X2X-4kB->tal@Xg=Bf`o|$%Rw{f>a z2JKsTLi`1P!|(6`P^at-1OZQk^-PzmFRrdSr@FfL>%p}6<;Tl}x~IqQ&$-#3S)@cE zOOHa2QlB=g_>}f2?Ni>Pkd;>NQ`i@MK>2`*A%#OKMih>y7*jYV59@}MPpFtuIHh8b z!aXYXDcmPdjVU`I)uZedr6anVj_J-z-jCJr5ZkH|Ww%Kk(waA)&<{i}iM|fsf*Tj} zDV%-GVtO)5m5Y;Yyvo(g8I!Nfi`m-LGrKk4>2fnmOlb|zRkbdiX`G#{Yg5eJR?U`m z{QYj7Yc;idZ0l6Jgh$lu<ka2b{<8h@vNfuI<L7J+sN9gnxm%iAxq+yU8|^UD=%iiY z%di{stJ;0*E^^}>oR*H>lyR=PM|RF)k*pJTqI8Q!FS-zvU389j+aI%Oe1QkXPq_&K zis@qDSTblmQhj0^!vP3n(3lej6Uqo&K^X%=C=*HtqD(2cm?I|pF^ewjzXkK(Kuq8k zKtKaG_DdFy{~ld2eLiJAUHSAAk;nb4C!=25=~Fg9KO0guLImEGd=;^`#Dsfn>TEuN zK_G6MO4R`?BoIfDF13pyH^Q89P4!d@Nllf;PRTICS*pZc>&OXr$jfzURqdYSu`Vyw z3n!m#RnGQXCi`MCUk6ADhhAK7gf{|tWWQmt*qTBuR$T%us@i0{7jt->VGmn|?Zay4 zwx(R<di4*qzn*o+)h<919b+db<Q;hj{*j*mk?Xd^EL>yKFXrIkOycZpiJt;tfQZ{J zD{tO+@nWOgSzM@(upxXS@0IiDit`_^0{Z#yAx}6vvc8NAkP}FVKji^vZux+LWF74D z%R$sCQTn+`m)p3OfjCX0B+m0yoIDF~0);|VXm>M!;Fzfr)#?-0{%bsfci5<)5xk37 zL3gbR^IW|SLU6<rHv<5;OSJ_8k68UH0!V4e2(07c!Rc^)`oVR8EO&_Qlq;$!zA(wN zuXM^Oc2cYOW+J-H-c+?(t6HV-2cCS!V_j%-+$~+1D)}66nL-{$QDM?1M;D<+QEHMX z3XmUil~`9xzRK|r-sa)p4#ZuE_gVaLj759%b%^(*2iz<w;m{j;`~GA+>ESmQ|L*g6 z7hBwLnX6yL#s`q~9zNb#Ie|_W?dADockVt6KzkqrW09O(nK*8*S)n~Z<!=E3fVqj& zr}}bNDKS{ZZtD(soC`gQdz9p{wSw(=n;~*v{NJbv@sC=nKLtQ7dj8Ox`0x4mynFtA F|95dnMO**? diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/CrtpSharkToolbox.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/CrtpSharkToolbox.py old mode 100755 new mode 100644 index 37476512..718aa7bf --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/CrtpSharkToolbox.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/CrtpSharkToolbox.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# || ____ _ __ -# +------+ / __ )(_) /_______________ _____ ___ +# || ____ _ __ +# +------+ / __ )(_) /_______________ _____ ___ # | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ @@ -15,49 +15,53 @@ # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -Toolbox for showing packets that is sent via the communication link when debugging. +Toolbox for showing packets that is sent via the communication link when +debugging. """ +import os +from time import time +from binascii import hexlify -__author__ = 'Bitcraze AB' -__all__ = ['CrtpSharkBoolbox'] +from PyQt5 import QtWidgets +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import pyqtSlot +from PyQt5.QtCore import Qt -import sys, time -import os +import cfclient -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL -from time import time +__author__ = 'Bitcraze AB' +__all__ = ['CrtpSharkToolbox'] + +param_tab_class = uic.loadUiType( + cfclient.module_path + "/ui/toolboxes/crtpSharkToolbox.ui")[0] -param_tab_class = uic.loadUiType(sys.path[0] + - "/cfclient/ui/toolboxes/crtpSharkToolbox.ui")[0] -class CrtpSharkToolbox(QtGui.QWidget, param_tab_class): +class CrtpSharkToolbox(QtWidgets.QWidget, param_tab_class): """Show packets that is sent vie the communication link""" nameModified = pyqtSignal() _incoming_packet_signal = pyqtSignal(object) _outgoing_packet_signal = pyqtSignal(object) - + def __init__(self, helper, *args): super(CrtpSharkToolbox, self).__init__(*args) self.setupUi(self) self.helper = helper - - #Init the tree widget + + # Init the tree widget self.logTree.setHeaderLabels(['ms', 'Direction', 'Port/Chan', 'Data']) - - #Connect GUI signals + + # Connect GUI signals self.clearButton.clicked.connect(self.clearLog) self.saveButton.clicked.connect(self._save_data) @@ -68,50 +72,58 @@ class CrtpSharkToolbox(QtGui.QWidget, param_tab_class): self._data = [] def _packet(self, dir, pk): - if self.masterCheck.isChecked(): - line = QtGui.QTreeWidgetItem() + if self.masterCheck.isChecked() and \ + not (pk.port == 15 and pk.channel == 3): + line = QtWidgets.QTreeWidgetItem() - ms_diff = int(round(time()*1000))-self._ms_offset + ms_diff = int(round(time() * 1000)) - self._ms_offset line.setData(0, Qt.DisplayRole, "%d" % ms_diff) line.setData(1, Qt.DisplayRole, "%s" % dir) line.setData(2, Qt.DisplayRole, "%d/%d" % (pk.port, pk.channel)) - line.setData(3, Qt.DisplayRole, pk.datal.__str__()) + + line.setData(3, Qt.DisplayRole, hexlify(pk.data).decode('utf8')) s = "%d, %s, %d/%d, %s" % (ms_diff, dir, pk.port, pk.channel, - pk.datal.__str__()) + hexlify(pk.data).decode('utf8')) self._data.append(s) self.logTree.addTopLevelItem(line) self.logTree.scrollToItem(line) - + @pyqtSlot() def clearLog(self): self.logTree.clear() self._data = [] - + def getName(self): return 'Crtp sniffer' - + def getTabName(self): return 'Crtp sniffer' - + + def _incoming_packet(self, pk): + self._incoming_packet_signal.emit(pk) + + def _outgoing_packet(self, pk): + self._outgoing_packet_signal.emit(pk) + def enable(self): self.helper.cf.packet_received.add_callback( - self._incoming_packet_signal.emit) + self._incoming_packet) self.helper.cf.packet_sent.add_callback( - self._outgoing_packet_signal.emit) + self._outgoing_packet) def disable(self): self.helper.cf.packet_received.remove_callback( - self._incoming_packet_signal.emit) + self._incoming_packet) self.helper.cf.packet_sent.remove_callback( - self._outgoing_packet_signal.emit) + self._outgoing_packet) def preferedDockArea(self): return Qt.RightDockWidgetArea def _save_data(self): - dir = os.path.join(sys.path[1], "logdata") + dir = os.path.join(cfclient.config_path, "logdata") fname = os.path.join(dir, "shark_data.csv") if not os.path.exists(dir): os.makedirs(dir) @@ -119,8 +131,3 @@ class CrtpSharkToolbox(QtGui.QWidget, param_tab_class): for s in self._data: f.write("%s\n" % s) f.close() - - - - - diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/CrtpSharkToolbox.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/CrtpSharkToolbox.pyc deleted file mode 100755 index 15e2f34b5bcbf4cd9cc2eb10b5e248280ac71b27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5286 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 W>ieisfkrDgq0!r3M^nMo%D({$oTxVd diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/DebugDriverToolbox.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/DebugDriverToolbox.py old mode 100755 new mode 100644 index 402b9cbb..d69ddabf --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/DebugDriverToolbox.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/DebugDriverToolbox.py @@ -20,34 +20,33 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Toolbox used to interact with the DebugDriver using a designated port. It's intended to be used for debugging. """ +import struct -__author__ = 'Bitcraze AB' -__all__ = ['DebugDriverToolbox'] - -import time -import sys +from cflib.crtp.crtpstack import CRTPPacket +from cflib.crtp.crtpstack import CRTPPort +from PyQt5 import QtWidgets +from PyQt5 import uic +from PyQt5.QtCore import pyqtSignal +from PyQt5.QtCore import Qt -import struct -from cflib.crtp.crtpstack import CRTPPacket, CRTPPort +import cfclient -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, SIGNAL +__author__ = 'Bitcraze AB' +__all__ = ['DebugDriverToolbox'] debugdriver_tab_class = uic.loadUiType( - sys.path[0] + - "/cfclient/ui/toolboxes/debugDriverToolbox.ui")[0] + cfclient.module_path + + "/ui/toolboxes/debugDriverToolbox.ui")[0] -class DebugDriverToolbox(QtGui.QWidget, debugdriver_tab_class): +class DebugDriverToolbox(QtWidgets.QWidget, debugdriver_tab_class): """Used to interact with the DebugDriver toolbox""" connectionDoneSignal = pyqtSignal(str) disconnectedSignal = pyqtSignal(str) @@ -60,7 +59,7 @@ class DebugDriverToolbox(QtGui.QWidget, debugdriver_tab_class): # Connected / disconnected signals self.helper.cf.connected.add_callback( - self.connectionDoneSignal.emit) + self.connectionDoneSignal.emit) self.connectionDoneSignal.connect(self.connectionDone) self.helper.cf.disconnected.add_callback(self.disconnectedSignal.emit) self.disconnectedSignal.connect(self.disconnected) @@ -69,14 +68,14 @@ class DebugDriverToolbox(QtGui.QWidget, debugdriver_tab_class): self.forceDisconnect.pressed.connect(self.forceDisconnecPressed) def forceDisconnecPressed(self): - if (self.helper.cf.link != None): + if (self.helper.cf.link is not None): p = CRTPPacket() p.set_header(CRTPPort.DEBUGDRIVER, 0) p.data = struct.pack('<B', 1) # Force disconnect self.helper.cf.send_packet(p) def linkQualityChanged(self, value): - if (self.helper.cf.link != None): + if (self.helper.cf.link is not None): p = CRTPPacket() p.set_header(CRTPPort.DEBUGDRIVER, 0) p.data = struct.pack('<BB', 0, value) # Set link quality @@ -106,4 +105,3 @@ class DebugDriverToolbox(QtGui.QWidget, debugdriver_tab_class): def preferedDockArea(self): return Qt.RightDockWidgetArea - diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/DebugDriverToolbox.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/DebugDriverToolbox.pyc deleted file mode 100755 index 8973d533d1112b1d954e0e5d7bcc9435755a2b54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4458 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 GrTQCVMgn30 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/__init__.py old mode 100755 new mode 100644 index 0ab24d41..5919562a --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/__init__.py @@ -21,9 +21,9 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ List all the available toolboxes so they can be used by the UI. @@ -31,29 +31,15 @@ List all the available toolboxes so they can be used by the UI. Dropping a new .py file into this directory will automatically list and load it into the UI when it is started. """ +from .ConsoleToolbox import ConsoleToolbox +from .CrtpSharkToolbox import CrtpSharkToolbox +from .DebugDriverToolbox import DebugDriverToolbox __author__ = 'Bitcraze AB' __all__ = [] -import os -import glob -import logging - -logger = logging.getLogger(__name__) - -foundToolboxes = [os.path.splitext(os.path.basename(f))[0] for f in - glob.glob(os.path.dirname(__file__) + - "/[A-Za-z]*Toolbox.py")] -if len(foundToolboxes) == 0: - foundToolboxes = [os.path.splitext(os.path.basename(f))[0] for f in - glob.glob(os.path.dirname(__file__) + - "/[A-Za-z]*Toolbox.pyc")] - - -logger.debug("Found toolboxes: %s", foundToolboxes) - -toolboxes = [] - -for tb in foundToolboxes: - tbModule = __import__(tb, globals(), locals(), [tb], -1) - toolboxes.append(getattr(tbModule, tb)) +toolboxes = [ + ConsoleToolbox, + CrtpSharkToolbox, + DebugDriverToolbox +] diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/__init__.pyc deleted file mode 100755 index a2c0023e92b9b4013d7f43721d6c8aa271234f13..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1136 zcmb7D&2G~`5FXn}+Pc3qEv1~c5=aqJ>KhUW5UmPQrNV_4kWsPL_9WS`@w(m(ZF<d( z$Kf5g@H$9bVRqw`Qx7=F?94ZR-^@C}uhnq$^V?|#^|L_dOZw@L9zYHdlk_0=pijCF zIei0=0mQ*vZ$R9b>rIH8fK3>-02g3NiHkN78!&7D1~6QLVF<WvU3mj`=r}s>K)f<{ zuFjP;z!e*11Dmk>*@p{+cpY#9aJ@#q_)z`6y?*OI>;JIz3u3zn!#j{KxJEvBcJfWQ zdS&gS^XCw^0k;52Zo`zq?>gCrK2h~yN;}vA+=Sshz+FJn+b|{E1Mi~keW3Nd>nz$0 ze<u;12yGabl9>TA{*?>KQ;EzdB~x{UnrUTS6PEFUrO3t_bCynA_}TG(7#>xsEJe|0 zoE3P<_R9(D3929pV>5+jxu`HRs+zD%L5=v>s1Y|JqplMsUH>9yQt><#W}b)a?3i5+ zuwWJ=8irQ}^ZigS6YWD`vWj0LJ2(`7=y|KR2#r1+bYtGVK7VvNqfcZ6;h?u~@n*VB zp4Vzj1a3xt${y;@eZq}>8IvSeS(2F0=|p~@Dl%s-8i915TuPe;9et@%=aZ`6r>&SJ z3!*t86Dwo)o+JeyA*Hp*uwjJT)RLQlOQn6;h&tFVlY;5r06hokQVN4t#u+Ks=z`a* z-_B8wj@ksaJ{G1)XO8K3M&@QrN86<JU}99N%G86|DY(=%L%JyKnwj*C%EuBN&dU;u z+!3bvxG`0S`oKS--;)^))Ci-rzOJaO)R5i<9ogHP^rXOUMxrpfTTW=RMI=QUWxW{~ zjYV`rH%byw2x3T=>exIRIWjNysEvL=qUE=|mcQcB$6xmYZ`*t9ZF=^65^VS_f7RRb F{sJa%6}A8X diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/consoleToolbox.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/consoleToolbox.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/crtpSharkToolbox.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/crtpSharkToolbox.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/debugDriverToolbox.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/toolboxes/debugDriverToolbox.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/__init__.py old mode 100755 new mode 100644 index 8de7dc26..97dc2b09 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/__init__.py @@ -21,10 +21,13 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Custom widgets used by the user interface. """ + +# This is required to show an hidden import to py2exe +from .hexspinbox import HexSpinBox as _HexSpinBox # noqa diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/__init__.pyc deleted file mode 100755 index 8563898fea878cd9191ad2659176eee65bf93907..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 238 zcmYL@K?=e^3`M89Pzqi_X4!>pE+8VfcVky>hIS^kBb`p^q)0u2NAo&fz!VDx^78*D zge*Us*u7u57IQ^BkK7?<7$L6ANL-S|l<gStX$a(<d{}cs3UUZ&WI0NzanilCEn#03 z8ngJEOy_9DP|A3%RKimH5puRrdxub3(tYtn=z4!gO#vo5R*l6}Gg=C1H&X3eXlx0( f`h_r9m|p><Y->rWjQ7@jc<;O!8a!-S2X65Nq#{3r diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/ai.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/ai.py old mode 100755 new mode 100644 index 39a975fe..926dd826 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/ai.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/ai.py @@ -21,23 +21,26 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Attitude indicator widget. """ +import sys + +from PyQt5 import QtGui +from PyQt5 import QtWidgets, QtCore + __author__ = 'Bitcraze AB' __all__ = ['AttitudeIndicator'] -import sys -from PyQt4 import QtGui, QtCore - -class AttitudeIndicator(QtGui.QWidget): +class AttitudeIndicator(QtWidgets.QWidget): """Widget for showing attitude""" + def __init__(self): super(AttitudeIndicator, self).__init__() @@ -50,27 +53,32 @@ class AttitudeIndicator(QtGui.QWidget): self.setMinimumSize(30, 30) # self.setMaximumSize(240,240) - def setRoll(self, roll): + def setRoll(self, roll, repaint=True): self.roll = roll - self.repaint() + if repaint: + self.repaint() - def setPitch(self, pitch): + def setPitch(self, pitch, repaint=True): self.pitch = pitch - self.repaint() - - def setHover(self, target): + if repaint: + self.repaint() + + def setHover(self, target, repaint=True): self.hoverTargetASL = target - self.hover = target>0 - self.repaint() - - def setBaro(self, asl): - self.hoverASL = asl; - self.repaint() - - def setRollPitch(self, roll, pitch): + self.hover = target > 0 + if repaint: + self.repaint() + + def setBaro(self, asl, repaint=True): + self.hoverASL = asl + if repaint: + self.repaint() + + def setRollPitch(self, roll, pitch, repaint=True): self.roll = roll self.pitch = pitch - self.repaint() + if repaint: + self.repaint() def paintEvent(self, e): qp = QtGui.QPainter() @@ -103,7 +111,7 @@ class AttitudeIndicator(QtGui.QWidget): qp.drawRect(-w, h / 2, 3 * w, 3 * h) pen = QtGui.QPen(QtGui.QColor(255, 255, 255), 1.5, - QtCore.Qt.SolidLine) + QtCore.Qt.SolidLine) qp.setPen(pen) qp.drawLine(-w, h / 2, 3 * w, h / 2) @@ -135,57 +143,56 @@ class AttitudeIndicator(QtGui.QWidget): qp.setWorldMatrixEnabled(False) pen = QtGui.QPen(QtGui.QColor(0, 0, 0), 2, - QtCore.Qt.SolidLine) + QtCore.Qt.SolidLine) qp.setBrush(QtGui.QColor(0, 0, 0)) qp.setPen(pen) qp.drawLine(0, h / 2, w, h / 2) - - - + # Draw Hover vs Target - + qp.setWorldMatrixEnabled(False) - + pen = QtGui.QPen(QtGui.QColor(255, 255, 255), 2, QtCore.Qt.SolidLine) qp.setBrush(QtGui.QColor(255, 255, 255)) qp.setPen(pen) - fh = max(7,h/50) + fh = max(7, h / 50) font = QtGui.QFont('Sans', fh, QtGui.QFont.Light) qp.setFont(font) qp.resetTransform() - - - - - qp.translate(0,h/2) - if not self.hover: - qp.drawText(w-fh*10, fh/2, str(round(self.hoverASL,2))) # asl - - + + qp.translate(0, h / 2) + if not self.hover: + # asl + qp.drawText(w - fh * 10, fh / 2, str(round(self.hoverASL, 2))) + if self.hover: - qp.drawText(w-fh*10, fh/2, str(round(self.hoverTargetASL,2))) # target asl (center) - diff = round(self.hoverASL-self.hoverTargetASL,2) - pos_y = -h/6*diff - + # target asl (center) + qp.drawText( + w - fh * 10, fh / 2, str(round(self.hoverTargetASL, 2))) + diff = round(self.hoverASL - self.hoverTargetASL, 2) + pos_y = -h / 6 * diff + # cap to +- 2.8m - if diff<-2.8: - pos_y = -h/6*-2.8 - elif diff>2.8: - pos_y= -h/6*2.8 + if diff < -2.8: + pos_y = -h / 6 * -2.8 + elif diff > 2.8: + pos_y = -h / 6 * 2.8 else: - pos_y = -h/6*diff - qp.drawText(w-fh*3.8, pos_y+fh/2, str(diff)) # difference from target (moves up and down +- 2.8m) - qp.drawLine(w-fh*4.5,0,w-fh*4.5,pos_y) # vertical line - qp.drawLine(w-fh*4.7,0,w-fh*4.5,0) # left horizontal line - qp.drawLine(w-fh*4.2,pos_y,w-fh*4.5,pos_y) #right horizontal line - - - + pos_y = -h / 6 * diff + + # difference from target (moves up and down +- 2.8m) + qp.drawText(w - fh * 3.8, pos_y + fh / 2, str(diff)) + # vertical line + qp.drawLine(w - fh * 4.5, 0, w - fh * 4.5, pos_y) + # left horizontal line + qp.drawLine(w - fh * 4.7, 0, w - fh * 4.5, 0) + # right horizontal line + qp.drawLine(w - fh * 4.2, pos_y, w - fh * 4.5, pos_y) if __name__ == "__main__": - class Example(QtGui.QWidget): + class Example(QtWidgets.QWidget): def __init__(self): super(Example, self).__init__() @@ -197,54 +204,51 @@ if __name__ == "__main__": def updateRoll(self, roll): self.wid.setRoll((roll / 10.0) - 180.0) - + def updateTarget(self, target): - self.wid.setHover(500+target/10.) + self.wid.setHover(500 + target / 10.) + def updateBaro(self, asl): - self.wid.setBaro(500+asl/10.) - - - def initUI(self): + self.wid.setBaro(500 + asl / 10.) - vbox = QtGui.QVBoxLayout() + def initUI(self): + vbox = QtWidgets.QVBoxLayout() - sld = QtGui.QSlider(QtCore.Qt.Horizontal, self) + sld = QtWidgets.QSlider(QtCore.Qt.Horizontal, self) sld.setFocusPolicy(QtCore.Qt.NoFocus) sld.setRange(0, 3600) sld.setValue(1800) vbox.addWidget(sld) - - + self.wid = AttitudeIndicator() sld.valueChanged[int].connect(self.updateRoll) vbox.addWidget(self.wid) - hbox = QtGui.QHBoxLayout() + hbox = QtWidgets.QHBoxLayout() hbox.addLayout(vbox) - sldPitch = QtGui.QSlider(QtCore.Qt.Vertical, self) + sldPitch = QtWidgets.QSlider(QtCore.Qt.Vertical, self) sldPitch.setFocusPolicy(QtCore.Qt.NoFocus) sldPitch.setRange(0, 180) sldPitch.setValue(90) sldPitch.valueChanged[int].connect(self.updatePitch) hbox.addWidget(sldPitch) - - sldASL = QtGui.QSlider(QtCore.Qt.Vertical, self) + + sldASL = QtWidgets.QSlider(QtCore.Qt.Vertical, self) sldASL.setFocusPolicy(QtCore.Qt.NoFocus) sldASL.setRange(-200, 200) sldASL.setValue(0) sldASL.valueChanged[int].connect(self.updateBaro) - - sldT = QtGui.QSlider(QtCore.Qt.Vertical, self) + + sldT = QtWidgets.QSlider(QtCore.Qt.Vertical, self) sldT.setFocusPolicy(QtCore.Qt.NoFocus) sldT.setRange(-200, 200) sldT.setValue(0) sldT.valueChanged[int].connect(self.updateTarget) - - hbox.addWidget(sldT) + + hbox.addWidget(sldT) hbox.addWidget(sldASL) - self.setLayout(hbox) @@ -253,16 +257,13 @@ if __name__ == "__main__": self.show() def changeValue(self, value): - self.c.updateBW.emit(value) self.wid.repaint() def main(): - - app = QtGui.QApplication(sys.argv) - ex = Example() + app = QtWidgets.QApplication(sys.argv) + Example() sys.exit(app.exec_()) - if __name__ == '__main__': main() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/ai.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/ai.pyc deleted file mode 100755 index 7214cb8692aab93825ea2ad0850495e247bce2a7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8343 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 XqGTf{!fu`^%zt;pn!hpFKVtnCB?^+^ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/hexspinbox.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/hexspinbox.py old mode 100755 new mode 100644 index 82eab2e9..446fa913 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/hexspinbox.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/hexspinbox.py @@ -21,21 +21,24 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ -This class provides a spin box with hexadecimal numbers and arbitrarily length (i.e. not limited by 32 bit). +This class provides a spin box with hexadecimal numbers and arbitrarily length +(i.e. not limited by 32 bit). """ +from PyQt5 import QtGui, QtCore +from PyQt5.QtWidgets import QAbstractSpinBox + __author__ = 'Bitcraze AB' __all__ = ['HexSpinBox'] -from PyQt4 import QtGui, QtCore -from PyQt4.QtGui import QAbstractSpinBox class HexSpinBox(QAbstractSpinBox): + def __init__(self, *args): QAbstractSpinBox.__init__(self, *args) regexp = QtCore.QRegExp('^0x[0-9A-Fa-f]{1,10}$') @@ -63,4 +66,5 @@ class HexSpinBox(QAbstractSpinBox): self.setValue(self._value + steps) def stepEnabled(self): - return QAbstractSpinBox.StepUpEnabled | QAbstractSpinBox.StepDownEnabled + return (QAbstractSpinBox.StepUpEnabled | + QAbstractSpinBox.StepDownEnabled) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/hexspinbox.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/hexspinbox.pyc deleted file mode 100755 index fe4095fa3bfd81eede39080a259b2554c64d7b83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2777 zcmcguU2hvj6urCtNF6AR_y|Zy)jm*gB^;*|A%RduT+&uTikeLuff20MyAx-k^{%x$ zZfr=O$|L`l9{}gvb(~VfW9($E?|gXgoOAA-*~VWtH=iUw94E5;H1Pc$TJ;<z6&b>M zGV~<%Wemrcv>|CzvW85WGHlAECBv3@9BoO~mdS<;H_-RRY{&_I*Oos-UWxoPydmj^ z9CdH-@j1-qvr}6INfuXCFfEH0HZ@fc2i4T(!Kj!A=hmGDr)D0fCb5$^3-Z}yWJ;{b z(;zNK)|GK-vqg}Ze2k@CyJL2Oyl_EgC)SxX7%hVPUj$fqcW1MD3n2&AC1w1Z3HAnV z6a6P<euQv?Vs8J&r|V<PwO|h2<C%4B^&S?b>3W>mVt;Q`A#mcBKU`7A6$7;DDU1Pi z051ej(mZuQlCMsaG;*p%GU>F*ADxXQWi?$K=}1_!mM{brVtb5MJ%Di{XP#V$TzK-Q zC!X`=41qj(<;hE5TvN_ka^bU!MG*q|>L8Fn4nFIk`T+LV-TBYEy|4FrkK*3RFTdaW z{NC=%Pb?-xH4C}YQN1X#xph$#DqR~GISkEse?ASbSgHq(<IJY9D@xbFsu!ysiH*>m z8I6xU0*uK{)QQV+rPP;ZZ06H0=0r_(46lD$OiUk|s*rso&Y4ME)n|8cl3CMBU~*UW zrVDpk<o(Q!`pHQ>*q_<{xlP9gKR{+N)sSgB(?!S~e1=vLpm<x}E$>|~xg?w44>|iD z3|Ks?IR~TQ)d!0NexT_Sk`JY63ActAk^qJ0%-lIXa9ULB!S*(S_0THnC0@d>%ciJ^ z83}^~+CEYc2Nn6)o!|Mf-XT}l2v{7oaB!|&7IzatNZ6yYm>e@-b}{fKj(@3xa&QU- z`OYGsI^6z2oyl~SeVf-RpqOjjC{W0FYY|0}DUpQs3=r=l^#3Bei%H1C0<IGf$dH3t z$*6Wr0WSVMt?4=&DPc%yH5)UVoBh-}$Na2}W5|#P+H2@<v5R*7x^i3Cgi87qeQs8~ zj+b!nY!ph9^A4Q4<Y+H(13lo951_|*V^xF-n{^t#PeVnO1+7s{;<Z2wN#-|bOK7*R z>TZ><A7T1+Xpr&4H$>FR+g@SNt{x>U#LAiJdd?6%j~Q;T;GJ`sr~eV_9Zc3260I+T z%cGH)>l=iE9N|gNr~7$4%1r9W6i2=<&hzEin#FQ_IUu}c_&s*XwRl~=CoHeMJf4^+ z(l>`FniT0QLszekkY}uxQ>dw@iV;^xjl+*&uCh+O>%7bmO+H1dSl?~0)9y6%ui0sK z8V6m?A07iylorVfP&~tZS)yA{#aRZQY4&t+=)Tmuy}t2DmX7V{Ym&+uVr-2NRgiCM T2_D===!!D6eSr11y)FMA2OEBA diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotter.ui b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotter.ui old mode 100755 new mode 100644 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotwidget.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotwidget.py old mode 100755 new mode 100644 index 459be6f6..19a5f46b --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotwidget.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotwidget.py @@ -21,9 +21,9 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Container for the simple plot with functionality for data legend, saving data @@ -32,43 +32,38 @@ and manipulating the plot. For more advanced plotting save the data and use an external application. """ -__author__ = 'Bitcraze AB' -__all__ = ['PlotWidget'] - -from PyQt4 import QtCore, QtGui, uic -from PyQt4.QtCore import Qt, pyqtSlot, pyqtSignal, QThread, QLine, QPoint, QPointF, QSize, QRectF +from PyQt5 import QtWidgets, uic from time import time -import math import logging -logger = logging.getLogger(__name__) +from PyQt5.QtWidgets import QButtonGroup +from PyQt5.QtCore import * # noqa +from PyQt5.QtWidgets import * # noqa +from PyQt5.Qt import * # noqa -import sys +import cfclient -from PyQt4 import Qt, QtCore, QtGui, uic -from PyQt4.QtGui import QButtonGroup -from PyQt4.QtCore import * -from PyQt4.QtGui import * -from PyQt4.Qt import * -from time import time +__author__ = 'Bitcraze AB' +__all__ = ['PlotWidget'] + +logger = logging.getLogger(__name__) -(plot_widget_class, -connect_widget_base_class) = (uic.loadUiType( - sys.path[0] + '/cfclient/ui/widgets/plotter.ui')) +(plot_widget_class, connect_widget_base_class) = ( + uic.loadUiType(cfclient.module_path + '/ui/widgets/plotter.ui')) # Try the imports for PyQtGraph to see if it is installed try: import pyqtgraph as pg from pyqtgraph import ViewBox - from pyqtgraph.Qt import QtCore, QtGui - import pyqtgraph.console - import numpy as np - + import pyqtgraph.console # noqa + import numpy as np # noqa + _pyqtgraph_found = True except Exception: import traceback + logger.warning("PyQtGraph (or dependency) failed to import:\n%s", traceback.format_exc()) _pyqtgraph_found = False @@ -77,14 +72,16 @@ except Exception: # Windows. But for Linux this is not required and might not be installed with # the PyQtGraph package. try: - from scipy.stats import futil - from scipy.sparse.csgraph import _validation - from scipy.special import _ufuncs_cxx + from scipy.stats import futil # noqa + from scipy.sparse.csgraph import _validation # noqa + from scipy.special import _ufuncs_cxx # noqa except Exception: pass + class PlotItemWrapper: """Wrapper for PlotDataItem to handle what data is shown""" + def __init__(self, curve): """Initialize""" self.data = [] @@ -102,13 +99,16 @@ class PlotItemWrapper: self.ts.append(ts) def show_data(self, start, stop): - """Set what data should be shown from the curve. This is done to keep performance when many - points have been added.""" + """ + Set what data should be shown from the curve. This is done to keep + performance when many points have been added. + """ limit = min(stop, len(self.data)) self.curve.setData(y=self.data[start:limit], x=self.ts[start:limit]) - return [self.ts[start], self.ts[limit-1]] + return [self.ts[start], self.ts[limit - 1]] + -class PlotWidget(QtGui.QWidget, plot_widget_class): +class PlotWidget(QtWidgets.QWidget, plot_widget_class): """Wrapper widget for PyQtGraph adding some extra buttons""" def __init__(self, parent=None, fps=100, title="", *args): @@ -129,9 +129,9 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): self._items = {} self._last_item = 0 - self.setSizePolicy(QtGui.QSizePolicy( - QtGui.QSizePolicy.MinimumExpanding, - QtGui.QSizePolicy.MinimumExpanding)) + self.setSizePolicy(QtWidgets.QSizePolicy( + QtWidgets.QSizePolicy.MinimumExpanding, + QtWidgets.QSizePolicy.MinimumExpanding)) self.setMinimumSize(self.minimumSizeHint()) self.parent = parent @@ -143,13 +143,14 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): self._plot_widget.setLabel('bottom', "Time", "ms") self._plot_widget.addLegend() self._plot_widget.getViewBox().disableAutoRange(ViewBox.XAxis) - self._plot_widget.getViewBox().sigRangeChangedManually.connect(self._manual_range_change) + self._plot_widget.getViewBox().sigRangeChangedManually.connect( + self._manual_range_change) self._plot_widget.getViewBox().setMouseEnabled(x=False, y=True) self._plot_widget.getViewBox().setMouseMode(ViewBox.PanMode) self.plotLayout.addWidget(self._plot_widget) - #self.saveToFile.clicked.connect(self.saveToFileSignal) + # self.saveToFile.clicked.connect(self.saveToFileSignal) self._x_min = 0 self._x_max = 500 self._enable_auto_y.setChecked(True) @@ -157,7 +158,8 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): self._last_ts = None self._dtime = None - self._x_range = (float(self._range_x_min.text()), float(self._range_x_max.text())) + self._x_range = ( + float(self._range_x_min.text()), float(self._range_x_max.text())) self._nbr_samples = int(self._nbr_of_samples_x.text()) self._nbr_of_samples_x.valueChanged.connect(self._nbr_samples_changed) @@ -192,7 +194,9 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): """Callback when user changes the X-axis mode""" if box == self._enable_range_x: logger.info("Enable range x") - self._x_range = (float(self._range_x_min.text()), float(self._range_x_max.text())) + self._x_range = ( + float(self._range_x_min.text()), + float(self._range_x_max.text())) else: self._range_x_min.setEnabled(False) self._range_x_max.setEnabled(False) @@ -202,7 +206,9 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): if box == self._enable_range_y: self._range_y_min.setEnabled(True) self._range_y_max.setEnabled(True) - y_range = (float(self._range_y_min.value()), float(self._range_y_max.value())) + y_range = ( + float(self._range_y_min.value()), + float(self._range_y_max.value())) self._plot_widget.getViewBox().setRange(yRange=y_range) else: self._range_y_min.setEnabled(False) @@ -212,8 +218,12 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): self._plot_widget.getViewBox().enableAutoRange(ViewBox.YAxis) def _manual_range_change(self, obj): - """Callback from pyqtplot when users changes the range of the plot using the mouse""" - [[x_min,x_max],[y_min,y_max]] = self._plot_widget.getViewBox().viewRange() + """ + Callback from pyqtplot when users changes the range of the plot using + the mouse + """ + [[x_min, x_max], + [y_min, y_max]] = self._plot_widget.getViewBox().viewRange() self._range_y_min.setValue(y_min) self._range_y_max.setValue(y_max) self._range_y_min.setEnabled(True) @@ -222,7 +232,9 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): def _y_range_changed(self, val): """Callback when user changes Y range manually""" - _y_range = (float(self._range_y_min.value()), float(self._range_y_max.value())) + _y_range = ( + float(self._range_y_min.value()), + float(self._range_y_max.value())) self._plot_widget.getViewBox().setRange(yRange=_y_range, padding=0) def _nbr_samples_changed(self, val): @@ -244,13 +256,15 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): title - the name of the data pen - color of curve (using r for red and so on..) """ - self._items[title] = PlotItemWrapper(self._plot_widget.plot(name=title, pen=pen)) + self._items[title] = PlotItemWrapper( + self._plot_widget.plot(name=title, pen=pen)) def add_data(self, data, ts): """ Add new data to the plot. - data - dictionary sent from logging layer containing variable/value pairs + data - dictionary sent from logging layer containing variable/value + pairs ts - timestamp of the data in ms """ if not self._last_ts: @@ -263,29 +277,41 @@ class PlotWidget(QtGui.QWidget, plot_widget_class): x_max_limit = 0 # We are adding new datasets, calculate what we should show. if self._enable_samples_x.isChecked(): - x_min_limit = max(0, self._last_item-self._nbr_samples) + x_min_limit = max(0, self._last_item - self._nbr_samples) x_max_limit = max(self._last_item, self._nbr_samples) for name in self._items: self._items[name].add_point(data[name], ts) if self._draw_graph and time() > self._ts + self._delay: - [self._x_min, self._x_max] = self._items[name].show_data(x_min_limit, x_max_limit) + [self._x_min, self._x_max] = self._items[name].show_data( + x_min_limit, x_max_limit) if time() > self._ts + self._delay: self._ts = time() - if self._enable_samples_x.isChecked() and self._dtime and self._last_item < self._nbr_samples: + if (self._enable_samples_x.isChecked() and self._dtime and + self._last_item < self._nbr_samples): self._x_max = self._x_min + self._nbr_samples * self._dtime self._last_item = self._last_item + 1 - self._plot_widget.getViewBox().setRange(xRange=(self._x_min, self._x_max)) + self._plot_widget.getViewBox().setRange( + xRange=(self._x_min, self._x_max)) def removeAllDatasets(self): """Reset the plot by removing all the datasets""" for item in self._items: self._plot_widget.removeItem(self._items[item]) - self._plot_widget.plotItem.legend.items = [] + + self._clear_legend() + self._items = {} self._last_item = 0 self._last_ts = None self._dtime = None self._plot_widget.clear() + def _clear_legend(self): + legend = self._plot_widget.plotItem.legend + + while legend.layout.count() > 0: + item = legend.items[0] + name = item[1].text + legend.removeItem(name) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotwidget.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/ui/widgets/plotwidget.pyc deleted file mode 100755 index a6cc6be362d25fd29aa4af50696e22e375fe8247..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10686 zcmcgyOLH98bv`{ac+3zWK!PFxnG~C{Bo1i;kY!4aWX2K+ih7u&$tEO{6FXgv=?2il zevGDjz!^nMoT4g=R8mnTl|}4bHvR>vvR6q}vPk6zWSdPES*9x4WR-m1x!pa0Xt^p2 z0%Bj?d+zJp^SbApJN5sXZ^i%er<+|V{-*H%_wZ%!)<k@f4oXWpmiRT<L8T^sUHpbb zb%`6&X-GUJohgZ@r86xS`=%tCk$6@*vl2I@)0DU+otDH$q;o{#IqA$vJTIMjiH}O> zsKg7>S&(>9I*Vrhv_!`wJ|>-GradFkap@e_eNkVM&XNR6(mNr+3-S~woh-XfN#~T- zXB9nz!f!^hDbcdTE7Dmpo3x1ZCecT2xvITrYWq<Nrlt2S2~J7xwD?D4#h;T?z~U!0 z>70?yOETUp(K#y}TkG=@ot5~Ubk3R0j!N|M0qQB;aJFwt=WIFq73sVx!E4evFZYwT zr4h8{QA-B@XyK1|V)zB=T#(?T^e&3OAi)LceMg>(JgtcpT;jyUk_Y3<y5gcls}iqC zXU*VnOrmv(Uzg77rhQzZ?@IiJblwo_esZkZ???^%aUFk2d{Fv?e2E=I9(KM*kqD-w zcUginvJJs_q3U~+_}y!tq9FYpiq=M&<X)Hr1A99i*!gZ?XJOor0=pljx&1iIckS(A z(#^v(@uDyv>oDKTJv$0^g2caMXWm|z?AV00yu`O-FA4j@$jb@kf?R2>)w+T8<8%<% zp1<cM-N4rl9fc(V9jXg+kzs~$i5-mcV1SKnuiuZtF4jzwwN`cnm|qL??!fyzu&-Xr zTWH_GF84!!C&<J9#b3J)SU!#7ZoYwCbL!9C{DWbbvu7A~+f9yuG69^=;(z_|XZby> zqRVL`+`-=Y42Nv)4g$|NtK0;=%+hz#Fv-mTt==#L?uDNh1Dv3n-)LLhslg(QgWGM^ z94*-45Cw-wnQ?Qd-Mu!<^ECNjkPiC>%8?gC6q21qvEJS8Mq!ZT>%(yUu^u~HC!s;F zwP9%H5b;mL;PJI|)YeU^?Xop=-5G-(1Fyepx4{}e=!2a>(j8y0x4kd|fAZ9ZETn_{ zoz|<FS&~%T9_C?Wnq-8#2f+a2z?yx)A*CjByQ5LQz`cOlM|lw6$A0}_&;>~Uh|x8C z*##5<tQzbYO3185ne9NIYFcSfSqPaD=bln9dlOTN^;9ak$8|^{_aW}P5F`ll<6SRT z>9oVl&UVwsNteVZzYXqAlJ1CnfzwnKOTNHAKopsKN<kHkkCHGCapup#O0rEkOUYGX z$}^RL?r^Xdm^tKh7DU_5GAeC+rpP`;ZGAV5gY~UKme>1(v<HdF)+yTKZE$$iusK`p zkMrF$S&zc4Z{)p^gEfq#IJ<5LL|yj*>KPS5YE7$Yb%`=R5<n0C3Mx2f5C8PcFq#(I zHEq{u$}O<NP$2s~jBeS*-&NnYJ-bgWAjPTedT^+FIizo|ngJCg&j6w(WVsjj?J%+9 ztm-r*bxvXzRWXW7;yW~0N^EC^JrtY10iyQ&=}A-J`M#?s{e3htGF4_44LRAMvMD(| zRB}+XMl=l_K|$F5Cv|Psr3YayyC`FIIR`1{&?%KUw4X{%d7yxmq6^AUm*th68hD{X zHNsZ+0+{Ja#3A3q$hWs(#wqFc_8^5WRBW*~ccBFM=cfrQZfZXYg1!xfgz<;n?owL< z@WV^S6-V^U8MFyDdMiLL2od;e%7d|%qmcY)Q^wS|#t;WeSQI46NELjwl3Ab{YB<Lu z7<SUCKo|zOs#2Dxebu2TjKlnJ6ow2Y#a!y~E*q*b^<`_-G6yp%m3VRBx@rboH%|Rw z#3p&~x_;VqUFSvAoii+6LovZ#YtK>VofFuOCM6@L)7G@roNl(dsOukzt%mjqDhCYh z0)-LsNBdf*<LEaELko}bOIX}#@u#&iL+62zS@CDJ(iFd`l@|Rob{(Pb1=s6K_<wWa z&ns|V{G(bqO5?o<46?USl*ZfGEn~y0I|))o2O@)gq#H2s>@B?$v(U#>D40mMfr7Hb z?*n|<#}GSo8O4Lj!G?X&kUtY+&{Y3u%^+q^jkTXDG|`<Fa54Llz;r^}TpSFl1wNYw zE?!n}GSyRePPKJj@}tsQD9YaAq=KzWD|$?a9_NM%QpI<dBtId&7t{j;GH?uwHV~Sw z+Atet<CD4w9LiIKsAWK7nfw4Jz=Nmt3c9j?$ct>iEzVC%?@Wag=9-R|q<2=Awx8`g zN0x#d;3w!%8l-CK%ev;bt9h?T@6`fJp0gm-Ym^0&?!5N3rFTJBE3TM}``REl2VNrO zSy`2QO((5O?{yvn%NCIDP9Sh^Irt69zo&yQPr3+yvjo0Xp7i?_#=j%I3i@^hedify z{sZpL)voAjSETp5T4`64D$o!2gWlbLR1A5q#Nn!rnyh<Gm%CQ3yHPDtfi6A^y8bNa z{r#W=yJMkh_ZvE@knIn2>kp;(QHk8g+D-9q&qJqf@BI94`1k8~p#)GZ`r2Dw_t6e~ z)5KT%|5$;zLV|t3M|yp4!6Qv$HS3$W@zq0$Gl%|`^Ad{izj1Z6f5e6L5*Xqxa?ldB zqvf43?0*tEL`JU_7cLg9v+D<uH_mBJT)OK!^kv;`MT?8w@FLtd#JB4uZjg9eQD86` z42^s4hHw=#9pXk_mTNobMwmz^{!WUhW2_!}PG9%#1gQJof{PUo<M&5>_?j?Rum?J~ zfNLB;_ZK%J$Fcn(BL<@1_XhCal_LEeb&|0u!m;ge=f{0|(>WsnmrlKFETp2a8~TBX z4l;G~FzKeZ6-0UAqukW6OwWW^sBr%kSwGB3f~&(kb-ZLJa7Z~N`-7{aFv~S440p6| z1J3hK;NS9+p%+DCWkfek5;&(YR6q+Z0(#s5hq+xHU7q1qis<cqCAY6<0E!B`mHL6M zbjM4yPTuf*H@$HR<6fNLzJ@b~#Uq!_gmN2IZ=?h+c<FjLi96P#l61R4_fg>I$B3Tc zwwuAhjDpM^Dc^6y=`pUcGP@EZ`l3pQ?I`tfLw0j8vweef!X5Or9$>?()*TrtsBDtC zia@e8aMSI52q-fNEpXDs5IPNmg4Twv`$iOGH8d<JJyv?C$d3;Y|Ldc?kwaNDD39H( zJaMU<{gTK=gp_3^vCNUjItBE6f7FeJS-2OdLYT{U1L{B;b7>d2fT1Px^?aj!8&U2L zE<HNPn*ajklQ(*tf@6hT6^sV`_idrkra$l=<0w#db2b%%K|rv<9C27h(k0@sZ$yD? zo901XPv<IX%DL^n3Ec89FU*8D*vZ=He(vFg+PVQY%C@<kb<&!z&sohnTsW&yYcg!B zp=~YJmQY)?7Oe$qo};W4>$G*&TB$A78QQUjV^^)^+DY`E#H=O!w^-H67Q(<X{;k5m zSFtss5jca7YBE^X7zWg{Bxy2D!uwDC#CsZtWv^lQ25bZGf=QS`THA&jc9#mdm5%h@ zDB`;BW0sS#cpHVuN@zr<)}O399E$H@_g~>F0^>Pru2xZ`4)_N9`Y22e0I@NNa+97V zd`i%WJ`UstR6#U{xUKL{3<R0T5>oglGm_Zl;8}qZsxOGi7+SUAGZn<WNEAxqYDfl? zIsip!ZZi$&9;|vW+Q_K+K}K~n2G>?4wnw+yw5?8xLak?%?(75uwSr-?ojQ!-ou9Dy zDGP?Q4pJZHdZ+Rm^X-sd`?y5XfTM@QBWlFo<I8vysZr)%hx99-hzP$8eAz#tIKZc& zl3G~>9+jj9pAeIqHq1R)havE`jcaKj7*s;Qx+g04y%{nI!+Hn{;J?GU7vx?IL(ML5 zkPDaA>{7H%lz&8p=O1*(YN<JaUF{v!c?oj){~z8zobX<`J9a1+x7#$i4rEoFfCWQ6 z)iVdVEm5B9HK(_ZbDgjcQIu|kE}|TFJ|UQ^8LNEtS(o7<U4}_U#`#0eU>sarONS#O zF*f{XeA#gn6cL)hi`HoxNwic{=sZ-S@&{;;@ydI0l)U5{0sev6NYSv;kS9hOG*^QN zvScoj>J9k<x?M0E{TeuyZS)^#&r)PS7WPAOiWJ(9fkdU<nxUclN=L|~U#RQZ0cAH@ zoo=h<>p<MhMS4A^yH)7>gs1eS_K^EEOr<!KZ2pu!hmnYhfT++gd!We<la(RS(yg9~ zjB$i$q>UTKn(;-7ns-P>;TAUjS9}@$4XK@1j+5(^Ss+3i9KoST1{8X(j0PVH2sl?l zCVF04axl^8IkeJ;!9X(3Z-9GTI{OaS|7P3#urR^Kk%`969}x{|M&G0~itCUNV}=9P ze#S!8wBn)j$AC>#OuZDSu5mgKRn6#@{2M-#^{id|4c-HTCS!wfjZ8%S3c$aGSj<c& z!*~mK8-%;?jG31#6PUO4Nx|8|GLvh_`Exe$J%7*4$0q-dFQc0z6Ca`SnivdK1_cB- zsOb!Bt3>KOWNLX}^)Pu}HmJ<|vgM`^>2VS!cx=X2E8I3TpoEm#yh(R;A8D8pJ`~bu zAOTOoRh0h&+Zq~8Yf4~HJu}e!sybdG*89|v8m11V-lsJXj&y_rWyuvNU6JDc3(Ts{ ze^s9wNEdx&D4!gD8x4`KElJJPZnYF%74QntO(Q&gffZ)Gwy~<_EfiiXo*;c>AZ<K4 zu3f06su#sXuxcb0Dqi#`3VN&R03zkQ1JFc+9WuxHE5h(Sci}BVJy#F+pV-lGXhwNM zzBKSDZ+?j^jFIB(1^PFrLyZ%Y(8IiU3LvhDW%j8PR18ve$HfVL;^O2g$h*>L%HU7< zHby=JXfD)gS$?Y5EIRf>32X@bpwXVfXXN@%AC<T846oc3xL`Ces8L{QCg0hV!B?7P zGx#6T$$0pG)L;j9C??PInT0pGUiIj3kFwickk7v2zxzld0A<cNu*i9<>OlGz2y#Sq zz(iBAmJCd#JmVvr-9U5`Tqm4m$%#{D%VHVidTXK}GjUOR$B0Bve^bFJX8Hmj@#%6- zE}>t7bCp0+EvOU}@Nduw?OL_{(7fai#&(9}lZo3H8_=0RGL12Y`9S~yd)^>q#%Ns~ zM!WBYgULhP*Iw}obEf+oe9_bUPG5-BR~;3;DnoPUAq)JHMV$L6RA9rbOytx7LdwVa z0sDCas5+Uq6%8SI=Qx*H@F`f|Tbz5WZL*-1RR7l8qm*|O@}Few6bj9!sb}NrQ&ZXY zMyBojB?cXis?K63xCi?D^gpPZ#KTO}(zqYdDIRp-(5@h|U$nkuy=+}VeF3iS8Ae3V zUVYB3^qHX(95RZKK$FhM6QhJ0tQaVCX@!^7XDzu8zk@*Zs>AC}377_mxyo6ALu9N1 z-UCdfSx!;CVZOhJUFjb=0d9usezUj6$O*)${!Rp*lXg&2FeoeBp(C6{b7?GS3pJe* z@HJmAI~r7Nkdx-eC+eDN4%Z0D1J18xN_)Fe;0-4Cqnc*UI2^Vz6=;reHHxkmCtd-& zGUmKQd3l^U8~v{c;Lh_D#Lv0FLJy^{ihFF5wNA|97K?2bK8vqd{56YTu=raPlS69l zdA>ekH%akj%P1(U$8R)en$6}>d{fOvb9S!Tv<*IQVT2w{Gq*1DbGzxFdPaqSpiWnt zKTx^sP`D?*k<lEVcC48n_Lv{iaJZu?KEv89izW*SlB2@KfWbT>P)%Yl-&L=?uzqTL zkTAcgi4sS7z+h4D_-vf1Z7BD}uZT=`mHU)HJq;4b{wLw)xNlw>`rL&=K;bR2_-+^3 z=PYN|tH`LA9a~U{qL;W=ZyL@uv`n_1hp6D7fLXkJ{8+<+S&H-}$pOC_zXYM9n)FQ; zfP~j`BDEWsCkF0=x7BXIG@jDqu{TKgl0m}huL5#67<Dx*pft$3VSl`a*ZMqjcrr~} z7eG8|WWicD)AX#vnA|+3m?{0Bi=WLnYWV3Z>2`Nbw%<Yf5XDsu$`$0!@P7ZpbJ#lj z7{xTKY_oRSdJlRzSDULX;CmUNWlR5CL_YS#dL0%S`Bap1wH7i`w9oTaYpSk+=n2#t IwWXE+1JLb)L;wH) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/__init__.py old mode 100755 new mode 100644 index 8a252d5b..cab62b7c --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/__init__.py @@ -21,9 +21,9 @@ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# You should have received a copy of the GNU General Public License along with +# this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. """ Various utilities used by the user interface. diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/__init__.pyc deleted file mode 100755 index 5859123c9c6fa6c4519f23a61276a26911af398d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 190 zcmYL>!3x4K42C;BC<R|Z>TMvjFCgL*coBBkC2Vbmfo_vFJM6i=c`^mT!2jh-2-&_5 z`g3j@uYOfYze%zd1f^PGr5^RB?3_S1U7~r(W?_oNgkl+k=~u%~ES?NajA`gRT79p} yN8Skl!t4QRQT0bY$!M*M)H^@;NI0=8zq13Ni5S4XR^H3iWt_tj@p=@`67>agpez;u diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config.py old mode 100755 new mode 100644 index e7e09816..2bfe88af --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config.py @@ -29,24 +29,25 @@ """ Gives access for reading and writing application configuration parameters """ - -__author__ = 'Bitcraze AB' -__all__ = ['Config'] - -import sys import json import logging from .singleton import Singleton +import cfclient + +__author__ = 'Bitcraze AB' +__all__ = ['Config'] + logger = logging.getLogger(__name__) -class Config(): + +class Config(metaclass=Singleton): """ Singleton class for accessing application configuration """ - __metaclass__ = Singleton + def __init__(self): """ Initializes the singleton and reads the config files """ - self._dist_config = sys.path[0] + "/cfclient/configs/config.json" - self._config = sys.path[1] + "/config.json" + self._dist_config = cfclient.module_path + "/configs/config.json" + self._config = cfclient.config_path + "/config.json" [self._readonly, self._data] = self._read_distfile() @@ -80,7 +81,7 @@ class Config(): else: raise KeyError("Could not get the parameter [%s]" % key) - if (isinstance(value, unicode)): + if (isinstance(value, str)): value = str(value) return value diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config.pyc deleted file mode 100755 index 484e51ab008a24f203c54cb006c29fea6489473f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3450 zcmcImYi}Dx6rEYWYNsV>D74|#<wKAKYW)QvAu3dwR;3gou|~8tpw(t~>}<N(wRXlS zuG%kzf6NbnbME+&ikFZ`+PS{-*qOQK+{ZM2yVUzKefWK<7Jm)=-bS+(M5fdTQmc_x zS)e9R0+lsX)>K79ji7kFsYcDE-cqBM%J9FfincoLs8L60(^5wll<BHdY|-Oh*#(t# z)UQgND)nTv!7YdVE)RYP(Yv3Y7#k*OYOD>%RUOtQ$?|d%CS?{rt8*v%bXw$T;_|8t z)2bZjlUeP1)1*$0jWf0F*$wP>CwFO`JU8JNcU&9&Jz1Uqj=%j}W1vsrc>WMO7sgfP z3KCA;L9<^$7(fCrAOmH90qoW^gGL9Uw21^qIy8z3Ol^tMB`O^0sc6{maL-R6!qu5! zS|kgDz3u;OX3DDtXk={<&E^nJsUuubs~z0v>I<dfU^&*nSksR+6lRW^#Q(>DdfXD( zmhle9UuyM2tJ=s&n+&2026YLiXn`+6X+MDoAC#aZDe~uF%^jN1E>RT1NS+_}G=<~5 zz(QVD*>@oZ={PNNQ@Vj)U>CnPk8D*6LH4376W(NWU%bW9ayz%KiQj4B4jtFUS#DkI zw{nDeslP^@w~-aRg>WuIRawkkOTJEA;`foIi+yP9Y?>v`^a;6~XiYJ8bg-E<_2Q5| zx=Muo2HN1TIyQrYg#!+zb#-J?2Ls`c^D&IR;Vri}rgL{#m4hNbSi>=Md9eZm3oc;C zIL?7~9N&a4u&CgQz7kvuF6y=xmmnx?dtC7?1YCk_i&vZmB-RD$2reLez6Aez;R_lN z9KnUfCGf$U<okt0{SJScYG)FFdIDuXg9szQDV!7ZIzPabSMexBGd5j<J0pDQ8<`m= zv%<k4=)SeR26-3XE@D_hJsj87aky(OLy|1q5PE1nqdz$)jKq(yP)$u4(E+4Kml36? zl1vCqi^>{_`=XjmOf9o{Ij;HyDI$Mzm9b2K;p99yjOa)Vd)tFh!M5JiJ@A(<StGQ< z92d<mE5J_jK%rK*9+mH_CT{z*r|OTD)*3oO9aCiL7p+RI9)rE1*k*UJML0B0fImr! znF*_Lm@J`Q<;l>7Jhhq?Sy)ys1YYvVdchC7_NRUE{D>@wCq6Xudv#saXK<tuPmK>G zIqy87^wDpeWM|$=1r2>!U()F^De^jk<p~tP;$7Xx!qc{@cNcL1{B|%`4u~YD1I6jP z3w=4grEugcaKmN558Mo4Ro4n$hAx=kW?<}9BJTfpA|`)B1hbmB>wZ-lVI<;E#9(rC ztQ;xWx};2vWWZUOr&VS=V(tuM(GEX*3*y|Ff-Mhlj@^b(K^uO*#TIM@n|d>l%thW- z{y#+L&zTEcfE^fu;zg#U@S^0NYAv}6(`{BS4ZBgYkg+`7lF8O(>pg594wDlje$M>8 z3<_8Iv?V#=ndFVU%ut+i-p&%QJ*h)}nZ+JRfK})tgb6F!qM#j;f0(gMba~m$X2(<O zDSMsku28%I;iF5^5qDuCi_be7N&TY<F{|NY9BX|bZR_huOF{~RXhq5sbmq6$ywKPG zy`1=<T9lJV<u-CyM{?MA%wfz|kJqsh;)r!wIZKUH1zt3?^w_gBut@l-@mD+u`Vk#3 zdKGiA|K883nX+s}?_k9`n?+2Y(N&J2omWwhNOp{7={8JZ2nS$)4T-E3^u-^@NgS7W z)W)%dcN`yA*{on!9yoDUrEwg|Gxm}!#``ys=Ol(XB6TNvn_5Wm0R@j<+a}uo|7wYF zi24Xk3~b|-($?LLZnxX%ZgxBVcs|>r4<Q!TB{MvR>Xmg#QNRqwpN}Kj%wmo=h4<j) sd($I8vyg4RmU18Q1RrHk&fi=qjki2KpI^s`-fSeiE}m%ohlCgW0a|wz5&!@I diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config_manager.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config_manager.py old mode 100755 new mode 100644 index 8da823aa..e61daaae --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config_manager.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config_manager.py @@ -7,7 +7,7 @@ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ # -# Copyright (C) 2013 Bitcraze AB +# Copyright (C) 2013-2017 Bitcraze AB # Copyright (C) 2013 Allyn Bauer # # Crazyflie Nano Quadcopter Client @@ -31,10 +31,6 @@ Manager for loading/accesing input device mappings. """ -__author__ = 'Bitcraze AB/Allyn Bauer' -__all__ = ['ConfigManager'] - -import sys import json import logging import glob @@ -44,15 +40,18 @@ import copy from .singleton import Singleton from cflib.utils.callbacks import Caller +import cfclient + +__author__ = 'Bitcraze AB/Allyn Bauer' +__all__ = ['ConfigManager'] + logger = logging.getLogger(__name__) -class ConfigManager(): +class ConfigManager(metaclass=Singleton): """ Singleton class for managing input processing """ conf_needs_reload = Caller() - configs_dir = sys.path[1] + "/input" - - __metaclass__ = Singleton + configs_dir = cfclient.config_path + "/input" def __init__(self): """Initialize and create empty config list""" @@ -65,7 +64,7 @@ class ConfigManager(): return self._input_config[idx] except: return None - + def get_settings(self, config_name): """Get the settings for an input device.""" try: @@ -87,16 +86,21 @@ class ConfigManager(): json_data = open(self.configs_dir + "/%s" % conf) data = json.load(json_data) new_input_device = {} - new_input_settings = {"updateperiod":10, "springythrottle":True} + new_input_settings = {"updateperiod": 10, + "springythrottle": True} for s in data["inputconfig"]["inputdevice"]: if s == "axis": for a in data["inputconfig"]["inputdevice"]["axis"]: axis = {} axis["scale"] = a["scale"] - axis["offset"] = a["offset"] if "offset" in a else 0.0 + axis["offset"] = a[ + "offset"] if "offset" in a else 0.0 axis["type"] = a["type"] axis["key"] = a["key"] axis["name"] = a["name"] + + self._translate_for_backwards_compatibility(axis) + try: ids = a["ids"] except: @@ -105,13 +109,15 @@ class ConfigManager(): locaxis = copy.deepcopy(axis) if "ids" in a: if id == a["ids"][0]: - locaxis["scale"] = locaxis["scale"] * -1 + locaxis["scale"] = locaxis[ + "scale"] * -1 locaxis["id"] = id # 'type'-'id' defines unique index for axis index = "%s-%d" % (a["type"], id) new_input_device[index] = locaxis else: - new_input_settings[s] = data["inputconfig"]["inputdevice"][s] + new_input_settings[s] = data[ + "inputconfig"]["inputdevice"][s] self._input_config.append(new_input_device) self._input_settings.append(new_input_settings) json_data.close() @@ -119,3 +125,57 @@ class ConfigManager(): except Exception as e: logger.warning("Exception while parsing inputconfig file: %s ", e) return self._list_of_configs + + def save_config(self, input_map, config_name): + """Save a configuration to file""" + mapping = {'inputconfig': {'inputdevice': {'axis': []}}} + + # Create intermediate structure for the configuration file + funcs = {} + for m in input_map: + key = input_map[m]["key"] + if key not in funcs: + funcs[key] = [] + funcs[key].append(input_map[m]) + + # Create a mapping for each axis, take care to handle + # split axis configurations + for a in funcs: + func = funcs[a] + axis = {} + # Check for split axis + if len(func) > 1: + axis["ids"] = [func[0]["id"], func[1]["id"]] + axis["scale"] = func[1]["scale"] + else: + axis["id"] = func[0]["id"] + axis["scale"] = func[0]["scale"] + axis["key"] = func[0]["key"] + axis["name"] = func[0]["key"] # Name isn't used... + axis["type"] = func[0]["type"] + mapping["inputconfig"]["inputdevice"]["axis"].append(axis) + + mapping["inputconfig"]['inputdevice']['name'] = config_name + mapping["inputconfig"]['inputdevice']['updateperiod'] = 10 + + filename = ConfigManager().configs_dir + "/%s.json" % config_name + logger.info("Saving config to [%s]", filename) + json_data = open(filename, 'w') + json_data.write(json.dumps(mapping, indent=2)) + json_data.close() + + self.conf_needs_reload.call(config_name) + + def _translate_for_backwards_compatibility(self, axis): + """Handle changes in the config file format""" + + # The parameter that used to be called 'althold' has been renamed to + # 'assistedControl' + althold = 'althold' + assistedControl = 'assistedControl' + + if axis['key'] == althold: + axis['key'] = assistedControl + + if axis['name'] == althold: + axis['name'] = assistedControl diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config_manager.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/config_manager.pyc deleted file mode 100755 index 51f6358a17701d6345bff2f8a43213c3bd918ffc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3562 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 D7pp8S diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/guiconfig.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/guiconfig.pyc deleted file mode 100755 index c08a5488a3f3fbab088fa8501cfa241ea285020f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1832 zcmcgsO>fjl5G{MYnBgPCqDA6FABbd-5?{C=5L%L51ql=p&t7&AvW(p`ap<u}-R+=3 z;j-D&{xtp$KLB2pop4+2CCp6MbX9j(SG`x&y{|VXt1tilnN#=a;r}-bcLGrm%^?Gt z2ULW##3ZDmM@64ZkLH-*Hz3oe)qv&$3RoYK8PaM*^AQEQM<>@vkLesoC+tHHXaQ#< z`iJP8=&$*8_BM;I@tv<ACI{uIb}Gwr?VMWFR#}}DWwlgURj7})^fF(sO_^uDtSgn* z)uLQBw$;{|%~slL>n83x{Oy%Kx7jDHUhMfX^n<3{mjmTDd=8@kHa~=Dt*t(Sel+tI zS6w2*8}~5WLkJCIkOm|G2{;)>Ba}&>VPVUFl3CQ}BTpdI4Bm|P9I?r|+}bq%JENRA zVK+SXG2By#vyeXb$jihBbRLp@Kt5zUz{XOAya0cn&afw-vmTxIz)%3NLw2$ap=R1E zf2`GMW*V*Pg~~cO)g_MVFdAU1pFotZtenrPTqo=U{^7{mL_icpd&$^K+S)8+%Ll#j z>_cu5uyF`V1RIHPZ!n9G>y?h*cZ9`jTc7CMyO{agEKI3)a)`>io%O~a*HvuF_i?^x zjd9~k<Kksgw)L>P-XwhI4u<3EqHq{&;hS^h94n7~40j3v?mh!N;6!v1(1#(}?QRa^ zJ*-vn#d0Xizss_mk>x4F0eG?fE*SVbAb<cikU5iMxym|n;7oX%MS__yaqvHwaQ8Xn zx-o^SYOj{v5upkduikFEcZU%dui$@JS6XmSi_B+I{V6w7U73w%NM7m9AJ*13;V?X( zYbwB3=!EH$;1X_)gqIRNA!LcT62_!jkk(^d<$i%^Nt=SUX*dl*Uzl^PT@0b`1`Ny^ zdi!NTC~sbE8$00_Ky=CDs-tJrie|Nzu(-@9h!{TsJ54J*Olc~Ol%}h?Xbh{2ZJHK! zo~BZ;$rcRB6yis?SBH3ld*~5{^vEz6hU3wAD`HHOI}ly8S%ZeNm(ga%baPWLmw3MX zuh@Ihio4Q^yKNt~Zv*>#vpMpQcaQvjZM)}#-(#@-8a}j5Zu4~v7yE>c*-wE$*m>6S W@tix%-GUh6xfq8xf+;F*EBp=}d#=s^ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input.pyc deleted file mode 100755 index 3e22bf8fd4eddad80cf08030c3f123c337ac4114..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11733 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 Df1&Vz diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/__init__.py old mode 100755 new mode 100644 index 34d3c4d1..b3edf6ac --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/__init__.py @@ -38,11 +38,6 @@ Windows drivers. The input device's axes and buttons are mapped to software inputs using a configuration file. """ - -__author__ = 'Bitcraze AB' -__all__ = ['JoystickReader'] - -import sys import os import re import glob @@ -50,24 +45,27 @@ import traceback import logging import shutil -import inputreaders as readers -import inputinterfaces as interfaces - -logger = logging.getLogger(__name__) +from . import inputreaders as readers +from . import inputinterfaces as interfaces +import cfclient from cfclient.utils.config import Config from cfclient.utils.config_manager import ConfigManager from cfclient.utils.periodictimer import PeriodicTimer from cflib.utils.callbacks import Caller -import mux -from .mux import InputMux from .mux.nomux import NoMux from .mux.takeovermux import TakeOverMux from .mux.takeoverselectivemux import TakeOverSelectiveMux +__author__ = 'Bitcraze AB' +__all__ = ['JoystickReader'] + +logger = logging.getLogger(__name__) + MAX_THRUST = 65000 + class JoystickReader(object): """ Thread that will read input from devices/joysticks and send control-set @@ -75,9 +73,17 @@ class JoystickReader(object): """ inputConfig = [] + ASSISTED_CONTROL_ALTHOLD = 0 + ASSISTED_CONTROL_POSHOLD = 1 + def __init__(self, do_device_discovery=True): self._input_device = None + self._mux = [NoMux(self), TakeOverSelectiveMux(self), + TakeOverMux(self)] + # Set NoMux as default + self._selected_mux = self._mux[0] + self.min_thrust = 0 self.max_thrust = 0 self._thrust_slew_rate = 0 @@ -87,10 +93,13 @@ class JoystickReader(object): self.max_rp_angle = 0 self.max_yaw_rate = 0 + try: + self.set_assisted_control(Config().get("assistedControl")) + except KeyError: + self.set_assisted_control(JoystickReader.ASSISTED_CONTROL_ALTHOLD) self._old_thrust = 0 self._old_raw_thrust = 0 - self._old_alt_hold = False self.springy_throttle = True self.trim_roll = Config().get("trim_roll") @@ -98,10 +107,6 @@ class JoystickReader(object): self._input_map = None - self._mux = [NoMux(self), TakeOverSelectiveMux(self), TakeOverMux(self)] - # Set NoMux as default - self._selected_mux = self._mux[0] - if Config().get("flightmode") is "Normal": self.max_yaw_rate = Config().get("normal_max_yaw") self.max_rp_angle = Config().get("normal_max_rp") @@ -122,10 +127,9 @@ class JoystickReader(object): self._dev_blacklist = None if len(Config().get("input_device_blacklist")) > 0: self._dev_blacklist = re.compile( - Config().get("input_device_blacklist")) + Config().get("input_device_blacklist")) logger.info("Using device blacklist [{}]".format( - Config().get("input_device_blacklist"))) - + Config().get("input_device_blacklist"))) self._available_devices = {} @@ -133,8 +137,8 @@ class JoystickReader(object): self._read_timer = PeriodicTimer(0.01, self.read_input) if do_device_discovery: - self._discovery_timer = PeriodicTimer(1.0, - self._do_device_discovery) + self._discovery_timer = PeriodicTimer(1.0, + self._do_device_discovery) self._discovery_timer.start() # Check if user config exists, otherwise copy files @@ -142,8 +146,8 @@ class JoystickReader(object): logger.info("No user config found, copying dist files") os.makedirs(ConfigManager().configs_dir) - for f in glob.glob(sys.path[0] + - "/cfclient/configs/input/[A-Za-z]*.json"): + for f in glob.glob( + cfclient.module_path + "/configs/input/[A-Za-z]*.json"): dest = os.path.join(ConfigManager(). configs_dir, os.path.basename(f)) if not os.path.isfile(dest): @@ -153,11 +157,12 @@ class JoystickReader(object): ConfigManager().get_list_of_configs() self.input_updated = Caller() + self.assisted_input_updated = Caller() self.rp_trim_updated = Caller() self.emergency_stop_updated = Caller() self.device_discovery = Caller() self.device_error = Caller() - self.althold_updated = Caller() + self.assisted_control_updated = Caller() self.alt1_updated = Caller() self.alt2_updated = Caller() @@ -175,10 +180,6 @@ class JoystickReader(object): """Set if altitude hold is available or not (depending on HW)""" self.has_pressure_sensor = available - def enable_alt_hold(self, althold): - """Enable or disable altitude hold""" - self._old_alt_hold = althold - def _do_device_discovery(self): devs = self.available_devices() @@ -207,6 +208,12 @@ class JoystickReader(object): logger.info("Selected MUX: {}".format(self._selected_mux.name)) + def set_assisted_control(self, mode): + self._assisted_control = mode + + def get_assisted_control(self): + return self._assisted_control + def available_devices(self): """List all available and approved input devices. This function will filter available devices by using the @@ -216,13 +223,13 @@ class JoystickReader(object): approved_devs = [] for dev in devs: - if ((not self._dev_blacklist) or - (self._dev_blacklist and not - self._dev_blacklist.match(dev.name))): + if ((not self._dev_blacklist) or + (self._dev_blacklist and + not self._dev_blacklist.match(dev.name))): dev.input = self approved_devs.append(dev) - return approved_devs + return approved_devs def enableRawReading(self, device_name): """ @@ -246,7 +253,7 @@ class JoystickReader(object): """Return the saved mapping for a given device""" config = None device_config_mapping = Config().get("device_config_mapping") - if device_name in device_config_mapping.keys(): + if device_name in list(device_config_mapping.keys()): config = device_config_mapping[device_name] logging.debug("For [{}] we recommend [{}]".format(device_name, config)) @@ -260,7 +267,8 @@ class JoystickReader(object): def read_raw_values(self): """ Read raw values from the input device.""" - [axes, buttons, mapped_values] = self._input_device.read(include_raw=True) + [axes, buttons, mapped_values] = self._input_device.read( + include_raw=True) dict_axes = {} dict_buttons = {} @@ -294,7 +302,7 @@ class JoystickReader(object): config_name. Returns True if device supports mapping, otherwise False """ try: - #device_id = self._available_devices[device_name] + # device_id = self._available_devices[device_name] # Check if we supplied a new map, if not use the preferred one device = self._get_device_from_name(device_name) self._selected_mux.add_device(device, role) @@ -306,19 +314,19 @@ class JoystickReader(object): return device.supports_mapping except Exception: self.device_error.call( - "Error while opening/initializing input device\n\n%s" % - (traceback.format_exc())) + "Error while opening/initializing input device\n\n%s" % + (traceback.format_exc())) if not self._input_device: self.device_error.call( - "Could not find device {}".format(device_name)) + "Could not find device {}".format(device_name)) return False def resume_input(self): self._selected_mux.resume() self._read_timer.start() - def pause_input(self, device_name = None): + def pause_input(self, device_name=None): """Stop reading from the input device.""" self._read_timer.stop() self._selected_mux.pause() @@ -339,12 +347,24 @@ class JoystickReader(object): data = self._selected_mux.read() if data: - if data.toggled.althold: + if data.toggled.assistedControl: + if self._assisted_control == \ + JoystickReader.ASSISTED_CONTROL_POSHOLD: + if data.assistedControl: + for d in self._selected_mux.devices(): + d.limit_thrust = False + d.limit_rp = False + else: + for d in self._selected_mux.devices(): + d.limit_thrust = True + d.limit_rp = True try: - self.althold_updated.call(str(data.althold)) + self.assisted_control_updated.call( + data.assistedControl) except Exception as e: - logger.warning("Exception while doing callback from" - "input-device for althold: {}".format(e)) + logger.warning( + "Exception while doing callback from input-device " + "for assited control: {}".format(e)) if data.toggled.estop: try: @@ -366,41 +386,53 @@ class JoystickReader(object): logger.warning("Exception while doing callback from" "input-device for alt2: {}".format(e)) - # Update the user roll/pitch trim from device - if data.toggled.pitchNeg and data.pitchNeg: - self.trim_pitch -= 1 - if data.toggled.pitchPos and data.pitchPos: - self.trim_pitch += 1 - if data.toggled.rollNeg and data.rollNeg: - self.trim_roll -= 1 - if data.toggled.rollPos and data.rollPos: - self.trim_roll += 1 - - if data.toggled.pitchNeg or data.toggled.pitchPos or \ - data.toggled.rollNeg or data.toggled.rollPos: - self.rp_trim_updated.call(self.trim_roll, self.trim_pitch) - - # Thrust might be <0 here, make sure it's not otherwise we'll - # get an error. - if data.thrust < 0: - data.thrust = 0 - if data.thrust > 0xFFFF: - data.thrust = 0xFFFF - - # If we are using alt hold the data is not in a percentage - if not data.althold: - data.thrust = JoystickReader.p2t(data.thrust) - - self.input_updated.call(data.roll + self.trim_roll, - data.pitch + self.trim_pitch, - data.yaw, data.thrust) + if self._assisted_control == \ + JoystickReader.ASSISTED_CONTROL_POSHOLD \ + and data.assistedControl: + vx = data.roll + vy = data.pitch + vz = data.thrust + yawrate = data.yaw + # The odd use of vx and vy is to map forward on the + # physical joystick to positiv X-axis + self.assisted_input_updated.call(vy, -vx, vz, yawrate) + else: + # Update the user roll/pitch trim from device + if data.toggled.pitchNeg and data.pitchNeg: + self.trim_pitch -= 1 + if data.toggled.pitchPos and data.pitchPos: + self.trim_pitch += 1 + if data.toggled.rollNeg and data.rollNeg: + self.trim_roll -= 1 + if data.toggled.rollPos and data.rollPos: + self.trim_roll += 1 + + if data.toggled.pitchNeg or data.toggled.pitchPos or \ + data.toggled.rollNeg or data.toggled.rollPos: + self.rp_trim_updated.call(self.trim_roll, + self.trim_pitch) + + # If we are using alt hold the data is not in a percentage + if not data.assistedControl: + data.thrust = JoystickReader.p2t(data.thrust) + + # Thrust might be <0 here, make sure it's not otherwise + # we'll get an error. + if data.thrust < 0: + data.thrust = 0 + if data.thrust > 0xFFFF: + data.thrust = 0xFFFF + + self.input_updated.call(data.roll + self.trim_roll, + data.pitch + self.trim_pitch, + data.yaw, data.thrust) else: self.input_updated.call(0, 0, 0, 0) except Exception: logger.warning("Exception while reading inputdevice: %s", traceback.format_exc()) self.device_error.call("Error reading from input device\n\n%s" % - traceback.format_exc()) + traceback.format_exc()) self.input_updated.call(0, 0, 0, 0) self._read_timer.stop() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/__init__.pyc deleted file mode 100755 index 9b26a5bbbc2cbee07572abccdebf8393c0943072..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13812 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 HjoJSTv2EBl diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/__init__.py old mode 100755 new mode 100644 index c27e0157..907ba867 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/__init__.py @@ -31,49 +31,55 @@ Find all the available input interfaces and try to initialize them. """ -__author__ = 'Bitcraze AB' -__all__ = ['InputInterface'] - -import os -import glob import logging from ..inputreaderinterface import InputReaderInterface +__author__ = 'Bitcraze AB' +__all__ = ['InputInterface'] + logger = logging.getLogger(__name__) -found_interfaces = [os.path.splitext(os.path.basename(f))[0] for - f in glob.glob(os.path.dirname(__file__) + "/[A-Za-z]*.py")] -if len(found_interfaces) == 0: - found_interfaces = [os.path.splitext(os.path.basename(f))[0] for - f in glob.glob(os.path.dirname(__file__) + - "/[A-Za-z]*.pyc")] +# Force py2exe to include interfaces module in the build +try: + from . import leapmotion # noqa + from . import wiimote # noqa + from . import zmqpull # noqa +except Exception: + pass + +# Statically listing input interfaces +input_interface = ["leapmotion", + "wiimote", + "zmqpull"] -logger.info("Found interfaces: {}".format(found_interfaces)) +logger.info("Found interfaces: {}".format(input_interface)) initialized_interfaces = [] available_interfaces = [] -for interface in found_interfaces: +for interface in input_interface: try: - module = __import__(interface, globals(), locals(), [interface], -1) + module = __import__(interface, globals(), locals(), [interface], 1) main_name = getattr(module, "MODULE_MAIN") initialized_interfaces.append(getattr(module, main_name)()) logger.info("Successfully initialized [{}]".format(interface)) except Exception as e: logger.info("Could not initialize [{}]: {}".format(interface, e)) + def devices(): # Todo: Support rescanning and adding/removing devices if len(available_interfaces) == 0: for reader in initialized_interfaces: devs = reader.devices() for dev in devs: - available_interfaces.append(InputInterface(dev["name"], - dev["id"], - reader)) + available_interfaces.append(InputInterface( + dev["name"], dev["id"], reader)) return available_interfaces + class InputInterface(InputReaderInterface): + def __init__(self, dev_name, dev_id, dev_reader): super(InputInterface, self).__init__(dev_name, dev_id, dev_reader) @@ -95,7 +101,7 @@ class InputInterface(InputReaderInterface): def read(self, include_raw=False): mydata = self._reader.read(self.id) # Merge interface returned data into InputReader Data Item - for key in mydata.keys(): + for key in list(mydata.keys()): self.data.set(key, mydata[key]) - return self.data \ No newline at end of file + return self.data diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/__init__.pyc deleted file mode 100755 index 0b8ff01cd5178a884db66a9b124ccbe1efb1dace..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3290 zcmd5;-EJFI5T3Jk?AmdD`je(^8gR=67AUoZxB($V+BBlHO{I+>bW2!mc8{HP*SpT{ zacj59Rr(NI@;bZ$uYq^~_-1zP1R*ZqqQUYR&zUo4{%4L$zc19k_8)!cQ}L<d_baUI zH$@Z>Ie>~BMS(><AQlBB3d$6f$N`e$Wpc_>e2$zs3h=E^RG~qYoGK|jNBv8rYjg?` zb?Oo6GWE-(OVppIeuMM^9|cuf#n0A$o1Dez;nEaYCcVg9%y@~KKU#D&Cg(EgE2J+M z)E5?|HT943YyVRIuPi@?wRP%Wr2z0+p$kT^8fS%_ajw(&XFk~4|B0Mcn)sw|kX|L- zq*L6!DR7koh=`pcL~EpPkzS)<o=z=t)=95W|Gk2!*O`cmtfWxg5Y?-N|7!2(6IIsl z(~CN#zbNIjW{e93qi%^1NC4~iSbM=Dy@jo}IhDFfT^O^(6exP;+~K6|wwF2e+W__L zFb-N?6t&EuZh0@gF!Bx}-3sI3$N(Chc0FHbEe~uaowQ5>YG^_)3SVo!G`L%@XY&ws zFEoDYfw+0kEMotVMLe8J2>-xmC$w<TM#+)6Hf6E37wB}xm@VL-^L%r|@it!Xe{^>^ z2|=KYMgE2CXDnhn8NsqMLqBi5IWcU`lc!tXK7Qan*?hQ@tz*AC^5I9;9YxXPoC`tg z`J0n{;kciSqM#Kg?Dxz=K4qEGIVH%cV%^8e4gn0ld8I1inha?Cl#GP}*`gDoW1>C^ zf#^ihxI@QW^B>ZQ#h1_)W{!^0Xcjg3r-UD53H*{w+B<5}9*PpYyX`WR?MNUDqp>&8 zP(u_3?F!q$mPI<2sLrzJo`uC+XXcq(!TBThD9|rMgvYQjZ#dL(U<0Ez%N1fOSrX;o z%|s!Pws0}XG(hJt8R*VIQ3;)4n)J1AvJMx<q#K2L!v}~>wlSQT!zAuR;X%jm=ETm( zgi+R!(#zqQ{T&w;hsJeL5B4Q!+GLen#$;Vl3#x&&tg327`Ap*vhvyzv)&YQVJlsfH z1Ho2;V60h!U_@b*mFO+zR)y?5-abcqy6&^2CjfcMIa3z(EzT*DcZ{r+NFgdXaLc^! zBe}o<fmZ|v1YQ-q%Es(UE9|t{Aru2NjD|Xu$Q!0jotCq0FUqu$&K(VhNoq28fK-KX zPk5tnfcT_C)4;`iV-C|%W=w5Hn0T+Gk|d3pj=FLaX>_HaIQhH@15+>1Jna{fWo~#5 zc*eGnx>c%`8_2WI(}Nf1SF*AS1flNZi(~*|sG^0=#aF7B%iKLz#tEw2=JZMuY#t^T z;%5_zpJ8R}5dCNW>>Ic(h2lp^rvDF~-GoIyU`;(^2RYze>5{o`fc!mkn2+O+xvTQo zxwXGeC(>9LncP*trQ@3DKy`G7_E-eJYFrgNG7s}$ur5xx#6oKRg`Q;j4D*a9GYl;y zEg|`rha-&rXcTBS^<K&38%%;JGp=7qiLAj97c1kTKx)Ohs@AMF7j!WuxP4t$y4H0E zNid4AwYh_AE-#xiVJ|UYQD;5~_6{dEl+$A@aipSZjasQzYJUKVk@j?h#Gm=$jqpUI z*ycz0lLDM;D9Ll!i;@F5i;`ZC#~`<`ydHU%&t4Ck3q!_WPn*YJ#*DqgBp!HtS*KDI zL(d$Fz#vRzAab}}w;OUa@eC8?12Y>&q0wU_!9VaaEzCTbyZmqD+}mn%sf+9|?k1wI zo1_EJ*zA)nPdAU}nW;qz!vPQY!gcl&v%j#`pQ3r1#a_7O8Iy{O122qaoZBo|NDs!o z9-1(T#Ro0#Xa2l{<6JeoyF!r2eUW?cWeY}Rp8`}Yl!V1YzM+<_C99+!sVl04NBuMF VI?gKA0(Q66l4`1(fVZvM{GX*Q`(*$C diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/leapmotion.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/leapmotion.py old mode 100755 new mode 100644 index 80c76d07..b21e7097 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/leapmotion.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/leapmotion.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# || ____ _ __ -# +------+ / __ )(_) /_______________ _____ ___ +# || ____ _ __ +# +------+ / __ )(_) /_______________ _____ ___ # | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ @@ -15,7 +15,7 @@ # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -28,27 +28,27 @@ """ Leap Motion reader for controlling the Crazyflie. Note that this reader needs -the Leap Motion SDK to be manually copied. See lib/leapsdk/__init__.py for +the Leap Motion SDK to be manually copied. See src/leapsdk/__init__.py for more info. """ -__author__ = 'Bitcraze AB' -__all__ = ['LeapmotionReader'] - try: import leapsdk.Leap as Leap - from leapsdk.Leap import CircleGesture, KeyTapGesture, ScreenTapGesture, SwipeGesture except Exception as e: - raise Exception("Leap Motion library probably not installed ({})".format(e)) + raise Exception( + "Leap Motion library probably not installed ({})".format(e)) import logging -import time + +__author__ = 'Bitcraze AB' +__all__ = ['LeapmotionReader'] logger = logging.getLogger(__name__) MODULE_MAIN = "LeapmotionReader" MODULE_NAME = "Leap Motion" + class LeapListener(Leap.Listener): def set_data_callback(self, callback): @@ -75,8 +75,6 @@ class LeapListener(Leap.Listener): # Get the most recent frame and report some basic information frame = controller.frame() data = {"roll": 0, "pitch": 0, "yaw": 0, "thrust": 0} - #logger.info("Frame id: %d, timestamp: %d, hands: %d, fingers: %d, tools: %d, gestures: %d" % ( - # frame.id, frame.timestamp, len(frame.hands), len(frame.fingers), len(frame.tools), len(frame.gestures()))) if not frame.hands.is_empty: # Get the first hand hand = frame.hands[0] @@ -89,7 +87,8 @@ class LeapListener(Leap.Listener): data["roll"] = -direction.pitch * Leap.RAD_TO_DEG / 30.0 data["pitch"] = -normal.roll * Leap.RAD_TO_DEG / 30.0 data["yaw"] = direction.yaw * Leap.RAD_TO_DEG / 70.0 - data["thrust"] = (hand.palm_position[1] - 80)/150.0 # Use the elevation of the hand for thrust + # Use the elevation of the hand for thrust + data["thrust"] = (hand.palm_position[1] - 80) / 150.0 if data["thrust"] < 0.0: data["thrust"] = 0.0 @@ -98,10 +97,12 @@ class LeapListener(Leap.Listener): self._dcb(data) + class LeapmotionReader: """Used for reading data from input devices using the PyGame API.""" + def __init__(self): - #pygame.init() + # pygame.init() self._ts = 0 self._listener = LeapListener() self._listener.set_data_callback(self.leap_callback) @@ -115,18 +116,20 @@ class LeapmotionReader: self.data = {"roll": 0.0, "pitch": 0.0, "yaw": 0.0, "thrust": -1.0, "estop": False, "exit": False, - "althold": False, "alt1": False, "alt2": False, + "assistedControl": False, "alt1": False, "alt2": False, "pitchNeg": False, "rollNeg": False, "pitchPos": False, "rollPos": False} logger.info("Initialized Leap") def open(self, deviceId): - """Initialize the reading and open the device with deviceId and set the mapping for axis/buttons using the - inputMap""" + """ + Initialize the reading and open the device with deviceId and set the + mapping for axis/buttons using the inputMap + """ return def leap_callback(self, data): - for k in data.keys(): + for k in list(data.keys()): self.data[k] = data[k] def read(self, id): @@ -141,9 +144,8 @@ class LeapmotionReader: dev = [] # According to API doc only 0 or 1 devices is supported - #logger.info("Devs: {}".format(self._controller.is_connected)) + # logger.info("Devs: {}".format(self._controller.is_connected)) if self._controller.is_connected: dev.append({"id": 0, "name": "Leapmotion"}) - - return dev + return dev diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/leapmotion.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/leapmotion.pyc deleted file mode 100755 index 7715c47e3d587d68a8815f5c15244d4fe9273e17..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6071 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 SdpK6Hjp){{qOVn3ee>Tc@~4yl diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/wiimote.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/wiimote.py old mode 100755 new mode 100644 index 290e9628..693ea836 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/wiimote.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/wiimote.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- import logging from threading import Thread import time @@ -12,6 +13,7 @@ logger = logging.getLogger(__name__) MODULE_MAIN = "WiimoteReader" MODULE_NAME = "WII" + class _Reader(object): # needs attributes: # - name @@ -19,15 +21,21 @@ class _Reader(object): # - limit_thrust # - limit_yaw # - open + def devices(self): """List all the available connections""" raise NotImplemented() + def open(self, device_id): - """Initialize the reading and open the device with deviceId and set the mapping for axis/buttons using the - inputMap""" + """ + Initialize the reading and open the device with deviceId and set the + mapping for axis/buttons using the inputMap + """ return + def close(self, device_id): return + def read(self, device_id): """Read input from the selected device.""" raise NotImplemented() @@ -47,6 +55,7 @@ PLUS = 4096 class HandleWiimote(Thread): + def __init__(self, reader, wii, *args): super(HandleWiimote, self).__init__(*args) self.reader = reader @@ -90,9 +99,9 @@ class HandleWiimote(Thread): self.reader.data['thrust'] = -1 if button: - sample = max(max_sample, sample/3) + sample = max(max_sample, sample / 3) else: - sample = min(min_sample, sample*3) + sample = min(min_sample, sample * 3) self.adjust() time.sleep(sample) @@ -112,6 +121,7 @@ class HandleWiimote(Thread): else: self.reader.data['roll'] = 0 + class WiimoteReader(_Reader): name = MODULE_NAME @@ -120,14 +130,14 @@ class WiimoteReader(_Reader): self.limit_thrust = False self.limit_yaw = False - print "Press 1 + 2 to connect wii" + print("Press 1 + 2 to connect wii") time.sleep(1) self.wm = cwiid.Wiimote() self.wm.rpt_mode = cwiid.RPT_BTN logger.info("FOUND WIIMOTE") self.data = {"roll": 0.0, "pitch": 0.0, "yaw": 0.0, "thrust": -1.0, "estop": False, "exit": False, - "althold": False, "alt1": False, "alt2": False, + "assistedControl": False, "alt1": False, "alt2": False, "pitchNeg": False, "rollNeg": False, "pitchPos": False, "rollPos": False} self.wii_thread = HandleWiimote(self, self.wm) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/wiimote.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/wiimote.pyc deleted file mode 100755 index a7367d572ff1f96996c426106d5de2b58bd85b78..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6087 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/zmqpull.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/zmqpull.py old mode 100755 new mode 100644 index f12f702d..0ff0e6bc --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/zmqpull.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/zmqpull.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# || ____ _ __ -# +------+ / __ )(_) /_______________ _____ ___ +# || ____ _ __ +# +------+ / __ )(_) /_______________ _____ ___ # | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ @@ -15,7 +15,7 @@ # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the @@ -30,22 +30,21 @@ Input interface that supports receiving commands via ZMQ. """ -__author__ = 'Bitcraze AB' -__all__ = ['ZMQReader'] +import logging +from threading import Thread + +from cfclient.utils.config import Config try: import zmq except Exception as e: raise Exception("ZMQ library probably not installed ({})".format(e)) -from cfclient.utils.config import Config if not Config().get("enable_zmq_input"): raise Exception("ZMQ input disabled in config file") -import logging -import time -import pprint -from threading import Thread +__author__ = 'Bitcraze AB' +__all__ = ['ZMQReader'] ZMQ_PULL_PORT = 1024 + 188 @@ -54,6 +53,7 @@ logger = logging.getLogger(__name__) MODULE_MAIN = "ZMQReader" MODULE_NAME = "ZMQ" + class _PullReader(Thread): def __init__(self, receiver, callback, *args): @@ -66,8 +66,10 @@ class _PullReader(Thread): while True: self._cb(self._receiver.recv_json()) + class ZMQReader: """Used for reading data from input devices using the PyGame API.""" + def __init__(self): context = zmq.Context() receiver = context.socket(zmq.PULL) @@ -85,7 +87,7 @@ class ZMQReader: self.data = {"roll": 0.0, "pitch": 0.0, "yaw": 0.0, "thrust": -1.0, "estop": False, "exit": False, - "althold": False, "alt1": False, "alt2": False, + "assistedControl": False, "alt1": False, "alt2": False, "pitchNeg": False, "rollNeg": False, "pitchPos": False, "rollPos": False} @@ -95,12 +97,14 @@ class ZMQReader: self._receiver_thread.start() def _cmd_callback(self, cmd): - for k in cmd["ctrl"].keys(): + for k in list(cmd["ctrl"].keys()): self.data[k] = cmd["ctrl"][k] def open(self, device_id): - """Initialize the reading and open the device with deviceId and set the mapping for axis/buttons using the - inputMap""" + """ + Initialize the reading and open the device with deviceId and set the + mapping for axis/buttons using the inputMap + """ return def read(self, device_id): @@ -116,4 +120,3 @@ class ZMQReader: # As a temporary workaround we always say we have ZMQ # connected. If it's not connected, there's just no data. return [{"id": 0, "name": "ZMQ@{}".format(self._bind_addr)}] - diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/zmqpull.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputinterfaces/zmqpull.pyc deleted file mode 100755 index e1193a55587204f671f4fe287d21eeaa117ab9f1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4432 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 G_J0AuhZ}DI diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaderinterface.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaderinterface.py old mode 100755 new mode 100644 index 7e41cd73..d6bb14c1 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaderinterface.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaderinterface.py @@ -37,6 +37,7 @@ logger = logging.getLogger(__name__) class _ToggleState(dict): + def __getattr__(self, attr): return self.get(attr) @@ -45,11 +46,12 @@ class _ToggleState(dict): class InputData: + def __init__(self): - #self._toggled = {} + # self._toggled = {} self._axes = ("roll", "pitch", "yaw", "thrust") self._buttons = ("alt1", "alt2", "estop", "exit", "pitchNeg", - "pitchPos", "rollNeg", "rollPos", "althold", + "pitchPos", "rollNeg", "rollPos", "assistedControl", "muxswitch") for axis in self._axes: self.__dict__[axis] = 0.0 @@ -64,7 +66,7 @@ class InputData: return self._axes + self._buttons def _check_toggle(self, key, data): - if not key in self._prev_btn_values: + if key not in self._prev_btn_values: self._prev_btn_values[key] = data elif self._prev_btn_values[key] != data: self._prev_btn_values[key] = data @@ -95,6 +97,7 @@ class InputData: class InputReaderInterface(object): + def __init__(self, dev_name, dev_id, dev_reader): """Initialize the reader""" # Set if the device supports mapping and can be configured @@ -122,7 +125,6 @@ class InputReaderInterface(object): # Stateful things self._old_thrust = 0 self._old_raw_thrust = 0 - self._old_alt_hold = False self._prev_thrust = 0 self._last_time = 0 @@ -159,14 +161,16 @@ class InputReaderInterface(object): return [self._cap_rp(roll), self._cap_rp(pitch)] def _scale_and_deadband_yaw(self, yaw): - return InputReaderInterface.deadband(yaw, 0.2) * self.input.max_yaw_rate + return (InputReaderInterface.deadband(yaw, 0.2) * + self.input.max_yaw_rate) - def _limit_thrust(self, thrust, althold, emergency_stop): + def _limit_thrust(self, thrust, assisted_control, emergency_stop): # Thust limiting (slew, minimum and emergency stop) if self.input.springy_throttle: - if althold and self.input.has_pressure_sensor: - thrust = int(round(InputReaderInterface.deadband(thrust, 0.2) - * 32767 + 32767)) # Convert to uint16 + if assisted_control and self.input.get_assisted_control() == \ + self.input.ASSISTED_CONTROL_ALTHOLD: + thrust = int(round(InputReaderInterface.deadband(thrust, 0.2) * + 32767 + 32767)) # Convert to uint16 else: # Scale the thrust to percent (it's between 0 and 1) thrust *= 100 @@ -190,8 +194,8 @@ class InputReaderInterface(object): else: # If we are "inside" the limit, then lower # according to the rate we have set each iteration - lowering = (time() - self._last_time) * \ - self.input.thrust_slew_rate + lowering = ((time() - self._last_time) * + self.input.thrust_slew_rate) limited_thrust = self._prev_thrust - lowering elif emergency_stop or thrust < self.thrust_stop_limit: # If the thrust have been pulled down or the @@ -214,7 +218,8 @@ class InputReaderInterface(object): thrust = limited_thrust else: thrust = thrust / 2 + 0.5 - if althold and self.input.has_pressure_sensor: + if assisted_control and self.input.get_assisted_control() == \ + self.input.ASSISTED_CONTROL_ALTHOLD: thrust = 32767 else: if thrust < -0.90 or emergency_stop: @@ -224,14 +229,14 @@ class InputReaderInterface(object): self.input.max_thrust - self.input.min_thrust) if (self.input.thrust_slew_enabled and - self.input.thrust_slew_limit > thrust and not - emergency_stop): + self.input.thrust_slew_limit > thrust and not + emergency_stop): if self._old_thrust > self.input.thrust_slew_limit: self._old_thrust = self.input.thrust_slew_limit if thrust < (self._old_thrust - - (self.input.thrust_slew_rate / 100)): - thrust = self._old_thrust - \ - self.input.thrust_slew_rate / 100 + self.input.thrust_slew_rate / 100): + thrust = (self._old_thrust - + self.input.thrust_slew_rate / 100) if thrust < -1 or thrust < self.input.min_thrust: thrust = 0 @@ -239,14 +244,6 @@ class InputReaderInterface(object): self._old_raw_thrust = thrust return thrust - def set_alt_hold_available(self, available): - """Set if altitude hold is available or not (depending on HW)""" - self.input._has_pressure_sensor = available - - def enable_alt_hold(self, althold): - """Enable or disable altitude hold""" - self._old_alt_hold = althold - @staticmethod def deadband(value, threshold): if abs(value) < threshold: @@ -255,4 +252,4 @@ class InputReaderInterface(object): value -= threshold elif value < 0: value += threshold - return value / (1 - threshold) \ No newline at end of file + return value / (1 - threshold) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaderinterface.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaderinterface.pyc deleted file mode 100755 index b768cf698b267463801adcd5ac995978e6ad369c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8721 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 N0_wbfZ2IV>{{p8c|JMKj diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/__init__.py old mode 100755 new mode 100644 index 11d1a8fe..978132fb --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/__init__.py @@ -33,37 +33,41 @@ To create a new input device reader drop a .py file into this directory and it will be picked up automatically. """ -__author__ = 'Bitcraze AB' -__all__ = ['InputDevice'] - -import os -import glob import logging from ..inputreaderinterface import InputReaderInterface +__author__ = 'Bitcraze AB' +__all__ = ['InputDevice'] + logger = logging.getLogger(__name__) -found_readers = [os.path.splitext(os.path.basename(f))[0] for - f in glob.glob(os.path.dirname(__file__) + "/[A-Za-z]*.py")] -if len(found_readers) == 0: - found_readers = [os.path.splitext(os.path.basename(f))[0] for - f in glob.glob(os.path.dirname(__file__) + - "/[A-Za-z]*.pyc")] -logger.info("Found readers: {}".format(found_readers)) +# Forces py2exe to include the input readers in the windows build +try: + from . import pysdl2 # noqa + from . import linuxjsdev # noqa +except Exception: + pass + +# Statically listing the available input readers +input_readers = ["linuxjsdev", + "pysdl2"] + +logger.info("Input readers: {}".format(input_readers)) initialized_readers = [] available_devices = [] -for reader in found_readers: +for reader in input_readers: try: - module = __import__(reader, globals(), locals(), [reader], -1) + module = __import__(reader, globals(), locals(), [reader], 1) main_name = getattr(module, "MODULE_MAIN") initialized_readers.append(getattr(module, main_name)()) logger.info("Successfully initialized [{}]".format(reader)) except Exception as e: logger.info("Could not initialize [{}]: {}".format(reader, e)) + def devices(): # Todo: Support rescanning and adding/removing devices if len(available_devices) == 0: @@ -77,6 +81,7 @@ def devices(): class InputDevice(InputReaderInterface): + def __init__(self, dev_name, dev_id, dev_reader): super(InputDevice, self).__init__(dev_name, dev_id, dev_reader) @@ -135,7 +140,7 @@ class InputDevice(InputReaderInterface): self.data.pitch) if self.limit_thrust: self.data.thrust = self._limit_thrust(self.data.thrust, - self.data.althold, + self.data.assistedControl, self.data.estop) if self.limit_yaw: self.data.yaw = self._scale_and_deadband_yaw(self.data.yaw) @@ -143,4 +148,4 @@ class InputDevice(InputReaderInterface): if include_raw: return [axis, buttons, self.data] else: - return self.data \ No newline at end of file + return self.data diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/__init__.pyc deleted file mode 100755 index fbb91527005546476a12468b4d18d99d6b80b392..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4311 zcmc&%UvC>(6+d_E*s+`cY3ihZcBcynYaz9SK!_DWq?=Zhc2hLTlHzU{jc2ZtamO?6 z%ynybV+kqyz$1@5@(tjTM_v(M0PVLxd;s{JGc&1oSNp&|1k3l%nS0MY|IfK+D*s+? z{=$F!YoCf=9nYU*WdBk`0Z|vTqOPLAqEi4C1r-Xa6ji7TAcw2et(Nctbr&eWzeZ7w zhIQ)JN$CX|ERt@}1xPgMlt@=;P$gZV!8IBzkzVGlpiV73_D|Z>T`4zLOJI%k3S%+i zBJKRvqL&luu9My%y<V)ouqbV)uchDkAL;*->Bo?^NrO!aFkdftK?r8k-C||BH)!%F z-q=6+BXwIe^+|7&Zjs)h3!J_wbBhfKi(SA(w@BY6eT#x?bYW5V4(Tl#yi+XdJG_X4 z%%otwB&=J7{_6PU4^&mZOD~#~{#~iAeTleSAZlBPfC5mTVH^i5^ciHm%dXUQ>O+`S zUIC-ubl+pA9=6xm^?%0Hd>F=o?M0Do&a~~l^1{gLMcNMI(b(9j_5z(|wg()OPHmIe z;c%3shOvkDn$4rc_JL$@)Q<J*;#i<xg}yFM+d-O)uzhbdwfmuv1{re}X3Zc>wQmv- zW(J|LUxyH+r|nVbztDj_#<{UchMoz1h&a91%&tM^`=Rku?~S(i?i+r8#Io)S&+tF^ z9fTHE+X!qj*UNoJRCyE|o%TInXUo{=Jm1^xdb@8<-iL4@7ARZ!^0J?;W9eZshJ=MV zKCnNX3FD8R?tlE`f&0<kql4@YunxyQC};gKWQ8e06M9kj28ulYbao;bA131{u;awc zZObmx^g)6u7<G&fF|spE2LC)66mi%GG<izKLJaQHjOd(bfLJ4%DVlWXoYU&NG_&{+ zGS4i~Ida*e9ez~sKp+5L;)RZ1?$9yf9=M0?DwrLJ6%2#1H`HK56b9`Y%fXUGIyP*N z%Rq5+UuR~MG2g1}7Pd01ONql|ywOO<fdh!zOcAV!QsD@+Ot=7O3j$AB4^!tX8R|~2 zaC~Q!CIduH*5Npq_M=em`j}#q?T)7AEQvc&*z5THe6ce&VU%?wr1QBDuH(8avg^YA z&LY@|(K$EB+EB}C31dyw)t2&kjel&A`xsdVlSY~$yGZg4=2ZfqR$2m}?x8+b=ra_< z8acUzeYR~mgx@|EawoHIEE-tsMY!u6eyWgyNwDF<mpQOd0<{vTvkZq4@CR+y173%S z<B?9q(1zDaUB%Q#=~x>n0^<?qbLI}=m@qyS)F>RnD(T29;avV=&eCyaOyhE4>b;hT z5ptQ1`f?JUb0u)t)%+3$rdfcw(XZaIoYKF-$XF0kw=0cGLp7AofyaYgDvoFY;B>+t z_Q#Ckj69jMZ3P$-(M5QR@(BXkVULOf9IiN5ujCH6KF7#d8?wHsa?UnROZ50rlIj1u zS~nq%i;=6PeAbTLcv&HzVCAbm`^4f3IFo!qbwnM!fUl9Cvnoyg%DJ_F@)w#RJCS8o zx-qNK^jzqmT-IoZ3nlJJF1LT1UtXY{S)I;-gy<+xf!>-e(mDQb7wfdM#fw-0`x>3& z)a5JSI!9Iu$*xd+kK-0qkv_<-z9m=v=cJU16+MG+=z)F=v0wg(jtg?ld2Rl{Wn%y2 z_cUuz(74p*XkHrDrYYL=)tr!pHuExq#-bp8qHx2-6+#L4S}A`AA-^nTMTwNll>S3l zt&}!cErB&A2nXfLxaGRL#tj%Ru2WjI7}zL}Y?i?F64>I(SWwt358j~kdvdT<qHVL8 z3$$%PQ<Uymd2P+tPb+koLx+;++)(7VptK0mTin}w_ULf;JAtITnU1uSlDAuOX}!=> z!&NWo_cLws3XHBrhg@T_RZRJT`yU@2Jv{)mjH~PXTAPzN&p<9GTrVX7g>B#&PfBU3 zLEiNyI+JP~a`VI0TZCZFT%=C%<f8vrPamWy3OpC?BS@aVar2YY>5Yv^;>=<BMCONH zguLfFUe34~>%ez`h?GQ;V2yASpE(<h#kAZnToTeP<o5;VsTbi!jsiIcp_7rry@KIt zTTn;$hd#m!dJN!V5f%7?;Z&D`D(zMn`_VXnFu-7Gyh)fzH7=BpRw9(y6K-g2^~AZ& z+*p6cf8|BE`Pe1Bt1r^;GFy!7mzYT1sw`VIv=~iQQ7yHOHe*Y@uQpXxtyI6b^L@2x zVbyA=RrPJ$U8@+|81LZxn$>12i@RO9d|g)p#dU{CFoyG7hp#|KqKgZv!<suR%v%!( zbXBbuIMY*%Y!OpUHLf+PjY|7lc*!qUH%R<TCGZ7smZW%PEnOGi0f6})NHU3n(<tf5 zUX+}katFf~uw+HvaD-*c@37Y;5Re^DfQ;_w176~I<-<B}Lr0!D6N30WkzR(SbY1>- z0cR$X_d3}q3XPuRiPrNnEy$b>eg0Y~J79-<F_AQk`-w2?Cn>&Z99GDYWZ@~7w(wm3 zl~pLs8X_wTIgyV!n0r?wg+iV&d6o~oFqSZIIOav)2NPe9Oqj$Xy_Qxt@4$gE7X(-2 ze+ku}=HmbCJxGxK5K|4Y+_09=bT1*MSFMVAtTvDtTk0p)4eZsdWxU-*?C+?XnD1JR GrT+qP1<Mrx diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/linuxjsdev.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/linuxjsdev.py old mode 100755 new mode 100644 index a0fee1ba..aaedd429 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/linuxjsdev.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/linuxjsdev.py @@ -1,4 +1,4 @@ -# -*- coding: utf8 -*- +# -*- coding: utf-8 -*- # || # +------+ / __ )(_) /_______________ _____ ___ # | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ @@ -22,30 +22,32 @@ # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software Foundation, # Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - """ Linux joystick driver using the Linux input_joystick subsystem. Requires sysfs to be mounted on /sys and /dev/input/js* to be readable. This module is very linux specific but should work on any CPU platform """ - +import ctypes +import glob +import logging +import os +import struct import sys + if not sys.platform.startswith('linux'): raise Exception("Only supported on Linux") -import struct -import glob -import os -import ctypes -import fcntl -import logging - -logger = logging.getLogger(__name__) +try: + import fcntl +except ImportError as e: + raise Exception("fcntl library probably not installed ({})".format(e)) __author__ = 'Bitcraze AB' __all__ = ['Joystick'] +logger = logging.getLogger(__name__) + JS_EVENT_FMT = "@IhBB" JE_TIME = 0 JE_VALUE = 1 @@ -56,31 +58,36 @@ JS_EVENT_BUTTON = 0x001 JS_EVENT_AXIS = 0x002 JS_EVENT_INIT = 0x080 -#ioctls +# ioctls JSIOCGAXES = 0x80016a11 JSIOCGBUTTONS = 0x80016a12 MODULE_MAIN = "Joystick" MODULE_NAME = "linuxjsdev" + class JEvent(object): """ Joystick event class. Encapsulate single joystick event. """ + def __init__(self, evt_type, number, value): self.type = evt_type self.number = number self.value = value def __repr__(self): - return "JEvent(type={}, number={}, value={})".format(self.type, - self.number, self.value) + return "JEvent(type={}, number={}, value={})".format( + self.type, self.number, self.value) + -#Constants +# Constants TYPE_BUTTON = 1 TYPE_AXIS = 2 + class _JS(): + def __init__(self, num, name): self.num = num self.name = name @@ -97,10 +104,10 @@ class _JS(): raise Exception("{} at {} is already " "opened".format(self.name, self._f_name)) - self._f = open("/dev/input/js{}".format(self.num), "r") + self._f = open("/dev/input/js{}".format(self.num), "rb") fcntl.fcntl(self._f.fileno(), fcntl.F_SETFL, os.O_NONBLOCK) - #Get number of axis and button + # Get number of axis and button val = ctypes.c_int() if fcntl.ioctl(self._f.fileno(), JSIOCGAXES, val) != 0: self._f.close() @@ -142,7 +149,7 @@ class _JS(): def __decode_event(self, jsdata): """ Decode a jsdev event into a dict """ - #TODO: Add timestamp? + # TODO: Add timestamp? if jsdata[JE_TYPE] & JS_EVENT_AXIS != 0: return JEvent(evt_type=TYPE_AXIS, number=jsdata[JE_NUMBER], @@ -165,6 +172,8 @@ class _JS(): self._f.close() self._f = None raise IOError("Device has been disconnected") + except TypeError: + pass except ValueError: # This will happen if I/O operations are done on a closed device, # which is the case when you first close and then open the device diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/linuxjsdev.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/linuxjsdev.pyc deleted file mode 100755 index 4816fdfea45669fd14e80ae7cff76c50a9c7465c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9030 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 ZZMFt45~cjJEqn>BvsF8OkoD2c{{o;!B+vi= diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/pysdl2.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/pysdl2.py old mode 100755 new mode 100644 index f998ad8e..5039f3a9 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/pysdl2.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/pysdl2.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- # -# || ____ _ __ -# +------+ / __ )(_) /_______________ _____ ___ +# || ____ _ __ +# +------+ / __ )(_) /_______________ _____ ___ # | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ @@ -15,45 +15,49 @@ # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. -# +# # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, # USA. - """ Driver for reading data from the PySDL2 API. Used from Inpyt.py for reading input data. """ - +import logging import sys +import time +from threading import Thread + +from queue import Queue + if sys.platform.startswith('linux'): raise Exception("No SDL2 support on Linux") +try: + import sdl2 + import sdl2.ext + import sdl2.hints +except ImportError as e: + raise Exception("sdl2 library probably not installed ({})".format(e)) + __author__ = 'Bitcraze AB' __all__ = ['PySDL2Reader'] -import sdl2 -import sdl2.ext -import sdl2.hints -from threading import Thread -from Queue import Queue -import time -import logging - logger = logging.getLogger(__name__) MODULE_MAIN = "PySDL2Reader" MODULE_NAME = "PySDL2" + class _SDLEventDispatcher(Thread): """Wrapper to read all SDL2 events from the global queue and distribute them to the different devices""" + def __init__(self, callback): Thread.__init__(self) self._callback = callback @@ -77,12 +81,12 @@ class _SDLEventDispatcher(Thread): class _JS(): """Wrapper for one input device""" + def __init__(self, sdl_index, sdl_id, name): self.axes = [] self.buttons = [] self.name = MODULE_NAME self._j = None - self._btn_count = 0 self._id = sdl_id self._index = sdl_index self._name = name @@ -90,25 +94,40 @@ class _JS(): def open(self): self._j = sdl2.SDL_JoystickOpen(self._index) - self._btn_count = sdl2.SDL_JoystickNumButtons(self._j) + btn_count = sdl2.SDL_JoystickNumButtons(self._j) self.axes = list(0 for i in range(sdl2.SDL_JoystickNumAxes(self._j))) - self.buttons = list(0 for i in range(sdl2.SDL_JoystickNumButtons( - self._j) + 4)) + self.buttons = list(0 for i in range(btn_count + 4)) def close(self): if self._j: sdl2.joystick.SDL_JoystickClose(self._j) self._j = None - def _set_fake_hat_button(self, btn=None): - self.buttons[self._btn_count] = 0 - self.buttons[self._btn_count+1] = 0 - self.buttons[self._btn_count+2] = 0 - self.buttons[self._btn_count+3] = 0 - - if btn: - self.buttons[self._btn_count+btn] = 1 + def _set_virtual_dpad(self, position): + self.buttons[-4:] = [0, 0, 0, 0] + + # -4 UP -3 DOWN -2 LEFT -1 RIGHT + if position == sdl2.SDL_HAT_UP: + self.buttons[-4] = 1 + elif position == sdl2.SDL_HAT_RIGHTUP: + self.buttons[-4] = 1 + self.buttons[-1] = 1 + elif position == sdl2.SDL_HAT_RIGHT: + self.buttons[-1] = 1 + elif position == sdl2.SDL_HAT_RIGHTDOWN: + self.buttons[-1] = 1 + self.buttons[-3] = 1 + elif position == sdl2.SDL_HAT_DOWN: + self.buttons[-3] = 1 + elif position == sdl2.SDL_HAT_LEFTDOWN: + self.buttons[-3] = 1 + self.buttons[-2] = 1 + elif position == sdl2.SDL_HAT_LEFT: + self.buttons[-2] = 1 + elif position == sdl2.SDL_HAT_LEFTUP: + self.buttons[-2] = 1 + self.buttons[-4] = 1 def add_event(self, event): self._event_queue.put(event) @@ -126,25 +145,18 @@ class _JS(): self.buttons[e.jbutton.button] = 0 if e.type == sdl2.SDL_JOYHATMOTION: - if e.jhat.value == sdl2.SDL_HAT_CENTERED: - self._set_fake_hat_button() - elif e.jhat.value == sdl2.SDL_HAT_UP: - self._set_fake_hat_button(0) - elif e.jhat.value == sdl2.SDL_HAT_DOWN: - self._set_fake_hat_button(1) - elif e.jhat.value == sdl2.SDL_HAT_LEFT: - self._set_fake_hat_button(2) - elif e.jhat.value == sdl2.SDL_HAT_RIGHT: - self._set_fake_hat_button(3) + self._set_virtual_dpad(e.jhat.value) + return [self.axes, self.buttons] + class PySDL2Reader(): """Used for reading data from input devices using the PySDL2 API.""" + def __init__(self): - sdl2.SDL_Init(sdl2.SDL_INIT_VIDEO | sdl2.SDL_INIT_JOYSTICK) + sdl2.SDL_Init(sdl2.SDL_INIT_JOYSTICK) sdl2.SDL_SetHint(sdl2.hints.SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, - "1") - sdl2.ext.init() + b"1") self._js = {} self.name = MODULE_NAME self._event_dispatcher = _SDLEventDispatcher(self._dispatch_events) @@ -178,7 +190,7 @@ class PySDL2Reader(): logger.info("Found {} devices".format(nbrOfInputs)) for sdl_index in range(0, nbrOfInputs): j = sdl2.joystick.SDL_JoystickOpen(sdl_index) - name = sdl2.joystick.SDL_JoystickName(j) + name = sdl2.joystick.SDL_JoystickName(j).decode("UTF-8") if names.count(name) > 0: name = "{0} #{1}".format(name, names.count(name) + 1) sdl_id = sdl2.joystick.SDL_JoystickInstanceID(j) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/pysdl2.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/inputreaders/pysdl2.pyc deleted file mode 100755 index 141afec89ad6dd1d4462cddb511db7cfad27c97d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8270 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 BNXY;I diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/__init__.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/__init__.py old mode 100755 new mode 100644 index 402c4d87..63a300e1 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/__init__.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/__init__.py @@ -20,7 +20,6 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -29,16 +28,16 @@ The mux is used to open one or more devices and mix the inputs from all of them into one "input" for the Crazyflie and UI. """ +import logging __author__ = 'Bitcraze AB' __all__ = ['InputMux'] -import logging - logger = logging.getLogger(__name__) class InputMux(object): + def __init__(self, input_layer): self._devs = {"Device": None} self.name = "N/A" @@ -49,34 +48,46 @@ class InputMux(object): for r in self._devs: if self._devs[r]: if self._devs[r] == dev: - self._devs[r].close() self._devs[r] = None + dev.close() + + # First set role to None to stop reading + old_dev = self._devs[role] + self._devs[role] = None + if old_dev: + old_dev.close() - if self._devs[role]: - self._devs[role].close() + # Open the new device before attaching it to a role + dev.open() self._devs[role] = dev - self._devs[role].open() def supported_roles(self): - return self._devs.keys() + return list(self._devs.keys()) def add_device(self, dev, role): logger.info("Adding device {} to MUX {}".format(dev.name, self.name)) self._open_new_device(dev, role) def pause(self): - for d in [key for key in self._devs.keys() if self._devs[key]]: + for d in [key for key in list(self._devs.keys()) if self._devs[key]]: self._devs[d].close() + def devices(self): + devs = () + for d in self._devs: + if self._devs[d]: + devs += (self._devs[d], ) + return devs + def resume(self): - for d in [key for key in self._devs.keys() if self._devs[key]]: + for d in [key for key in list(self._devs.keys()) if self._devs[key]]: self._devs[d].open() def close(self): """Close down the MUX and close all it's devices""" - for d in [key for key in self._devs.keys() if self._devs[key]]: + for d in [key for key in list(self._devs.keys()) if self._devs[key]]: self._devs[d].close() self._devs[d] = None def read(self): - return None \ No newline at end of file + return None diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/__init__.pyc deleted file mode 100755 index ac147b6b3038f7b89e9ebfa6ad78bc2bf1f8f8e2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3102 zcmc&$TW{P{5I(jyo9xoiloUdEsa2t}MM{l?l&2MtrV_o-1)PM^h}PQJXE)w@?Tyb_ znn3at{slji9{}Gs-b*SF5)W*XoXO0b+sro?AMcOV=EL~O53!p3c=-PnhItH<D0K+x zs6$63uIhtvRpP0nrZP_*dP;k0P*ZwIU1F-vHF{a~uy{%RrqrcU&kt9)daqUIndczQ z{bTJ9$ESX3{ISuAZwtQ|>D(`J?H8p#EK2Ps`sXy(#_#5dKTJ=3i#=&R8e8M{%3|nu zv#eS4s2)Pk6R`QVthnv>a0)l<mfc^@dReOFn1e_6n&urCa6h#%X0*R^->yJ@#B-mH zPt!l~)0qL`a4ClQ4nzY8c%|qSA#j8N5Uwyag2JgKI!gvv2n2`ADyfSGI4ld(P~l#S z7soCL2QlBpFn2&wxd%6F1FcAKC*!JfN0Gs$3V3o)#}d^C6;`4Mc3L&4EJ+8L*d;I# z&@`gTyTeK)NVRyk=#9>Lme`0s%DQK|Y(Z2)%yV$TaWT}v(FD6-R2BmrTN4mU0eLG1 z(z!KTqceM4<Uy7m1#z!Z24kCMCXmwu#6F0kG*4|5-NRx+F_k|BZ|IbA)|`eD(<%DG zAqf2r=JbF-4B+{T$LhkH2<M*KESpyZ;PuK?<^C1bz+p~0iJI%$C;RH8$-igSq315n zIh!tkFxix2lSBX)V@-R$df-h@-D@#xIue7BwhR7oRu~=5z-F>nE9j`@G6YECP!^fC zJYsR^ui>_cCPle^%}hbv1<;xIK$N@YtUBw?4QIn$b#8)>Y29>4L{_1wu&98VVnBZ@ z3>dsu`pgJ8A)Q`WZe7P^W;_}drPWD9cukus8mFrCBL1`V`W%8qZlUZPHISM^bm<;q z?6S)_6l#(RkX=cpJ*lLQ`3Sprk|fRhlLqGhdcpSg^x#KuE!Lt`Y*zI9x|E2gd9M&1 zn%1yuLs}BP3nB$BV1+Eq@EUa(3n|Ga?&&7UBptqlWN4UjZdD2J24>%4;`E{FznKOP zUTmt1S-m)@sda+((p4wxDBKNo0d%E`S#W^*633r>rk*A2ZdDoa8cCs$aSR(Eb6BKs zkXBMJ$-<yv5Jz2nxOTxzP}zQ)s4!M@RKoWmh96Lev5;h8L6_Q$hx%)9{{qQRm`3mZ zZ;A5pKPC#QbCx`9$r=Y)!>Tr0AiM0iep0;7<srcO<4ZysG2ae;YCkd4N5++QJ<l^~ z*KZS6$@V97NIr+|Hk$C?n=h;KO2M#fD$9jiXse|urS2x*)8?wbwwRlf?>nC!QDmu! zqG6GYGl<~|L}_;+zeC|ok`0m%Nm%gVCdfROh5LUWBq1(TcQFiYsymIP#%jZB)a19` zqEU7kB#M$Ep1IT=<JD6_tfr7;6Q0c;Uj)m2eQm#y-XHQ)5#HcY3{r8#$CO;WP*){3 W?J62y+=3y7@u|CT+P&sp_x=LI*0}fp diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/nomux.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/nomux.py old mode 100755 new mode 100644 index d32965a1..ba4d51f0 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/nomux.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/nomux.py @@ -20,7 +20,6 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -28,16 +27,18 @@ """ This mux will only use one device and not mix it with any other input. """ +import logging + +from . import InputMux __author__ = 'Bitcraze AB' __all__ = ['NoMux'] -from . import InputMux -import logging logger = logging.getLogger(__name__) class NoMux(InputMux): + def __init__(self, *args): super(NoMux, self).__init__(*args) self.name = "Normal" @@ -49,4 +50,4 @@ class NoMux(InputMux): return data else: - return None \ No newline at end of file + return None diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/nomux.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/nomux.pyc deleted file mode 100755 index 295adbfe806ffd6abffdc7e855a0a8fdd5e6bced..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1267 zcmchW&2G~`5XWcjd^DjINJvO<Kt6CV60HwNoGJtbi6S5e7gZvcmFwLk8?EigyM_jp zQ#tasJOKP>69O+lt?YPac6L4Un@RlhV0>D>J1=Sb#CX5Ja#ILJgqIRD6{I4XLy1Vm zq<Umys(Li-kx+e71G0UZ_DT0?IUqfxYlQCc8Qr594iD)&(KXSh>4>Ax(mnphDa82W z!nmaBE|V|D+N7!NI_aE-q7$V*n^Gr5t&+O&No6h*;}Pc<@U4@^FLaxjde!-(vAc!K zPK+<x;;T+xp7=iON%Nt*Gy+=6!t+<(ay+|#;hF3T=lv5b_W(kpaAZxKHJ2=c5>tMb zM%XSnm=&h=2FpE#@c0S3LY)yUBf1jwgMcTvWK2i{7XryMgh)UmVBiZTe!#M6tHK8L zbtpS!Z>Yj`E8XU>HU&s&YU8E!J$UM((m|O3ScsOO=0cjm@3fr-rD*3a<x7Ha=g_i6 zQ|att3oTo<%~F@%Wz29rvqm455Vd!QtF>P=b!N>)R?argtn<dYEa1=3zpQQ`k5=oP z$v?(&TmgxDVkCCNnA$7edjbIv%P?Q}+eiNxOTnY^4d4WwF{XfuPfl_M7O3Ui%TQRW z3zZMq&msBfk6#tOxS4`^^p3C`=S1Q_+>Lrs%IyggCna|Y4I9HFW!0$8!VH{pKKnPz zp#9I@;A`P?j<XwxQ9tFRJmZs6HRUeLqC>}9n47J_TIh(PJp7Z`Yn%Dp)N{|o=i0xA mi8(!h6~>siw{v@Q1qR^98^q5aA{Dm}F^EuVbVuxq+wpIm)glrA diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeovermux.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeovermux.py old mode 100755 new mode 100644 index d4cccf3e..8295e202 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeovermux.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeovermux.py @@ -20,7 +20,6 @@ # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. - # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA @@ -30,21 +29,22 @@ Mux for giving control to one device (slave/student) for all axis (roll/pitch/ yaw/thrust) with the ability to take over all of them from a second device (master/teacher). """ - -__author__ = 'Bitcraze AB' -__all__ = ['SelectiveMux'] - import logging from .takeoverselectivemux import TakeOverSelectiveMux +__author__ = 'Bitcraze AB' +__all__ = ['TakeOverMux'] + logger = logging.getLogger(__name__) class TakeOverMux(TakeOverSelectiveMux): + def __init__(self, *args): super(TakeOverMux, self).__init__(*args) self.name = "Teacher (RPYT)" - self._muxing = {self._master: ("estop", "alt1", "alt2", "althold", - "exit"), - self._slave: ("roll", "pitch", "yaw", "thrust")} \ No newline at end of file + self._muxing = { + self._master: ("estop", "alt1", "alt2", "assistedControl", "exit"), + self._slave: ("roll", "pitch", "yaw", "thrust") + } diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeovermux.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeovermux.pyc deleted file mode 100755 index 02296e8241ecfc48e3669cb25e0c5d3c2052fd54..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1396 zcmcgs&2G~`5FXn}+N3Q%65_l^SE9A(ffGWd7m$F0k_xF2lI7YPd&AmmdB<sjdMig> zg{R{IU}o)<K0%|*cy>Jh->ic_2b1^dhp#F0zkr^nM0QRr1E5Fd!Q6w)hnxf-vH-FH z=m6#<3?UnV9zZ#S`4BuAz;Xm~2X4u97qT6YLs*dWF8l<z1-P7#*?Sg_Imd5elTYnh zEKDPEwNh0sQd41Lv_K<FB}FDzDwQI%I$6ocVw=ed51m7zwMf>=ijeGeR4Yu2XtGJJ zBP^QMlGU}sLSP|9a;3Dw4F|>KyA)<68^Qi&!S744XiO;*VI`%{`lOSvOf1SKLYbt6 zYz~hnc8@APqeM;eLyEU&xKHPq)G|f2lGKU%OTTmFkve3C&xl=6%FmSXz9Dj??F(|e z1Ax8Gi0o5hk^rFT0Z)%cKb^UtDckr&BcgXi_LLaX--8<(vkyxjZanw};1PJFiUUxD z+#buz0ldogoiv13{Bpz@X5j$^Ik%69Uvv$NaQfx);t+?Vk`_&k1CkPrFSo)8?sS^M z=*%hQTA>pd6X)r0LEbBZ2D#)8o{+=ZyV!Ocdn=sSd$FC8V~1?!PMpBGy9BmRVDBYh ze^-KSYuQYBVz^5zj#Z^Fj$NHqQcBlF+@b9%jNQ8RYC^TjL+9<1OTFm&Z*m(_IB?8< zBPl9ODWj`?L87`bOIi&Z@xE*pTFIl7ScUee-e6&>NUN(TU3AK*MWt<|s=CFfY}XO5 zDsL*u$Mt5)_#6@02{G`Vdt)!~CSJ&$_kD3Q)E67XacQzv)6qHpFZ6+`<$1jzvTjkm zkZbA&8fPZGD>7+m4h<a{tT?7S*~{AGInCW&pzR>+_NLK9rtW(2XC#;Sk&FppzHAOZ hcJ2{>=*Arque;g55mb=nZ^XzSd1HUyf8sw5{sE<!VW<EA diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeoverselectivemux.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeoverselectivemux.py old mode 100755 new mode 100644 index cde7af02..40207d53 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeoverselectivemux.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeoverselectivemux.py @@ -31,17 +31,18 @@ from a second device (master/teacher) with the possibility to take over roll/pitch as well. """ -__author__ = 'Bitcraze AB' -__all__ = ['TakeOverSelectiveMux'] - import logging from . import InputMux +__author__ = 'Bitcraze AB' +__all__ = ['TakeOverSelectiveMux'] + logger = logging.getLogger(__name__) class TakeOverSelectiveMux(InputMux): + def __init__(self, *args): super(TakeOverSelectiveMux, self).__init__(*args) self._master = "Teacher" @@ -49,9 +50,11 @@ class TakeOverSelectiveMux(InputMux): self.name = "Teacher (RP)" self._devs = {self._master: None, self._slave: None} - self._muxing = {self._master: ("thrust", "yaw", "estop", "alt1", "alt2", - "althold", "exit"), - self._slave: ("roll", "pitch")} + self._muxing = { + self._master: ("thrust", "yaw", "estop", "alt1", "alt2", + "assistedControl", "exit"), + self._slave: ("roll", "pitch") + } def read(self): try: diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeoverselectivemux.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/input/mux/takeoverselectivemux.pyc deleted file mode 100755 index e24f03584f76f52794220b9cdbf47b64a85ffe4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2001 zcmc&!UvJ|?5TCW3q)D&W)A8p3fmnEQrR!Oo(1{0xpnw1Y1v#fXh=eTH-Xu;PJ9sy3 zg4(C@h{OXgd<8xOFMKCH0Q_d0rYAlC=VWJRXXnrE%x~8JdvEZ0_T`g|HlL6ALkv3t z$%!!KibjfZk0xL|%6-ZMDt#J(=}_LKGN5^fMjcYdr&*UwkFKD)!#1WvV;J}7XQC^j z??-*M9)>#{;}4L**UOb2*Nx8V$~ARa7S%-a94!i$P4&2`=en+p&dpho86Da(Ju{JY z%iL7%K&Mr%-PGvDST_*mR9gdQ`PO2dT4$QbnKYZ4=0KkpZYnm5+S=lzC=0jNuGTI+ zHM%}C&ET2%snzGEEFTQ)E>3%dGd1Z?Mt^kVUc~w_Oum7|(3B=~#hJlvihuAO7Yf@U z6UTS`qFO8+Hn)l9og)nU8i+xnktO0Raf+2NKE=b(!*<5X%&@1=Fl-It@K<z!ym~bA z=t9viL<+VLC8!NVU;-`}GaV}6nV6sX^k~Bc^oTcmvbne2ye-^j6NMy{Y#%X?T@Une zn@Qn^Z6WNf8@UeSZx39Tk2r0X);R{%Iz4wC%qUa6Z~?fqbnjd<55*TG)4I$>XjX+2 zhHD{~f`^df+Z*3@<J)e1+iTy~%tOmI8{Z;i-;!8aaR4!I1N5OR@$7P8ni#9Lf=N<T zg-a4SY0_d!E|~}-<*ZdYH^LkPvEn2FZ0*Jb(5NO7S9Gi?$HJt|#D*M4hy@rZn$~j@ zoovt+Et+};eA$S>w;q>;Im|#RXAc)^<gALy;v~w(tuR`;qO?)Lkc;NaRm8w%Tq9zO zQV1U`*70pbI>fMdKuEo;`tp0j^VL8J=s2r9KE|+rfvkTQWVA3+^lJ0lGi&cZYwQDR zS45Wr%2{g#t&LPbI}6DEN~?FpPe&*;KKbEIx&&|)KPVSqfbkwPcv*mV^<zO#EBI41 zWN<#M-lD+u>2yHNpQJ7WQf@%AUAhR^Lb1+wOr#@^Lq==-0ux4c%=ed4G$zgAh6ow5 zcqg)H%xx|Rwx&h$#JKn_3t8{eRc02hz}v-`EbGa{G*a&Kw5hn<oW1xZR_6xJ=j~+0 z<EdGrgV7VurTX^}`8^E#3J57*X&`_xa8GG3@OHd?wWmVvCV9b<gwYNB4<JdBd7Upy zECoa{`?|Tr|BYh=r~4Sv&Rx~t4f%|1*ClzKZ4aF;(Jak%4<~6^Zg?&ns)Z*N)sjb> qi;GHsB^8a|X8G$(FrME{r4aA8ssBLZB=YQbJ>1#5<=yf2{eJ-?TiO@^ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/joystick/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/joystick/__init__.pyc deleted file mode 100755 index f98770b26655e6ba6ee2e856607abb6defe8a526..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 245 zcmYL@K?=e^3`Iv>C<U(|UDk!>0wSKkjUwV^Xs0PntsR-9i+Tai;5og3859iU<^N9z znY`!8bNM<t^Q)20oi-<m(wK{KWDeOlW}rw;c_80&+6%QLgsK?Jv=~yUG3t;~Cm5>S z;X2u8@uEx>)|TE`o2fK^@L4U?{)SMHxR5^(?!h<cgdy6YY6(|P(Fw2agVer*mI`py iH-z{JL*oY)a#ygHIudKwx;xY3o0~8D7Pkx4tZhDNA3`z! diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/joystick/linuxjsdev.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/joystick/linuxjsdev.pyc deleted file mode 100755 index 45bc0a261684b6e4666f9b7509e4b3d94ebc7c92..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9305 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 DWOf+p diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logconfigreader.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logconfigreader.py old mode 100755 new mode 100644 index 1e948b48..c548dcf4 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logconfigreader.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logconfigreader.py @@ -35,22 +35,19 @@ Currently it can just use the PySdl2 driver but in the future there will be a Linux and Windows driver that can bypass PySdl2. """ -__author__ = 'Bitcraze AB' -__all__ = ['LogVariable', 'LogConfigReader', 'LogConfigRemoveThis'] - import glob import json import logging import os import shutil -import sys -logger = logging.getLogger(__name__) +import cfclient +from cflib.crazyflie.log import LogVariable, LogConfig -#from PyQt4 import QtCore, QtGui, uic -#from PyQt4.QtCore import pyqtSlot, pyqtSignal +__author__ = 'Bitcraze AB' +__all__ = ['LogVariable', 'LogConfigReader'] -from cflib.crazyflie.log import LogVariable, LogConfig +logger = logging.getLogger(__name__) class LogConfigReader(): @@ -59,24 +56,25 @@ class LogConfigReader(): def __init__(self, crazyflie): self.dsList = [] # Check if user config exists, otherwise copy files - if (not os.path.exists(sys.path[1] + "/log")): + if (not os.path.exists(cfclient.config_path + "/log")): logger.info("No user config found, copying dist files") - os.makedirs(sys.path[1] + "/log") - for f in glob.glob(sys.path[0] + - "/cfclient/configs/log/[A-Za-z]*.json"): - shutil.copy2(f, sys.path[1] + "/log") + os.makedirs(cfclient.config_path + "/log") + for f in glob.glob( + cfclient.module_path + "/configs/log/[A-Za-z]*.json"): + shutil.copy2(f, cfclient.config_path + "/log") self._cf = crazyflie self._cf.connected.add_callback(self._connected) def _read_config_files(self): """Read and parse log configurations""" configsfound = [os.path.basename(f) for f in - glob.glob(sys.path[1] + "/log/[A-Za-z_-]*.json")] + glob.glob(cfclient.config_path + + "/log/[A-Za-z_-]*.json")] new_dsList = [] for conf in configsfound: try: logger.info("Parsing [%s]", conf) - json_data = open(sys.path[1] + "/log/%s" % conf) + json_data = open(cfclient.config_path + "/log/%s" % conf) self.data = json.load(json_data) infoNode = self.data["logconfig"]["logblock"] @@ -115,7 +113,7 @@ class LogConfigReader(): def saveLogConfigFile(self, logconfig): """Save a log configuration to file""" - filename = sys.path[1] + "/log/" + logconfig.name + ".json" + filename = cfclient.config_path + "/log/" + logconfig.name + ".json" logger.info("Saving config for [%s]", filename) # Build tree for JSON diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logconfigreader.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logconfigreader.pyc deleted file mode 100755 index 5bc212757895ae145bd54f853d5f53b9df89c06d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4251 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 OEt|{V+S<ac`hNjTB%X!< diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logdatawriter.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logdatawriter.py old mode 100755 new mode 100644 index d9c551c6..0f305fa1 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logdatawriter.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logdatawriter.py @@ -30,20 +30,17 @@ Used to write log data to files. """ -__author__ = 'Bitcraze AB' -__all__ = ['LogWriter'] - import os -import sys import datetime import logging -logger = logging.getLogger(__name__) +import cfclient -from cflib.crazyflie.log import LogConfig +__author__ = 'Bitcraze AB' +__all__ = ['LogWriter'] -import traceback +logger = logging.getLogger(__name__) class LogWriter(): @@ -55,7 +52,7 @@ class LogWriter(): self._dir = directory self._connected_ts = connected_ts - self._dir = os.path.join(sys.path[1], "logdata", + self._dir = os.path.join(cfclient.config_path, "logdata", connected_ts.strftime("%Y%m%dT%H-%M-%S")) self._file = None self._header_written = False @@ -116,4 +113,4 @@ class LogWriter(): self._write_header() self._block.data_received_cb.add_callback(self._new_data) logger.info("Started logging of block [%s] to file [%s]", - self._block.name, self._filename) \ No newline at end of file + self._block.name, self._filename) diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logdatawriter.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/logdatawriter.pyc deleted file mode 100755 index d41df77b73f2fa48831abd2082f3b08482223575..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3823 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 BTeJWG diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/periodictimer.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/periodictimer.py old mode 100755 new mode 100644 index cfdff4ee..7ba3063d --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/periodictimer.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/periodictimer.py @@ -30,14 +30,14 @@ Implementation of a periodic timer that will call a callback every time the timer expires once started. """ -__author__ = 'Bitcraze AB' -__all__ = ['PeriodicTimer'] - import logging from threading import Thread from cflib.utils.callbacks import Caller import time +__author__ = 'Bitcraze AB' +__all__ = ['PeriodicTimer'] + logger = logging.getLogger(__name__) @@ -68,6 +68,7 @@ class PeriodicTimer: class _PeriodicTimerThread(Thread): + def __init__(self, period, caller): super(_PeriodicTimerThread, self).__init__() self._period = period @@ -82,4 +83,4 @@ class _PeriodicTimerThread(Thread): time.sleep(self._period) if self._stop: break - self._callbacks.call() \ No newline at end of file + self._callbacks.call() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/periodictimer.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/periodictimer.pyc deleted file mode 100755 index 04a5eb1373f92282b172bf825bba163593671ac3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2914 zcmcgu-*4kY5FXq4(d1gLy7Kdozyg7C(p@9*079SxT6BPbs&Xn2d9hr3+dAji!MowE zsBgU&{$Bn7_`b1|_7L#aI@!tYdUj{`o0)GC{JAy!HvRsmRN5!N@0V!y4~R@;3hBwz zlgyV>bbQGI$vRR5GDQd9t`r@acV*fYkK>*cJ(>4q+Hc0t-H_>qm_TL&F+;h;Hg~vR zHk7O{FGMayewl7c2Bof?z}8?ryG3J@(H$NshZuf0Ule9;N|(62D#Pj|Ou~h!^D4{J z(B*SehwdzK;j_Fb!Zd+M^yfH9pN8f)Q=hBW(4Co9-8^69wXtDUrY5v5sh!Dohn6Py za+lW0?<V|e&uw9R*cv*bo%}C62O|&jt_N{+R+}Wd8t=onsZ+eshkAQx_5p+evbZNC zVDNZbqUmd=Ls&V}m1r{RaLHqceeCYc|J`;41MHsv^Xh4UE!cc+g=Rm4aEkqfNbCvZ z%#)cf7d~C&xqwq~M=tbT+~sjO(`RR*_dFPFV3&w{x*<eNz=^bVn;0fpww`faOgu>n zYaG|aEzqvdL347)yB<`fX(nBRCl9S}tSL?u=vJHCtn7`@7Zvshz42K!H{;{hd*el2 z%}na-n9e*uDRT2Dg(#hUv^aNXRXHy5<8gY@Opcc>FYI`QrpDAR^z_(qUgj>2$1q}f zWAQe<ZEt{2N(Zy?z>4q$9il2y-xsIY!q>zWo}M)L&VVmex^fBNfy8RXtS3N$y3G!= z4Q7ch9MOQi3o&7^BHY_ZwjW?lLo-YY#^U)ZoF9f|<w68G7v$yX!Ds;0h(Zx9s?$?b zE9}pbx`c*%74PE1>+#;icSMIpJc8qLxby48%&SsebW|^mI$8~Bh(tu`7Tgo<z|O}! z5hG9hfw$##yf@*TwPV(y{~;7w$Gq2e5c-O56YC<S^4?^`HTD&ViK`Y@P#>rh8UQsz z@it<B-0q#}q%U|v@=tT;5xZ@ymdV`2ag&+xyvmjZhnjJ5R;6(qk<=8qh+AE`NqaYz zN)c?yLo`dsdS1^T^aq1z8-o;0pEX^+kKvjwU;GDSf+!i1YnJ0+AI*LQ;qX<zBFDgQ zm&l`*(?D@e+I0kB%lzwICpRM1g!2+?pyz84TjxMTR#O!aTD54Rf)O9Fd}wZwqD*}S z?aiS|XMTgGsEW7qGA*s6pK5@Fx78A~qH-!k_bA?ixcxx>5mqe^A^(!HtboryX_M7{ z+R`bLIJm}=^#eIX=5o5Dq>8<M4dmx*1&isS7gWL`xi=mzj9FacHYPPacdIa<B%oF- z%R~IUR9!mWh=CTpM)5j@CN6U}dI#bvx^6genW9h7lyG|9pf?B_+oZ_o4TzR)k|pYD zy=EIA+4fm#SYNdEXobfpVzxWpE=6@d-qi}cyDIKh|6oLKQ-{k=jr&0hR)dF{#<XaH i-WC)}v7a}j`uJT~w@jU$4^VvmCD`^h{ky@={l5VW|CKTT diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/pysdl2reader.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/pysdl2reader.pyc deleted file mode 100755 index 371ba770c345e6c3e06779065a005f1d301ca081..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5784 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/singleton.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/singleton.py old mode 100755 new mode 100644 index 3a0dab0e..832d2cee --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/singleton.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/singleton.py @@ -33,12 +33,14 @@ Singleton class. __author__ = 'Bitcraze AB' __all__ = ['Singleton'] + class Singleton(type): """Class for making singletons""" _instances = {} - + def __call__(cls, *args, **kwargs): """Called when creating new class""" if cls not in cls._instances: - cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + cls._instances[cls] = super(Singleton, cls).__call__( + *args, **kwargs) return cls._instances[cls] diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/singleton.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/singleton.pyc deleted file mode 100755 index ec89e13b651a261d597761710075f458596fbfb2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 899 zcmcIiO>fgc5FM{WN`nv*H&j7=0LhnjFB~gA+B+bJ3%RVe>rLWhy|%m)MM1fh6NmmV z{!afuXV$6dA84F;o}G;6y?IW0_i|GI`}@<t;giz+3q_CwCBTd@fms5jfCVLj6Pv=E zDk=N{xB>Vz8$mgOY5t5Kd`&Q!R(|0uHa;^>hj2a#FQ|N3q3QH*n|-~+V>%CA1AW3> z6yYs_C3>PE6i^YSEQKhEu9)V6+fE3sm?4`tT~_Ng@n+$HJQ$wGD{*|M2%ib|@w)<8 zA3^sKFaZ=?yb-WUVV}TW!0kg1)i3;`!<%W&L&H0QEA5;uv+dH-o}Jam?A~tsrSlQB z;DkU`KA`r-28<SMTH6&=2Yk-IDnoOW%2^~b7#ENq*4-lDn3DCD)0{Gh5Pnc5mrZTu z^}$owcFoEf43aJ0&0S^B41vdR*6wiGc<HKZY36-VZm@De4pyDFyMn2Cd|*ltuaXZ* ze5D7KUe{Ksej!yi<;L;xh+35@8>3Xg#tc(>rB5iAMZTwqa>of>;#<^P@PF%|Q*UVX hZqONxj^5&~wecPNclGJCMh7o?&pw?Fn#DLd7WW5?)2ILd diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_led_driver.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_led_driver.py old mode 100755 new mode 100644 index 8232b6c3..e639b092 --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_led_driver.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_led_driver.py @@ -30,25 +30,27 @@ Give access to the LED driver memory via ZMQ. """ -import cflib -import cflib.crazyflie from cflib.crazyflie.mem import MemoryElement import logging from threading import Thread, Lock + ZMQ_PULL_PORT = 1024 + 190 logger = logging.getLogger(__name__) enabled = False try: import zmq + enabled = True except Exception as e: logger.warning("Not enabling ZMQ LED driver access," "import failed ({})".format(e)) + class _PullReader(Thread): """Blocking thread for reading from ZMQ socket""" + def __init__(self, receiver, callback, *args): """Initialize""" super(_PullReader, self).__init__(*args) @@ -59,12 +61,13 @@ class _PullReader(Thread): def run(self): while True: - #self.lock.acquire() + # self.lock.acquire() self._cb(self._receiver.recv_json()) class ZMQLEDDriver: """Used for reading data from input devices using the PyGame API.""" + def __init__(self, crazyflie): if enabled: @@ -96,4 +99,4 @@ class ZMQLEDDriver: memory.write_data(self._write_cb) def _write_cb(self, mem, addr): - return \ No newline at end of file + return diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_led_driver.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_led_driver.pyc deleted file mode 100755 index 9d11f15fe5930ef3137ec1223755222a21c76613..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3608 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 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_param.py b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_param.py old mode 100755 new mode 100644 index e2ea3fc0..da221b6b --- a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_param.py +++ b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_param.py @@ -32,15 +32,18 @@ Give access to the parameter framework via ZMQ. import logging from threading import Thread, Lock + ZMQ_PULL_PORT = 1024 + 189 logger = logging.getLogger(__name__) enabled = False try: import zmq + enabled = True except Exception as e: - logger.warning("Not enabling ZMQ param access, import failed ({})".format(e)) + logger.warning( + "Not enabling ZMQ param access, import failed ({})".format(e)) class _PullReader(Thread): @@ -60,6 +63,7 @@ class _PullReader(Thread): class ZMQParamAccess: """Used for reading data from input devices using the PyGame API.""" + def __init__(self, crazyflie): if enabled: @@ -70,21 +74,23 @@ class ZMQParamAccess: # If the port is already bound an exception will be thrown # and caught in the initialization of the readers and handled. self._receiver.bind(self._bind_addr) - logger.info("Biding ZMQ for parameters at {}".format(self._bind_addr)) - self._receiver_thread = _PullReader(self._receiver, self._cmd_callback) + logger.info( + "Biding ZMQ for parameters at {}".format(self._bind_addr)) + self._receiver_thread = _PullReader(self._receiver, + self._cmd_callback) def start(self): if enabled: self._receiver_thread.start() def _cmd_callback(self, data): - #logger.info(data) + # logger.info(data) if data["cmd"] == "toc": - response = {"version":1, "toc": []} + response = {"version": 1, "toc": []} self._receiver.send_json(response) self._receiver_thread.lock.release() if data["cmd"] == "set": - resp = {"version": 1} + resp = {"version": 1} # noqa group = data["name"].split(".")[0] name = data["name"].split(".")[1] self._cf.param.add_update_callback(group=group, name=name, @@ -98,6 +104,6 @@ class ZMQParamAccess: self._cf.param.remove_update_callback(group=group, name=name_short, cb=self._param_callback) - response = {"version":1, "cmd": "set", "name": name, "value": value} + response = {"version": 1, "cmd": "set", "name": name, "value": value} self._receiver.send_json(response) self._receiver_thread.lock.release() diff --git a/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_param.pyc b/pps_ws/src/d_fall_pps/crazyradio/cfclient/utils/zmq_param.pyc deleted file mode 100755 index 168cdd01bcb4d437b887c1e9a61e7e9a3cf25da2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3797 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 P0F|_7cFgO+?#}-J<hdv% diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/__init__.pyc index f5e936ccbb0fd4da975be38c2a121c3f618e5b17..a5ca6d4071705a3ae3b59a286df950bbcbb51bb7 100644 GIT binary patch delta 40 vcmbQoxsa2c`7<w9YUSmP>;^2t0SpWb`WgATsrt!9iB*+pIhm=G-C4o`^TG^k delta 37 tcmZ3;IggW_`7<w<!`#~&*$r3(d>I%R^fU5vQ}t7H(-L!XCVR1j0|3i)3f2Gs diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/__init__.pyc index b09a12f550842caeaa953ba1c7a810c6c4aaaf89..1d052e26d093f2d2af461e4f7305e6843adeba19 100644 GIT binary patch delta 951 zcmX?AxweX(`7<w9YUSmP?2#<OQ49<W`WgATsrt!9iB*+pIhm=G7xMaS-oxUJOVWFC z5@#C@jRBKAxF+J1v*hl>DW}fUf>Vy07pr}n7xFeS;n3tgxlZ6X4mqFA3k9_qaY%Y^ zRu_)IDLMI;$S+(PC+my7#UbajxkCIlZbR2e-ov5M8)zuo=C@LXxHS80-X$}G8JF(O zYZV%C>GYo5sdNyl#z5nM$*YtXW0eD?jg=}=I1Sw_r*;WfocL_^(G<kx)_}=-b$W4F z8L)YkE<08$Hy_js#VP?##6<>)xFz+Cgs@6(4m6&LRRV0Jn`s_yNdfZ>xcu%tS=y=& ThxdFof3>p0Wvch&E*l2`A6Go? delta 852 zcmZ2mb*hq``7<w<!`#~&*&|s5!WkGC^fU5vQ}t7H(-L!XCNpyRY~Ih}ja9~bat3D` zHZ2da2?k7d<?h2SVaC&fT|$-@tN8(&+4zi@uxat0JWb#@HVL22djz!^vB`LEb`_4m zE;ISJ$S<r~CI^eX#U|midA|5<9A@2+yoXJT_hu34a;#c>HouaY!Hiwc1BFJcdb}s^ zS2~DIi_hfy%F8h&0!;%pzf=*!Zr0{lwM$q-*=KW~rXW_A1x#kr?Zvc)kt<;HCtY@| z*7$6W(C5S<bHE@GhfIT!5DuA-#=e*`n*&XEVTyuNcb54Ete*6qTwzs*%_}~eL#?f_ L8s<Iut&IZ!0DJb9 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/commander.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/commander.pyc index 1a4551165f13f85143fbb07424587f5960cf074a..8c878db97973dab1c6de56c815a53f19287b7151 100644 GIT binary patch delta 154 zcmew>&?Css{F#?4wes>t_CzM(Xa)ub{fzwFRQ=?l#Hz})oXph8f*gUHPcktw;*j*+ atj?l?OQ-MT4Qv%SH2O?#VXws@mjeJwMK7oT delta 135 zcmeAX{42oD{F#@_VeajX?1@YQ5ey6r`WgATsro6pX^A;GlNC4uH=ki*WW<o!{D8R< di~0x5zLR&dRbVKe{D9eK@&xu;ObG>!901*~DQW-! diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/console.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/console.pyc index 7eda3dbedd01ce70ec7b102c900beb60cab58b61..1a8c8c2f279ac0c46bc4c8048ae830c7e0bbfcd1 100644 GIT binary patch delta 125 zcmeC<oyE(}{F#?4wes>t_R~zlkqitB`WgATsrt!9iB*+pIhm=G4OzW5>o8j|;*j*7 Syq_frhulLP;$D+;*pvW_ZYNs+ delta 113 zcmbQm+sDh!{F#@_VeajX?5CLo!WbAB^fU5vQ}t7H(-L!XChM{JZ#H2zX2d4rHTeij NGIog;*6G+JasW^uAp!sZ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/log.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/log.pyc index d210b97174cb49fbd0506298c0ccae2dd1f3d8e8..5fd1124b09b2bf380993fdf3f869e6755d087817 100644 GIT binary patch delta 910 zcmcaLn{oRbMt0`Uyj-c3mp8Is=N1lSU|`VC$j?pHPcBNVs!YqtOr1PY#(lCW&j*}x zHN0za$~Evk!6~<!zZR?9MGN=M{Q@D(I3&F{+lgc_VU?UH<Gq<tTmzS+`{V}61voT< z<X9$GOGV?AH<X@%L*8eys!R+vxy=)0R$})GFkClJRN%+y+RfjUE;3>>5)>nw<y9}^ zmh@CN#%b*2%bMG;nhFZ{2U`2FYXnJt)8)W!B}g(<p9Qz%1_N%~l0rtmaY=e_&M+~+ zCF#ETz3C;auHAgm!k7)KA3<rkL6T#0vi)T2#)1_1IxfYfd9$a}Dt4@rpfK?AV#RJM QNOGC?1niO^D|>x?0qUVM00000 delta 802 zcmdl!hw;{IMt0`Uyj%`*Z*OG3&Mgqcz`&rNk)NBYpQ4+Vn3J>lBeyvthUnyv-0qW` zc-LZ==;V8XUE(-@Ej9_a&2t4pnX$`wi{vt4lX2fHB(8%+CQ$M@rt&~Z@5$4oqOnW( zOV7ZR0Qt{RCK0Q|=07q?n6BMis1Sz5JwSstD=J^a9)z2HR4-$ZDOB*@T&u2+-L%PU zTHCNW%Wbo$_5rL~+&1g!abmINBe&b;3Hq!!WZoI@;E)M6`h!Deg^4K+88frXINX+G z`IZ&aKY^0|n>X4|#%h}T<av%uF|~j~dalzdc5E_kn-_SoVKvNc^MCJ&SY^B?zw`A3 E08J|Y8vp<R diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/mem.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/mem.pyc index 81bb975962c1dd992cb3a97871cedbca6f3738ce..c4343391b200d15a226cc52046ce297a6e8b47e6 100644 GIT binary patch delta 1673 zcmaKs%`3xk9LM)#4;W(e5E;pogRF#!6&ByGg@{>F9@Y$No7K3Gqtgx!K8Zq<+MQ3S zm4$MU+sI|}bnpi(4&o$Sy`5j*_xt^M`u(nw%3Dg&WxnO*c$aUFbn#5%s7j@>%!h(r zizn<}S)L8}ywueo=s>ICDs`CxAFOLmAv@4ML3XE$04Dh)%Z36aIdW1!C}>4L0+?iT z?o<YZ$$Sk=<dy=c6trKW;k3bp)Pi=4?m_I2n9>FvC5uD<yqN?{va>Xdf+d^EQfRM| z22C;G`m=NLR1N|zIlIb;C%IVN3QMBtCN*hm_K-7u)+|7FX2!eq)fU25IZ^k4%dM_2 zKoFgo<VDLn5=p*j?1cm1=_Wgb^wE3`yDzr}AbYURA;vqcuQ>3fZ3_wMrX78sf{$%} z-2YO?CQAH0t(h(#N@cU%3Z3b=8(&Ve=Ny{G#RfFxsAC(ID`~UO4P6KNi`5XuhJwgd z(CTmk2n8LEJVW;VFMf39LSyc9r4W=H9>a~YdwdOzNO1eaiT<ymSn*xryb6B=!QVSj Gg7OPS93<fY delta 1473 zcmZ{j%`3xk9LM*w&14Tv^N{k8nFC?9WMtS@_AA>6vtmiV@@zjVIVlHn;X*z{;@}@p zd~-mGBHD?QY(+V^xsc>$-}Cpq^Q-s6=kxh~zthq~N-}7_&H3KL^oik0Ywg!)G|s7n zI_?~6m{8(zQq&-`>q;d=WZKbRA`qnG+!O*by&Kj<@Z^%&U7iPoWC+Fb)1pLCW!g0M zi-3E1OrtrN{8;ojg+;7LlZjzw+c41Z0yl+Onwf1zl8O^z2d+vMkBETRUM`sjL7aq3 z)8ICIIV<JoqM4$GXuqOI1l-GCX@koNGFH`u^T}6z1kK3fn8U!^qNBW;UI^JqO#vQ< zmDT>iaxzQQTQQ-R#%&yP@B9@d?8&u(r(_pReoQFZoP-gy=#FFHZJC6CNv&U5Lc(pk zP(mG^brJBFX>Xqq2PA&vkIo&ClKIT^;+q!Dxa7d^#%9#ebqFQo2wX$JI^-?v#p=5E zKr#N3%R&k^dkz)pFbVXjz>NPf^T4Ah;lLevLm<c&22I$DrJ^Z7_{uCpS%x`{t%CXa Z$zDg!jA8+9_Bp+jCFXW^9S}v``Uh`s*p2`I diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/param.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/param.pyc index 300adf07e0912abb81c395eab49e516c272d5c0f..f804a69a9f074702fb526631e73d0d01aa742de1 100644 GIT binary patch delta 643 zcmZpQIugas{F#?4wes>t_VaAQ;S3B6`WgATsrt!9iB*+pIhm=G6{I{S>#@(oCAV3g zqlyuSr03>OoX?qXN*eKM;nL}`c?+L4Zb^3mK4zT8t`knjtut5j6>iD(;=VW~Cx=Mx z!Di)V1t|?&nmjizlorC}P>;#n^0-3PbMs&MLYx6N`MA;%Y)%12mFMIq%Kvf6ZMIQO i!0ptpYQeZA7iu`+lJuBtt(Az=%CB05xHaz6aRC50o6La# delta 569 zcmX>S)fC0f{F#@_VeajX?C048LKqkr^fU5vQ}t7H(-L!XCJPF9PBvnnfmLF&8b>7~ zri`PM=jPv>&zZ2x*zsy%(F3$*^ASEPOqtDs0%6S9O*$-`j;S8x;LUBKFLB767Wcs} zGr3rDH-<Hv9i=p|D4(d|yZNLv9~NhULd#elOK5?@L|vf}dzeiAqI3kq?#VzclSNei rW0lyPubP0xVIW(y)q^o*Hc!;(#uNodZiQ9?b}LM@3vp;+)O7{`4DF?Z diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/platformservice.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/platformservice.pyc index c983623f14c9112fa7340dc67dae8cf239564dad..8e52e53c5ddb19fd7b056fbfd10099ba065fafb7 100644 GIT binary patch delta 125 zcmZ3(vxA47`7<w9YUSmP>`Y9;i3|)3`WgATsrt!9iB*+pIhm=G|1bw{&S7d`#36Ya Shj`FrP1Z&na>0{%+2jEY^(n#t delta 113 zcmdnNvxbMA`7<w<!`#~&*_oIG;ushh^fU5vQ}t7H(-L!XCO=>a+MLJK$cR;DatKQ$ PHi^sF1cN3^uqglltwJLh diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/toc.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/toc.pyc index 4f1b78dbfca9968abd4baa1f92115eb83a5a37ac..c4aeffa7a142105eb313e0067d3be5011c1398f6 100644 GIT binary patch delta 468 zcmbPle%_p&`7<w9YUSmP>`$14Lm3zt^fU5vQ}vUJ600iHaxzmVC$hOsc4YpBL(YA2 zA4?%lxiHq>*yJ`RvQ;r+lK@)gzS)SQ5tpRfWKOQvI5fI#_TtvTt?>*`JWh>`yuWd3 x+<b}u2rfzY&2I&{a7+3L^ReKxbCdW4Tsqw*&yWnorE#*e)Fm8p?vrz*jR6~ymy-Yh delta 417 zcmX?aKHr?3`7<w<!`#~&*`F{81Tio$=x5~Trs}8YrX}X&Z2re&!-yd|`5%+p<jE{W z*d^jv|6rBayqV1eyIGqZIGV7^xKEbhdWFp}_st31+E}#A<5`Mb`CQ&#Sd{-`a^L)s u|1ee=x6Qml+&E+kh51>q+jC32AFCes$%iFFuxgoHD0LB=gxloV(k1|6w1t8I diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/toccache.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crazyflie/toccache.pyc index b8a5da1d4d2221ea5b2848d45378c56f3f277164..e5b628ed00701329883b82d40698b14eb32a18cd 100644 GIT binary patch delta 212 zcmaDT`%RXe`7<w9YUSmP?2*jEQ49<W`WgATsrt!9iB*+pIhm=GA9DC?-oxzAgi|t| pEeosU=7$`w7;)(G-mJ!*gi~_zW1ccx8YgezU4cW+XYvj{O#s7kNY(%V delta 187 zcmew+`%sph`7<w<!`#~&*&~?+!WkGC^fU5vQ}t7H(-L!XCO7g0Y(C8F&4eMdS&?lU rrs!lvHlNLAobwnl)B|O_Hyd#$VV9ZwiKh&!mdVF>S71ss@|6MrZCy9B diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/__init__.pyc index d51361206bc0697d66635adddef42367f3445640..47b409e54ba811525f2e198f5b5c5b337b68ad59 100644 GIT binary patch delta 156 zcmew_+$X}${F#?4wes>t_5)19p$rTR`WgATsrt!9iB*+pIhm=OuQRP-#3nKMI+Oe6 YTP)nTC2iQ2<Ce7Iu*4}j`4p!q0OG<l6#xJL delta 141 zcmeAZ`7g}Q{F#@_VeajX><5?xf*2SW^fU5vQ}t7H(-L!XCjV!5->k@-%7{(Id-D?( bcC0e)n_bzKW6Es)&)$G33bJGJO-@q)ND3_G diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/crtpdriver.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/crtpdriver.pyc index ccd50c1a2b57d9278b134e4e69ca71755eafaea9..5db88fa87e5e1b8d9a5c3613c0b188a8e6a7cbf5 100644 GIT binary patch delta 338 zcmcaA^HYYM`7<w9YUSmP>_$w&;S3B6`WgATsrt!9iB*+pIhm=GKl1u+p2oD05vyb) zo9E;SEIGL3Hixpx;L>;>m!`=(*{5NZ1G;4L8jhn_<r+DEVHXEF@Cw%^ta2dp9&^WG Xl?&v#f>pec&0}&cZwgkqkGv@W2c2@` delta 311 zcmew<b5(|&`7<w<!`#~&*^QV4LKqkr^fU5vQ}t7H(-L!XCKqz}Zl1}skP(}V=j3TD zIann&$Fa)b&~lA!8dfcnPq1T3Y%b&w!eP#R&W+g3dBe2{Q(`0cYD~dG4$sLuc)GDk Rcubzhn}SWkcXAS+H~`M7UsC`8 diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/crtpstack.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/crtpstack.pyc index 442e4dafa5e3fe75cdaf89fafdabe6efc3fad89e..ec186b246738c1e481340ff0969dcfadfc5fe543 100644 GIT binary patch delta 466 zcmdm?@j`>0`7<w9YUSmP?CMOyVGIlm`WgATsrt!9iB*+pIhm=GFABSFZe?18OVVd@ zGix;tjUJQ3*p}mz3uQ0EDW}Xa0jC@{XDv>-2b`zy$gxaj<GzSP-hHwjPc{xYkIf%> u4l?49bf3)0zZi#{$7B|P9XRCNCkqSi#v$i1Sxsmc4mtP9=E7Y#<kA69a-IeN delta 422 zcmaE%u|tEM`7<w<!`#~&+0~f@f*BYX^fU5vQ}t7H(-L!XHajxC#1x&(DB?4@leHQ{ zIZ(o5ay;8|ToSC4)7T5KOY-w_PPXP~$0f-+S&6d(yX05SQ`jY>xUXVLI5K%m_TtIH zlmI$?Ge7S^Mobxy7H$4Tm=Yl0Y6$GWlmO|l7Tkp?0n!m5ghc|RBUQK)n~rn<WaW5F diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/debugdriver.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/debugdriver.pyc index 6b2576f59196bc4b770a3d5df22a1ff1427fd798..f97e1180c96b4e355311a8106d298493719a4c42 100644 GIT binary patch delta 1043 zcmca~lX2fIMt0`Uyj-c3mp8Ikvk6BqFfiz6<maa9Cl@7FRi@=+rcT~y<Td$&0?XtF zY}GjBx3U*ul{=W?wYibwg%D23!_pDVSS3NWmda=0l(STb#U;1-gF-GVPRZ?RwT!qV zC--U0$0^sYc^jwP9<6+=av=Y=YVTsgB{_MfUN0`W%?<jBSi@%XMk9ah{sUPTWs!na z*JO~Sgw1E{o(D;$+Ua69cB7H!=GV?;SaohLbQNd8>4it0&p2>ODg}SXY9z>|lZ!)h zacZ;*yNcV&%xFQ}re2BJip$i=k7E;X$oXwv821);9KJ{_z@gD=^QI(A+^%s=$-$;^ j^TCw;xTEk^1_y2vZL<8anFx;ir&)H`HNrA@V@@Cd#;|dV delta 931 zcmdmYi}BJ;Mt0`Uyj%`*Z*OF;W)lcyU|`VC$j?pHPti?F%*mNt$nG`yK3hFDi9MKt zj5c1IyEtA5VU?MDK#yhfW$6%ROj(dEE%I5I5{wGVF$ICDH?u0{vSODxuU5;5Rc7)^ zjrrImmTKO{CgC^vp;k7g1jv&swRbULl>vIP7puhPRr-q9eZE=4m=%j(z+q{Tf~jXS zqm3=5<(mWT%CVSI$nLpW#ia~;h;07udKT0C$sn5*y`FJk_eV<bcPyp>^-SIonu}da zQ`l7&tTNyvu_Kxnhk;75Td`|1iA%tgP)zmP{59?^X3&5<G}%6>08<Odr##7)IIIVz q*U8ILGBC7lR!rTGBiL*+IdB-ZD9aziAaF?gW!quV0?H9Db3y?h;2Pin diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/exceptions.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/exceptions.pyc index 60f4731de97ab8939d73b92c20b3cf87f32cdbfe..eaceba555ada6016b0e18416fa742354f22f4dc5 100644 GIT binary patch delta 96 zcmZ3>v5kYB`7<w9YUSmP?2Jsp;S3B6`WgATsrt!9iB*+pIhm=G`I$W@Co;{$A-4jD KxW{CE7C8Wdz8xX} delta 87 zcmdnSv6h3K`7<w<!`#~&*%_GxLKqkr^fU5vQ}t7H(-L!XCSPFon4HWsAG<^>a{@Mr FGyr@K8r}c^ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/radiodriver.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/radiodriver.pyc index ba8b4dd57c47ce72b0371ab0982658814c939458..ec96f252e92283b12ef806a1e36b4866a655a017 100644 GIT binary patch delta 717 zcmdm+(3;53{F#?4wes>tc77J&2nGfQ{fzwFRQ=?l#Hz})oXph83x&Kk7qDz+!y)Op zxq(}P376#L_X@0=zwyR1;#9DXzYC|_M1j3H<r=tIC$ABFicNm=LLoz(7H-xSVPnRs z%Tb&WR|t4co-JLAO%o_|COgQoOfHitz$1^#ix9mUa`??=md7uDPksjuyFE9*SJ;6w zC?+YF;L<nwtnx%0a$cKvs3_oyaIeV)EG(1F)YstDY@_i9cPLNPU5iuW3_T&7KAFsH GU<ClDC+$@L delta 608 zcmZoo+?&A8{F#@_VeajX?EEYOp$rTR`WgATsro6pX^A;GlNsf_HW#yOXTy})$m_Ma zom-p<LuT_v-nEPvqLT~xFJlS<4Vk=9U=MbQU4kz$C4df^B>Wsx9ON7q5mshQ8ITv2 ziEqau1G0UWbPYBwev_xm6kwOgkZr>zaT=ST-(+3+TI>?s3Og_*HuCyyR#DuHCHO#Y zHBm0crp0SAi^>E{36Q@(swiMa5GYb7=c#YN(6ZT3!;KX~bTY{5E4phiB|tXZ)f2+u IS|0;T08$FJ+yDRo diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/serialdriver.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/serialdriver.pyc index a750b4443eac55cb030929271f9cd05899348aec..7dccc6413750c3c141518887764df6ca7856b3e1 100644 GIT binary patch delta 181 zcmX@jcbAWy`7<w9YUSmP>^~TVBN-SN^fU5vQ}vUJ600iHaxzmVGqQPYj$}&3DLGk! cB?Xtp$=6uoaLV<uCgYGhheO<JvL?F{04g&$KL7v# delta 163 zcmcc1cbbo#`7<w<!`#~&*?%w!gfTEM=x5~Trs}8YrX}X&O#aB`zd4a90jrGnWO<fk ctXd{NVTr^h;XQdaYZ5jIugOttE!ZS-0JiKjh5!Hn diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/udpdriver.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/udpdriver.pyc index d1bd738f1d44c57b3967c315484bead65cc82ee4..981031d8fb3899920cd996450f5043489367bd4a 100644 GIT binary patch delta 295 zcmaDL{ZE>m`7<w9YUSmP>@G~gVGIlm`WgATsrt!9iB*+pIhm=G9k@I;FJ{`$h(pqS z^G=q3xFkI`^Rvg{l60SZgrg0IsUDLTarWVmn}<W(W3m}{EKa%C+=V#g+$V45S%X8) JWAb)hO#m>_U*G@$ delta 265 zcmew-{Xm+X`7<w<!`#~&*<F|ff*BYX^fU5vQ}t7H(-L!XCSPFl*u0EsKO;67_s#oR z{$a{&zQDE&Qxs^D`{WB8ZP*O*n7om*54*%Ht}yHp-rTX+Bzz{b^W<WaaG!jRXAL$9 JkI7egH33j1RYm{+ diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/usbdriver.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/crtp/usbdriver.pyc index ce85a2d9158d09302e4287d02ca52494a49aea28..00e521d81c13456e1fffd28d828eb77c36f42175 100644 GIT binary patch delta 463 zcmeCO+GWMg{F#?4wes>t_7BX$VGIlm`WgATsrt!9iB*+pIhm=G9Yx$X`>}Mh;E?p# zY{>bB5vOD+_e5Nh?vrDAn{jEJY{9n?m)vGYekYuUZoVaO5SOIK<j+DKxJ;dVSvU@d w+&LWL?wiv@H{i0&eR8h&T3i|z7fLW;m1~q*id7sG3$@ZrxGeLTd|O5z04p+;kN^Mx delta 420 zcmdmG)n&!b{F#@_VeajX>>ro~f*BYX^fU5vQ}t7H(-L!XCI?D*Yz|`SV!<ZkzS)fP zEhBcBTJA|$WjrQl@it-AGTDu96IO}MLHy3x&D#7y-~d(`_sLwsomdT<{8l&~yTme) zc5D(Jn>$3;W3|L%@+9#!7+N+5O1Lv&hyugWeex%%IBXIgn^#LSVzt42GMlUk0Os6% ArvLx| diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/drivers/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/drivers/__init__.pyc index 3a1be3d44723ddc6e2148aa5d17d34b9b6948f6e..439cbca53e07ce314914a57bf924c6c86fc1d6f9 100644 GIT binary patch delta 38 tcmeyz*vQ1r{F#?4wes>r_733)1_lQGjQreG{p6y=s>-yS%+!hV;{otc4Ke@# delta 35 rcmZo<`p3x5{F#@_VeajT>>UE33=9nV8Tq-X`YF0;i8(nF7sUer$4m>I diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/drivers/cfusb.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/drivers/cfusb.pyc index 8c8e137aa5f0c8add477e9fb323ae6583c6f6e8d..7b7678b9858a809ce8fbb7a05aa8ac7012a9eab4 100644 GIT binary patch delta 354 zcmaE*+o#9Q{F#?4wes>t_N&aop$rTR`WgATsrt!9iB*+pIhm=GH}bh}HfEWQQ*yE* z$7x&|Cp&X~z$w?oH3O$yCHEOza+~Myurgtj+`N&G1*-(e3zK;SXJgX@lylqsS1^bX Xr{q#$K3tOSo4G`ta7s>IEanaXpX_xp delta 319 zcmeCvd!@_H{F#@_VeajX>{pouf*2SW^fU5vQ}t7H(-L!XCOdMwZ#H9@j$LN5I>%|O zS|<B&e!wm<jcW#m#AZisVMYv5u+{5$SedZP@bd4)u4l4};B0JK+%`)H1!2|Vw)wCy TA66On&Dx?)*kvXk7jp*yKT})Z diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/drivers/crazyradio.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/drivers/crazyradio.pyc index fc0771ba3cc7a0596f8cb15beeb6f4c3ad6c6b0c..d1e265c341b2a469db40734587773f7e90c769e3 100644 GIT binary patch delta 579 zcmbQ{eaV}h`7<w9YUSmP>|89uQ49<W`WgATsrt!9iB*+pIhm=O6<LfKu}Mr;Wbxj- zo>hbmhosMDc^-9KI(;TD;(dZcqxa^Ad|J3PdQVOhID$*#<W|95IOS#uUBV@|`M9t$ zE(?7oyNNEvrE#*G*kPP<DdNF6<a{;@OUPlhaI>T28>|wO9VJ6IPm&g8#$lxQWG4Bq fxa2kmDdb@{6%>ckN_@B_Ta*)VN%~B7R1F0HSLU=E delta 530 zcmccQJ<Xe)`7<w<!`#~&*|}H*!WkGC^fU5vQ}t7H(-L!XCL5~yOfFz~j!nXQ^Hx?7 zHf%Bhn{{}U8L`RuOkT(P1e=8S<_~;YShaXht`InaRm<dAg1fLwY!bSJRbulaVO;J? z5nYN^%j9&i!`LM{#DlR(_-wY4ki+T|P)M?D-Yq!?kL)gKDQ0Y@dQUcz|B6*&bE`rg URs+2^2P*O5klCx8h*f4G06HX{jsO4v diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/utils/__init__.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/utils/__init__.pyc index 9a836124b1252f7c20851b151691a737f68a4bde..7c1192880b3f121662f5fcb0f624294c7bba6b2c 100644 GIT binary patch delta 38 ucmey!_=S<3`7<w9YUSmL?6tyS3=9nV8Tq-X`pHF!Rh4NunW+<}!~y{Q9}Rr~ delta 35 rcmeyu_>qyF`7<w<!`#~w*=q%Y85kJ!GxBp&^;2}y5_57UPLBlu)Da8l diff --git a/pps_ws/src/d_fall_pps/crazyradio/cflib/utils/callbacks.pyc b/pps_ws/src/d_fall_pps/crazyradio/cflib/utils/callbacks.pyc index 74e35185cd8928cfd392adc026a7e4c35c1703a1..79876aa959683ac1070d0dc0f785b469ba986413 100644 GIT binary patch delta 180 zcmX@fdz+V?`7<w9YUSmP?0t;F;S3B6`WgATsrt!9iB*+pIhm=GZ!>vLe#dwhhum8n e;+~TgS&rhAvu91iA?GpqFKYx2InT-K*rWmb(msd) delta 163 zcmcc3dy<!(`7<w<!`#~&+4~p;LKqkr^fU5vQ}t7H(-L!XCO>5IoP2<dW%5_Xo7g1Z fVhC=2$jpbs9B<Y%4CO!zJSOw7MPQQv*(?nJ*H<&~ -- GitLab