cfclient 2017.4__py3-none-any.whl → 2025.12.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. cfclient/__init__.py +16 -11
  2. cfclient/configs/config.json +4 -3
  3. cfclient/configs/input/Generic_OS_X.json +1 -0
  4. cfclient/configs/input/Joystick.json +1 -0
  5. cfclient/configs/input/PS3_Mode_1.json +1 -0
  6. cfclient/configs/input/PS3_Mode_2.json +1 -0
  7. cfclient/configs/input/PS3_Mode_3.json +1 -0
  8. cfclient/configs/input/PS4_Mode_1.json +1 -0
  9. cfclient/configs/input/PS4_Mode_2.json +1 -0
  10. cfclient/configs/input/PS4_shoulder_btns_yaw.json +1 -0
  11. cfclient/configs/input/xbox360_mode1.json +1 -0
  12. cfclient/configs/log/PID_tuning/Attitude.json +46 -0
  13. cfclient/configs/log/PID_tuning/Attitude_rate.json +46 -0
  14. cfclient/configs/log/PID_tuning/Position.json +46 -0
  15. cfclient/configs/log/PID_tuning/Velocity.json +46 -0
  16. cfclient/configs/log/PID_tuning_components/Pitch.json +22 -0
  17. cfclient/configs/log/PID_tuning_components/Pitch_rate.json +22 -0
  18. cfclient/configs/log/PID_tuning_components/Position_x.json +22 -0
  19. cfclient/configs/log/PID_tuning_components/Position_y.json +22 -0
  20. cfclient/configs/log/PID_tuning_components/Position_z.json +22 -0
  21. cfclient/configs/log/PID_tuning_components/Roll.json +22 -0
  22. cfclient/configs/log/PID_tuning_components/Roll_rate.json +22 -0
  23. cfclient/configs/log/PID_tuning_components/Velocity_x.json +22 -0
  24. cfclient/configs/log/PID_tuning_components/Velocity_y.json +22 -0
  25. cfclient/configs/log/PID_tuning_components/Velocity_z.json +22 -0
  26. cfclient/configs/log/PID_tuning_components/Yaw.json +22 -0
  27. cfclient/configs/log/PID_tuning_components/Yaw_rate.json +22 -0
  28. cfclient/gui.py +44 -9
  29. cfclient/headless.py +3 -12
  30. cfclient/resources/log_param_doc.json +1 -0
  31. cfclient/ui/connectivity_manager.py +198 -0
  32. cfclient/ui/dialogs/about.py +53 -36
  33. cfclient/ui/dialogs/about.ui +23 -3
  34. cfclient/ui/dialogs/anchor_position_dialog.py +252 -0
  35. cfclient/ui/dialogs/anchor_position_dialog.ui +138 -0
  36. cfclient/ui/dialogs/basestation_mode_dialog.py +185 -0
  37. cfclient/ui/dialogs/basestation_mode_dialog.ui +186 -0
  38. cfclient/ui/dialogs/bootloader.py +448 -85
  39. cfclient/ui/dialogs/bootloader.ui +387 -134
  40. cfclient/ui/dialogs/cf2config.py +4 -4
  41. cfclient/ui/dialogs/cf2config.ui +3 -4
  42. cfclient/ui/dialogs/inputconfigdialogue.py +24 -19
  43. cfclient/ui/dialogs/inputconfigdialogue.ui +53 -30
  44. cfclient/ui/dialogs/lighthouse_bs_geometry_dialog.py +220 -0
  45. cfclient/ui/dialogs/lighthouse_bs_geometry_dialog.ui +110 -0
  46. cfclient/ui/dialogs/lighthouse_system_type_dialog.py +93 -0
  47. cfclient/ui/dialogs/lighthouse_system_type_dialog.ui +121 -0
  48. cfclient/ui/dialogs/logconfigdialogue.py +401 -101
  49. cfclient/ui/dialogs/logconfigdialogue.ui +117 -72
  50. cfclient/ui/icons/bl.webp +0 -0
  51. cfclient/ui/icons/bolt.webp +0 -0
  52. cfclient/ui/icons/cf21.webp +0 -0
  53. cfclient/ui/icons/checkmark_black.png +0 -0
  54. cfclient/ui/icons/checkmark_white.png +0 -0
  55. cfclient/ui/icons/create.png +0 -0
  56. cfclient/ui/icons/delete.png +0 -0
  57. cfclient/ui/icons/flapper.webp +0 -0
  58. cfclient/ui/icons/tag.webp +0 -0
  59. cfclient/ui/main.py +328 -258
  60. cfclient/ui/main.ui +184 -80
  61. cfclient/ui/pluginhelper.py +7 -1
  62. cfclient/ui/pose_logger.py +116 -0
  63. cfclient/ui/tab_toolbox.py +208 -0
  64. cfclient/ui/tabs/ColorLEDTab.py +752 -0
  65. cfclient/ui/tabs/ConsoleTab.py +48 -13
  66. cfclient/ui/{toolboxes → tabs}/CrtpSharkToolbox.py +19 -34
  67. cfclient/ui/tabs/ExampleTab.py +9 -16
  68. cfclient/ui/tabs/FlightTab.py +437 -325
  69. cfclient/ui/tabs/GpsTab.py +14 -20
  70. cfclient/ui/tabs/LEDRingTab.py +277 -0
  71. cfclient/ui/tabs/LogBlockDebugTab.py +20 -27
  72. cfclient/ui/tabs/LogBlockTab.py +35 -35
  73. cfclient/ui/tabs/LogClientTab.py +85 -0
  74. cfclient/ui/tabs/LogTab.py +50 -27
  75. cfclient/ui/tabs/ParamTab.py +443 -57
  76. cfclient/ui/tabs/PlotTab.py +23 -25
  77. cfclient/ui/tabs/TuningTab.py +292 -0
  78. cfclient/ui/tabs/__init__.py +12 -2
  79. cfclient/ui/tabs/colorLEDTab.ui +624 -0
  80. cfclient/ui/tabs/consoleTab.ui +46 -0
  81. cfclient/ui/tabs/flightActionContainer.ui +103 -0
  82. cfclient/ui/tabs/flightTab.ui +724 -237
  83. cfclient/ui/tabs/{ledTab.ui → ledRingTab.ui} +63 -46
  84. cfclient/ui/tabs/lighthouse_tab.py +714 -0
  85. cfclient/ui/tabs/lighthouse_tab.ui +430 -0
  86. cfclient/ui/tabs/locopositioning_tab.py +606 -389
  87. cfclient/ui/tabs/locopositioning_tab.ui +370 -253
  88. cfclient/ui/tabs/logClientTab.ui +52 -0
  89. cfclient/ui/tabs/logTab.ui +1 -1
  90. cfclient/ui/tabs/paramTab.ui +204 -3
  91. cfclient/ui/tabs/tuningTab.ui +773 -0
  92. cfclient/ui/widgets/ai.py +37 -39
  93. cfclient/ui/widgets/hexspinbox.py +16 -10
  94. cfclient/ui/widgets/plotter.ui +39 -47
  95. cfclient/ui/widgets/plotwidget.py +57 -22
  96. cfclient/ui/widgets/super_slider.py +112 -0
  97. cfclient/ui/wizards/__init__.py +0 -0
  98. cfclient/ui/wizards/bslh_1.png +0 -0
  99. cfclient/ui/wizards/bslh_2.png +0 -0
  100. cfclient/ui/wizards/bslh_3.png +0 -0
  101. cfclient/ui/wizards/bslh_4.png +0 -0
  102. cfclient/ui/wizards/bslh_5.png +0 -0
  103. cfclient/ui/wizards/lighthouse_geo_bs_estimation_wizard.py +465 -0
  104. cfclient/utils/config_manager.py +5 -4
  105. cfclient/utils/input/__init__.py +77 -19
  106. cfclient/utils/input/inputinterfaces/wiimote.py +2 -2
  107. cfclient/utils/input/inputreaderinterface.py +17 -7
  108. cfclient/utils/input/inputreaders/__init__.py +17 -0
  109. cfclient/utils/logconfigreader.py +245 -25
  110. cfclient/utils/logdatawriter.py +3 -1
  111. cfclient/utils/periodictimer.py +1 -1
  112. cfclient/utils/ui.py +336 -0
  113. cfclient/utils/zmq_led_driver.py +5 -0
  114. cfclient/utils/zmq_param.py +6 -0
  115. cfclient/version.py +34 -1
  116. cfclient-2025.12.1.dist-info/METADATA +70 -0
  117. cfclient-2025.12.1.dist-info/RECORD +152 -0
  118. {cfclient-2017.4.dist-info → cfclient-2025.12.1.dist-info}/WHEEL +1 -1
  119. {cfclient-2017.4.dist-info → cfclient-2025.12.1.dist-info}/entry_points.txt +0 -1
  120. cfclient-2025.12.1.dist-info/licenses/LICENSE.txt +350 -0
  121. {cfclient-2017.4.dist-info → cfclient-2025.12.1.dist-info}/top_level.txt +1 -0
  122. cfconfig/Makefile +51 -0
  123. cfconfig/configblock.py +111 -0
  124. cfloader/__init__.py +41 -55
  125. cfzmq/__init__.py +22 -14
  126. cfclient/ui/dialogs/cf1config.py +0 -265
  127. cfclient/ui/dialogs/cf1config.ui +0 -260
  128. cfclient/ui/tab.py +0 -96
  129. cfclient/ui/tabs/LEDTab.py +0 -169
  130. cfclient/ui/toolboxes/ConsoleToolbox.py +0 -69
  131. cfclient/ui/toolboxes/DebugDriverToolbox.py +0 -107
  132. cfclient/ui/toolboxes/__init__.py +0 -45
  133. cfclient/ui/toolboxes/consoleToolbox.ui +0 -62
  134. cfclient/ui/toolboxes/debugDriverToolbox.ui +0 -86
  135. cfclient-2017.4.dist-info/DESCRIPTION.rst +0 -3
  136. cfclient-2017.4.dist-info/METADATA +0 -22
  137. cfclient-2017.4.dist-info/RECORD +0 -104
  138. cfclient-2017.4.dist-info/metadata.json +0 -1
  139. /cfclient/{icon-256.png → ui/icons/icon-256.png} +0 -0
  140. /cfclient/ui/{toolboxes → tabs}/crtpSharkToolbox.ui +0 -0
@@ -0,0 +1,208 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ #
4
+ # || ____ _ __
5
+ # +------+ / __ )(_) /_______________ _____ ___
6
+ # | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \
7
+ # +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/
8
+ # || || /_____/_/\__/\___/_/ \__,_/ /___/\___/
9
+ #
10
+ # Copyright (C) 2011-2023 Bitcraze AB
11
+ #
12
+ # Crazyflie Nano Quadcopter Client
13
+ #
14
+ # This program is free software; you can redistribute it and/or
15
+ # modify it under the terms of the GNU General Public License
16
+ # as published by the Free Software Foundation; either version 2
17
+ # of the License, or (at your option) any later version.
18
+ #
19
+ # This program is distributed in the hope that it will be useful,
20
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
21
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
+ # GNU General Public License for more details.
23
+
24
+ # You should have received a copy of the GNU General Public License along with
25
+ # this program; if not, write to the Free Software Foundation, Inc.,
26
+ # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27
+
28
+ """
29
+ Superclass for all tabs that implements common functions.
30
+ """
31
+
32
+ import logging
33
+
34
+ from PyQt6 import QtWidgets
35
+ from PyQt6.QtCore import pyqtSignal
36
+ from PyQt6.QtCore import Qt
37
+ from PyQt6.QtGui import QCloseEvent
38
+
39
+ from cfclient.utils.config import Config
40
+
41
+ __author__ = 'Bitcraze AB'
42
+ __all__ = ['TabToolbox']
43
+
44
+ logger = logging.getLogger(__name__)
45
+
46
+
47
+ class TabToolbox(QtWidgets.QWidget):
48
+ """Superclass for all tabs that implements common functions."""
49
+
50
+ CONF_KEY_OPEN_TABS = "open_tabs"
51
+ CONF_KEY_OPEN_TOOLBOXES = "open_toolboxes"
52
+ CONF_KEY_TOOLBOX_AREAS = "toolbox_areas"
53
+
54
+ # Display states
55
+ DS_HIDDEN = 0
56
+ DS_TAB = 1
57
+ DS_TOOLBOX = 2
58
+
59
+ def __init__(self, helper, tab_toolbox_name):
60
+ super(TabToolbox, self).__init__()
61
+ self._helper = helper
62
+ self.tab_toolbox_name = tab_toolbox_name
63
+
64
+ # Dock widget for toolbox behavior
65
+ self.dock_widget = self.ClosingDockWidget(tab_toolbox_name)
66
+ self.dock_widget.tab_toolbox = self
67
+
68
+ self._display_state = self.DS_HIDDEN
69
+
70
+ self._dock_area = self._get_toolbox_area_config()
71
+
72
+ # Do not allow floating toolboxes, it seems to be buggy
73
+ self.dock_widget.setFeatures(QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetClosable |
74
+ QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable)
75
+ # If floating is set in the config, change to right docking area
76
+ if self._dock_area == Qt.DockWidgetArea.NoDockWidgetArea:
77
+ self._dock_area = Qt.DockWidgetArea.RightDockWidgetArea
78
+
79
+ def get_tab_toolbox_name(self):
80
+ """Return the name that will be shown in the tab or toolbox"""
81
+ return self.tab_toolbox_name
82
+
83
+ def is_visible(self):
84
+ return self._display_state != self.DS_HIDDEN
85
+
86
+ def get_display_state(self):
87
+ return self._display_state
88
+
89
+ def set_display_state(self, new_display_state):
90
+ if new_display_state != self._display_state:
91
+ self._display_state = new_display_state
92
+ self._update_open_config(new_display_state)
93
+
94
+ if new_display_state == self.DS_HIDDEN:
95
+ self.disable()
96
+ else:
97
+ self.enable()
98
+
99
+ def preferred_dock_area(self):
100
+ return self._dock_area
101
+
102
+ def set_preferred_dock_area(self, area):
103
+ self._dock_area = area
104
+ self._store_toolbox_area_config(area)
105
+
106
+ def enable(self):
107
+ pass
108
+
109
+ def disable(self):
110
+ pass
111
+
112
+ @classmethod
113
+ def read_open_tab_config(cls):
114
+ return cls._read_open_config(TabToolbox.CONF_KEY_OPEN_TABS)
115
+
116
+ @classmethod
117
+ def read_open_toolbox_config(cls):
118
+ return TabToolbox._read_open_config(TabToolbox.CONF_KEY_OPEN_TOOLBOXES)
119
+
120
+ @classmethod
121
+ def _read_open_config(cls, key):
122
+ config = []
123
+ try:
124
+ value = Config().get(key)
125
+ # Python will return a list of an empty string if value is empty, filter it
126
+ config = list(filter(None, value.split(",")))
127
+ except KeyError:
128
+ logger.info(f'No config found for {key}')
129
+
130
+ return config
131
+
132
+ def _update_open_config(self, display_state):
133
+ if display_state == self.DS_HIDDEN:
134
+ self._remove_from_open_config(TabToolbox.CONF_KEY_OPEN_TABS)
135
+ self._remove_from_open_config(TabToolbox.CONF_KEY_OPEN_TOOLBOXES)
136
+ elif display_state == self.DS_TAB:
137
+ self._add_to_open_config(TabToolbox.CONF_KEY_OPEN_TABS)
138
+ self._remove_from_open_config(TabToolbox.CONF_KEY_OPEN_TOOLBOXES)
139
+ elif display_state == self.DS_TOOLBOX:
140
+ self._remove_from_open_config(TabToolbox.CONF_KEY_OPEN_TABS)
141
+ self._add_to_open_config(TabToolbox.CONF_KEY_OPEN_TOOLBOXES)
142
+
143
+ def _add_to_open_config(self, key):
144
+ config = self._read_open_config(key)
145
+ name = self.tab_toolbox_name
146
+
147
+ if name not in config:
148
+ config.append(name)
149
+ self._store_open_config(key, config)
150
+
151
+ def _remove_from_open_config(self, key):
152
+ config = self._read_open_config(key)
153
+ name = self.tab_toolbox_name
154
+
155
+ if name in config:
156
+ config.remove(name)
157
+ self._store_open_config(key, config)
158
+
159
+ def _store_open_config(self, key, config):
160
+ value = ','.join(config)
161
+ Config().set(key, value)
162
+
163
+ def _get_toolbox_area_config(self):
164
+ result = Qt.DockWidgetArea.RightDockWidgetArea
165
+
166
+ config = self._read_toolbox_area_config()
167
+
168
+ if self.tab_toolbox_name in config.keys():
169
+ result = Qt.DockWidgetArea(config[self.tab_toolbox_name])
170
+
171
+ return result
172
+
173
+ def _store_toolbox_area_config(self, area):
174
+ config = self._read_toolbox_area_config()
175
+ config[self.tab_toolbox_name] = area.value
176
+ self._write_toolbox_area_config(config)
177
+
178
+ def _read_toolbox_area_config(self):
179
+ composite_config = []
180
+ try:
181
+ key = self.CONF_KEY_TOOLBOX_AREAS
182
+ value = Config().get(key)
183
+ # Python will return a list of an empty string if value is empty, filter it
184
+ composite_config = list(filter(None, value.split(",")))
185
+ except KeyError:
186
+ logger.info(f'No config found for {key}')
187
+
188
+ config = {}
189
+ for composite in composite_config:
190
+ try:
191
+ parts = composite.split(':')
192
+ config[parts[0]] = int(parts[1])
193
+ except (KeyError, ValueError):
194
+ logger.info(f'Can not understand config {composite}')
195
+
196
+ return config
197
+
198
+ def _write_toolbox_area_config(self, config):
199
+ key = self.CONF_KEY_TOOLBOX_AREAS
200
+ value = ','.join(map(lambda item: f'{item[0]}:{item[1]}', config.items()))
201
+ Config().set(key, value)
202
+
203
+ class ClosingDockWidget(QtWidgets.QDockWidget):
204
+ closed = pyqtSignal()
205
+
206
+ def closeEvent(self, event: QCloseEvent) -> None:
207
+ super(TabToolbox.ClosingDockWidget, self).closeEvent(event)
208
+ self.closed.emit()