class E5PassivePopup(QFrame): """ Class implementing dialog-like popup that displays messages without interrupting the user. """ Boxed = 0 Custom = 128 clicked = pyqtSignal((), (QPoint, )) def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(E5PassivePopup, self).__init__(None) self.__popupStyle = DEFAULT_POPUP_TYPE self.__msgView = None self.__topLayout = None self.__hideDelay = DEFAULT_POPUP_TIME self.__hideTimer = QTimer(self) self.__autoDelete = False self.__fixedPosition = QPoint() self.setWindowFlags(POPUP_FLAGS) self.setFrameStyle(QFrame.Box | QFrame.Plain) self.setLineWidth(2) self.__hideTimer.timeout.connect(self.hide) self.clicked.connect(self.hide) def setView(self, child): """ Public method to set the message view. @param child reference to the widget to set as the message view (QWidget) """ self.__msgView = child self.__topLayout = QVBoxLayout(self) self.__topLayout.addWidget(self.__msgView) self.__topLayout.activate() def view(self): """ Public method to get a reference to the message view. @return reference to the message view (QWidget) """ return self.__msgView def setVisible(self, visible): """ Public method to show or hide the popup. @param visible flag indicating the visibility status (boolean) """ if not visible: super(E5PassivePopup, self).setVisible(visible) return if self.size() != self.sizeHint(): self.resize(self.sizeHint()) if self.__fixedPosition.isNull(): self.__positionSelf() else: self.move(self.__fixedPosition) super(E5PassivePopup, self).setVisible(True) delay = self.__hideDelay if delay < 0: delay = DEFAULT_POPUP_TIME if delay > 0: self.__hideTimer.start(delay) def show(self, p=None): """ Public slot to show the popup. @param p position for the popup (QPoint) """ if p is not None: self.__fixedPosition = p super(E5PassivePopup, self).show() def setTimeout(self, delay): """ Public method to set the delay for the popup is removed automatically. Setting the delay to 0 disables the timeout. If you're doing this, you may want to connect the clicked() signal to the hide() slot. Setting the delay to -1 makes it use the default value. @param delay value for the delay in milliseconds (integer) """ self.__hideDelay = delay if self.__hideTimer.isActive(): if delay: if delay == -1: delay = DEFAULT_POPUP_TIME self.__hideTimer.start(delay) else: self.__hideTimer.stop() def timeout(self): """ Public method to get the delay before the popup is removed automatically. @return the delay before the popup is removed automatically (integer) """ return self.__hideDelay def mouseReleaseEvent(self, evt): """ Protected method to handle a mouse release event. @param evt reference to the mouse event (QMouseEvent) """ self.clicked.emit() self.clicked.emit(evt.pos()) def hideEvent(self, evt): """ Protected method to handle the hide event. @param evt reference to the hide event (QHideEvent) """ self.__hideTimer.stop() def __defaultArea(self): """ Private method to determine the default rectangle to be passed to moveNear(). @return default rectangle (QRect) """ return QRect(100, 100, 200, 200) def __positionSelf(self): """ Private method to position the popup. """ self.__moveNear(self.__defaultArea()) def __moveNear(self, target): """ Private method to move the popup to be adjacent to the specified rectangle. @param target rectangle to be placed at (QRect) """ pos = self.__calculateNearbyPoint(target) self.move(pos.x(), pos.y()) def __calculateNearbyPoint(self, target): """ Private method to calculate the position to place the popup near the specified rectangle. @param target rectangle to be placed at (QRect) @return position to place the popup (QPoint) """ pos = target.topLeft() x = pos.x() y = pos.y() w = self.minimumSizeHint().width() h = self.minimumSizeHint().height() r = QApplication.desktop().screenGeometry( QPoint(x + w // 2, y + h // 2)) if x < r.center().x(): x += target.width() else: x -= w # It's apparently trying to go off screen, so display it ALL at the # bottom. if (y + h) > r.bottom(): y = r.bottom() - h if (x + w) > r.right(): x = r.right() - w if y < r.top(): y = r.top() if x < r.left(): x = r.left() return QPoint(x, y)
class IMU(PluginBase, Ui_IMU): def __init__(self, *args): PluginBase.__init__(self, BrickIMU, *args) self.setupUi(self) self.imu = self.device # the firmware version of a Brick can (under common circumstances) not # change during the lifetime of a Brick plugin. therefore, it's okay to # make final decisions based on it here self.has_status_led = self.firmware_version >= (2, 3, 1) self.acc_x = CurveValueWrapper() self.acc_y = CurveValueWrapper() self.acc_z = CurveValueWrapper() self.mag_x = CurveValueWrapper() self.mag_y = CurveValueWrapper() self.mag_z = CurveValueWrapper() self.gyr_x = CurveValueWrapper() self.gyr_y = CurveValueWrapper() self.gyr_z = CurveValueWrapper() self.temp = CurveValueWrapper() self.roll = None self.pitch = None self.yaw = None self.qua_x = None self.qua_y = None self.qua_z = None self.qua_w = None self.all_data_valid = False self.quaternion_valid = False self.orientation_valid = False self.update_timer = QTimer(self) self.update_timer.timeout.connect(self.update_data) self.cbe_all_data = CallbackEmulator(self.imu.get_all_data, None, self.cb_all_data, self.increase_error_count, expand_result_tuple_for_callback=True, use_result_signal=False) self.cbe_orientation = CallbackEmulator(self.imu.get_orientation, None, self.cb_orientation, self.increase_error_count, expand_result_tuple_for_callback=True, use_result_signal=False) self.cbe_quaternion = CallbackEmulator(self.imu.get_quaternion, None, self.cb_quaternion, self.increase_error_count, expand_result_tuple_for_callback=True, use_result_signal=False) self.imu_gl = IMU3DWidget(self) self.imu_gl.setMinimumSize(150, 150) self.imu_gl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.update_counter = 0 self.mag_plot_widget = PlotWidget("Magnetic Field [mG]", [("X", Qt.red, self.mag_x, str), ("Y", Qt.darkGreen, self.mag_y, str), ("Z", Qt.blue, self.mag_z, str)], clear_button=self.clear_graphs, key='right-no-icon', y_resolution=5) self.acc_plot_widget = PlotWidget("Acceleration [mg]", [("X", Qt.red, self.acc_x, str), ("Y", Qt.darkGreen, self.acc_y, str), ("Z", Qt.blue, self.acc_z, str)], clear_button=self.clear_graphs, key='right-no-icon', y_resolution=5) self.gyr_plot_widget = PlotWidget("Angular Velocity [°/s]", [("X", Qt.red, self.gyr_x, str), ("Y", Qt.darkGreen, self.gyr_y, str), ("Z", Qt.blue, self.gyr_z, str)], clear_button=self.clear_graphs, key='right-no-icon', y_resolution=0.05) self.temp_plot_widget = PlotWidget("Temperature [°C]", [("t", Qt.red, self.temp, str)], clear_button=self.clear_graphs, key=None, y_resolution=0.01) self.mag_plot_widget.setMinimumSize(250, 250) self.acc_plot_widget.setMinimumSize(250, 250) self.gyr_plot_widget.setMinimumSize(250, 250) self.temp_plot_widget.setMinimumSize(250, 250) self.orientation_label = QLabel('Position your IMU Brick as shown in the image above, then press "Save Orientation".') self.orientation_label.setWordWrap(True) self.orientation_label.setAlignment(Qt.AlignHCenter) self.gl_layout = QVBoxLayout() self.gl_layout.addWidget(self.imu_gl) self.gl_layout.addWidget(self.orientation_label) self.layout_top.addWidget(self.gyr_plot_widget) self.layout_top.addWidget(self.acc_plot_widget) self.layout_top.addWidget(self.mag_plot_widget) self.layout_bottom.addLayout(self.gl_layout) self.layout_bottom.addWidget(self.temp_plot_widget) self.save_orientation.clicked.connect(self.save_orientation_clicked) self.calibrate.clicked.connect(self.calibrate_clicked) self.led_button.clicked.connect(self.led_clicked) self.speed_spinbox.editingFinished.connect(self.speed_finished) width = QFontMetrics(self.gyr_x_label.font()).boundingRect('-XXXX.X').width() self.gyr_x_label.setMinimumWidth(width) self.gyr_y_label.setMinimumWidth(width) self.gyr_z_label.setMinimumWidth(width) self.calibrate = None self.alive = True if self.has_status_led: self.status_led_action = QAction('Status LED', self) self.status_led_action.setCheckable(True) self.status_led_action.toggled.connect(lambda checked: self.imu.enable_status_led() if checked else self.imu.disable_status_led()) self.set_configs([(0, None, [self.status_led_action])]) else: self.status_led_action = None reset = QAction('Reset', self) reset.triggered.connect(self.imu.reset) self.set_actions([(0, None, [reset])]) def save_orientation_clicked(self): self.imu_gl.save_orientation() self.orientation_label.hide() def cleanup_gl(self): self.state = self.imu_gl.get_state() self.imu_gl.hide() self.imu_gl.cleanup() def restart_gl(self): self.imu_gl = IMU3DWidget() self.imu_gl.setMinimumSize(150, 150) self.imu_gl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.gl_layout.addWidget(self.imu_gl) self.imu_gl.show() self.save_orientation.clicked.connect(self.save_orientation_clicked) self.imu_gl.set_state(self.state) def start(self): if not self.alive: return if self.has_status_led: async_call(self.imu.is_status_led_enabled, None, self.status_led_action.setChecked, self.increase_error_count) self.parent().add_callback_on_untab(lambda x: self.cleanup_gl(), 'imu_cleanup_on_untab') self.parent().add_callback_post_untab(lambda x: self.restart_gl(), 'imu_restart_post_untab') self.parent().add_callback_on_tab(lambda x: self.cleanup_gl(), 'imu_cleanup_on_tab') self.parent().add_callback_post_tab(lambda x: self.restart_gl(), 'imu_restart_post_tab') self.gl_layout.activate() self.cbe_all_data.set_period(100) self.cbe_orientation.set_period(100) self.cbe_quaternion.set_period(50) self.update_timer.start(50) async_call(self.imu.get_convergence_speed, None, self.speed_spinbox.setValue, self.increase_error_count) self.mag_plot_widget.stop = False self.acc_plot_widget.stop = False self.gyr_plot_widget.stop = False self.temp_plot_widget.stop = False def stop(self): self.mag_plot_widget.stop = True self.acc_plot_widget.stop = True self.gyr_plot_widget.stop = True self.temp_plot_widget.stop = True self.update_timer.stop() self.cbe_all_data.set_period(0) self.cbe_orientation.set_period(0) self.cbe_quaternion.set_period(0) def destroy(self): self.alive = False self.cleanup_gl() if self.calibrate: self.calibrate.close() @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickIMU.DEVICE_IDENTIFIER def cb_all_data(self, acc_x, acc_y, acc_z, mag_x, mag_y, mag_z, gyr_x, gyr_y, gyr_z, temp): self.acc_x.value = acc_x self.acc_y.value = acc_y self.acc_z.value = acc_z self.mag_x.value = mag_x self.mag_y.value = mag_y self.mag_z.value = mag_z self.gyr_x.value = gyr_x / 14.375 self.gyr_y.value = gyr_y / 14.375 self.gyr_z.value = gyr_z / 14.375 self.temp.value = temp / 100.0 self.all_data_valid = True def cb_quaternion(self, x, y, z, w): self.qua_x = x self.qua_y = y self.qua_z = z self.qua_w = w self.quaternion_valid = True def cb_orientation(self, roll, pitch, yaw): self.roll = roll / 100.0 self.pitch = pitch / 100.0 self.yaw = yaw / 100.0 self.orientation_valid = True def led_clicked(self): if 'On' in self.led_button.text().replace('&', ''): self.led_button.setText('Turn LEDs Off') self.imu.leds_on() elif 'Off' in self.led_button.text().replace('&', ''): self.led_button.setText('Turn LEDs On') self.imu.leds_off() def update_data(self): self.update_counter += 1 if self.quaternion_valid: self.imu_gl.update_orientation(self.qua_w, self.qua_x, self.qua_y, self.qua_z) if self.update_counter == 2: self.update_counter = 0 if self.all_data_valid and self.orientation_valid: self.acceleration_update(self.acc_x.value, self.acc_y.value, self.acc_z.value) self.magnetometer_update(self.mag_x.value, self.mag_y.value, self.mag_z.value) self.gyroscope_update(self.gyr_x.value, self.gyr_y.value, self.gyr_z.value) self.orientation_update(self.roll, self.pitch, self.yaw) self.temperature_update(self.temp.value) def acceleration_update(self, x, y, z): self.acc_y_label.setText(format(x, '.1f')) self.acc_x_label.setText(format(y, '.1f')) self.acc_z_label.setText(format(z, '.1f')) def magnetometer_update(self, x, y, z): # Earth magnetic field: 0.5 Gauss self.mag_x_label.setText(format(x, '.1f')) self.mag_y_label.setText(format(y, '.1f')) self.mag_z_label.setText(format(z, '.1f')) def gyroscope_update(self, x, y, z): self.gyr_x_label.setText(format(x, '.1f')) self.gyr_y_label.setText(format(y, '.1f')) self.gyr_z_label.setText(format(z, '.1f')) def orientation_update(self, r, p, y): self.roll_label.setText(format(r, '.1f')) self.pitch_label.setText(format(p, '.1f')) self.yaw_label.setText(format(y, '.1f')) def temperature_update(self, t): self.tem_label.setText(format(t, '.1f')) def calibrate_clicked(self): self.stop() if self.calibrate is None: self.calibrate = CalibrateWindow(self) self.calibrate.refresh_values() self.calibrate.show() def speed_finished(self): speed = self.speed_spinbox.value() self.imu.set_convergence_speed(speed)
class E5PassivePopup(QFrame): """ Class implementing dialog-like popup that displays messages without interrupting the user. @signal clicked emitted to indicate a mouse button click """ Boxed = 0 Custom = 128 clicked = pyqtSignal((), (QPoint, )) def __init__(self, parent=None): """ Constructor @param parent reference to the parent widget (QWidget) """ super(E5PassivePopup, self).__init__(None) self.__popupStyle = DEFAULT_POPUP_TYPE self.__msgView = None self.__topLayout = None self.__hideDelay = DEFAULT_POPUP_TIME self.__hideTimer = QTimer(self) self.__autoDelete = False self.__fixedPosition = QPoint() self.setWindowFlags(POPUP_FLAGS) self.setFrameStyle(QFrame.Box | QFrame.Plain) self.setLineWidth(2) self.__hideTimer.timeout.connect(self.hide) self.clicked.connect(self.hide) self.__customData = {} # dictionary to store some custom data def setView(self, child): """ Public method to set the message view. @param child reference to the widget to set as the message view (QWidget) """ self.__msgView = child self.__topLayout = QVBoxLayout(self) self.__topLayout.addWidget(self.__msgView) self.__topLayout.activate() def view(self): """ Public method to get a reference to the message view. @return reference to the message view (QWidget) """ return self.__msgView def setVisible(self, visible): """ Public method to show or hide the popup. @param visible flag indicating the visibility status (boolean) """ if not visible: super(E5PassivePopup, self).setVisible(visible) return if self.size() != self.sizeHint(): self.resize(self.sizeHint()) if self.__fixedPosition.isNull(): self.__positionSelf() else: self.move(self.__fixedPosition) super(E5PassivePopup, self).setVisible(True) delay = self.__hideDelay if delay < 0: delay = DEFAULT_POPUP_TIME if delay > 0: self.__hideTimer.start(delay) def show(self, p=None): """ Public slot to show the popup. @param p position for the popup (QPoint) """ if p is not None: self.__fixedPosition = p super(E5PassivePopup, self).show() def setTimeout(self, delay): """ Public method to set the delay for the popup is removed automatically. Setting the delay to 0 disables the timeout. If you're doing this, you may want to connect the clicked() signal to the hide() slot. Setting the delay to -1 makes it use the default value. @param delay value for the delay in milliseconds (integer) """ self.__hideDelay = delay if self.__hideTimer.isActive(): if delay: if delay == -1: delay = DEFAULT_POPUP_TIME self.__hideTimer.start(delay) else: self.__hideTimer.stop() def timeout(self): """ Public method to get the delay before the popup is removed automatically. @return the delay before the popup is removed automatically (integer) """ return self.__hideDelay def mouseReleaseEvent(self, evt): """ Protected method to handle a mouse release event. @param evt reference to the mouse event (QMouseEvent) """ self.clicked.emit() self.clicked.emit(evt.pos()) def hideEvent(self, evt): """ Protected method to handle the hide event. @param evt reference to the hide event (QHideEvent) """ self.__hideTimer.stop() def __defaultArea(self): """ Private method to determine the default rectangle to be passed to moveNear(). @return default rectangle (QRect) """ return QRect(100, 100, 200, 200) def __positionSelf(self): """ Private method to position the popup. """ self.__moveNear(self.__defaultArea()) def __moveNear(self, target): """ Private method to move the popup to be adjacent to the specified rectangle. @param target rectangle to be placed at (QRect) """ pos = self.__calculateNearbyPoint(target) self.move(pos.x(), pos.y()) def __calculateNearbyPoint(self, target): """ Private method to calculate the position to place the popup near the specified rectangle. @param target rectangle to be placed at (QRect) @return position to place the popup (QPoint) """ pos = target.topLeft() x = pos.x() y = pos.y() w = self.minimumSizeHint().width() h = self.minimumSizeHint().height() if qVersionTuple() >= (5, 10, 0): r = (QApplication.screenAt(QPoint(x + w // 2, y + h // 2)).geometry()) else: r = QApplication.desktop().screenGeometry( QPoint(x + w // 2, y + h // 2)) if x < r.center().x(): x += target.width() else: x -= w # It's apparently trying to go off screen, so display it ALL at the # bottom. if (y + h) > r.bottom(): y = r.bottom() - h if (x + w) > r.right(): x = r.right() - w if y < r.top(): y = r.top() if x < r.left(): x = r.left() return QPoint(x, y) def setCustomData(self, key, data): """ Public method to set some custom data. @param key key for the custom data @type str @param data data to be stored @type any """ self.__customData[key] = data def getCustomData(self, key): """ Public method to get some custom data. @param key key for the custom data @type str @return stored data @rtype any """ return self.__customData[key]
class IMU(PluginBase, Ui_IMU): def __init__(self, *args): PluginBase.__init__(self, BrickIMU, *args) self.setupUi(self) self.imu = self.device # the firmware version of a Brick can (under common circumstances) not # change during the lifetime of a Brick plugin. therefore, it's okay to # make final decisions based on it here self.has_status_led = self.firmware_version >= (2, 3, 1) self.acc_x = CurveValueWrapper() self.acc_y = CurveValueWrapper() self.acc_z = CurveValueWrapper() self.mag_x = CurveValueWrapper() self.mag_y = CurveValueWrapper() self.mag_z = CurveValueWrapper() self.gyr_x = CurveValueWrapper() self.gyr_y = CurveValueWrapper() self.gyr_z = CurveValueWrapper() self.temp = CurveValueWrapper() self.roll = None self.pitch = None self.yaw = None self.qua_x = None self.qua_y = None self.qua_z = None self.qua_w = None self.all_data_valid = False self.quaternion_valid = False self.orientation_valid = False self.update_timer = QTimer(self) self.update_timer.timeout.connect(self.update_data) self.cbe_all_data = CallbackEmulator( self.imu.get_all_data, None, self.cb_all_data, self.increase_error_count, expand_result_tuple_for_callback=True, use_result_signal=False) self.cbe_orientation = CallbackEmulator( self.imu.get_orientation, None, self.cb_orientation, self.increase_error_count, expand_result_tuple_for_callback=True, use_result_signal=False) self.cbe_quaternion = CallbackEmulator( self.imu.get_quaternion, None, self.cb_quaternion, self.increase_error_count, expand_result_tuple_for_callback=True, use_result_signal=False) self.imu_gl = IMU3DWidget(self) self.imu_gl.setMinimumSize(150, 150) self.imu_gl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.update_counter = 0 self.mag_plot_widget = PlotWidget( "Magnetic Field [µT]", [("X", Qt.red, self.mag_x, str), ("Y", Qt.darkGreen, self.mag_y, str), ("Z", Qt.blue, self.mag_z, str)], clear_button=self.clear_graphs, key='right-no-icon', y_resolution=5) self.acc_plot_widget = PlotWidget( "Acceleration [mg]", [("X", Qt.red, self.acc_x, str), ("Y", Qt.darkGreen, self.acc_y, str), ("Z", Qt.blue, self.acc_z, str)], clear_button=self.clear_graphs, key='right-no-icon', y_resolution=5) self.gyr_plot_widget = PlotWidget( "Angular Velocity [°/s]", [("X", Qt.red, self.gyr_x, str), ("Y", Qt.darkGreen, self.gyr_y, str), ("Z", Qt.blue, self.gyr_z, str)], clear_button=self.clear_graphs, key='right-no-icon', y_resolution=0.05) self.temp_plot_widget = PlotWidget("Temperature [°C]", [("t", Qt.red, self.temp, str)], clear_button=self.clear_graphs, key=None, y_resolution=0.01) self.mag_plot_widget.setMinimumSize(250, 250) self.acc_plot_widget.setMinimumSize(250, 250) self.gyr_plot_widget.setMinimumSize(250, 250) self.temp_plot_widget.setMinimumSize(250, 250) self.orientation_label = QLabel( 'Position your IMU Brick as shown in the image above, then press "Save Orientation".' ) self.orientation_label.setWordWrap(True) self.orientation_label.setAlignment(Qt.AlignHCenter) self.gl_layout = QVBoxLayout() self.gl_layout.addWidget(self.imu_gl) self.gl_layout.addWidget(self.orientation_label) self.layout_top.addWidget(self.gyr_plot_widget) self.layout_top.addWidget(self.acc_plot_widget) self.layout_top.addWidget(self.mag_plot_widget) self.layout_bottom.addLayout(self.gl_layout) self.layout_bottom.addWidget(self.temp_plot_widget) self.save_orientation.clicked.connect(self.save_orientation_clicked) self.calibrate.clicked.connect(self.calibrate_clicked) self.led_button.clicked.connect(self.led_clicked) self.speed_spinbox.editingFinished.connect(self.speed_finished) width = QFontMetrics( self.gyr_x_label.font()).boundingRect('-XXXX.X').width() self.gyr_x_label.setMinimumWidth(width) self.gyr_y_label.setMinimumWidth(width) self.gyr_z_label.setMinimumWidth(width) self.calibrate = None self.alive = True if self.has_status_led: self.status_led_action = QAction('Status LED', self) self.status_led_action.setCheckable(True) self.status_led_action.toggled.connect( lambda checked: self.imu.enable_status_led() if checked else self.imu.disable_status_led()) self.set_configs([(0, None, [self.status_led_action])]) else: self.status_led_action = None reset = QAction('Reset', self) reset.triggered.connect(self.imu.reset) self.set_actions([(0, None, [reset])]) def save_orientation_clicked(self): self.imu_gl.save_orientation() self.orientation_label.hide() def cleanup_gl(self): self.state = self.imu_gl.get_state() self.imu_gl.hide() self.imu_gl.cleanup() def restart_gl(self): self.imu_gl = IMU3DWidget() self.imu_gl.setMinimumSize(150, 150) self.imu_gl.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.gl_layout.addWidget(self.imu_gl) self.imu_gl.show() self.save_orientation.clicked.connect(self.save_orientation_clicked) self.imu_gl.set_state(self.state) def start(self): if not self.alive: return if self.has_status_led: async_call(self.imu.is_status_led_enabled, None, self.status_led_action.setChecked, self.increase_error_count) self.parent().add_callback_on_untab(lambda x: self.cleanup_gl(), 'imu_cleanup_on_untab') self.parent().add_callback_post_untab(lambda x: self.restart_gl(), 'imu_restart_post_untab') self.parent().add_callback_on_tab(lambda x: self.cleanup_gl(), 'imu_cleanup_on_tab') self.parent().add_callback_post_tab(lambda x: self.restart_gl(), 'imu_restart_post_tab') self.gl_layout.activate() self.cbe_all_data.set_period(100) self.cbe_orientation.set_period(100) self.cbe_quaternion.set_period(50) self.update_timer.start(50) async_call(self.imu.get_convergence_speed, None, self.speed_spinbox.setValue, self.increase_error_count) self.mag_plot_widget.stop = False self.acc_plot_widget.stop = False self.gyr_plot_widget.stop = False self.temp_plot_widget.stop = False def stop(self): self.mag_plot_widget.stop = True self.acc_plot_widget.stop = True self.gyr_plot_widget.stop = True self.temp_plot_widget.stop = True self.update_timer.stop() self.cbe_all_data.set_period(0) self.cbe_orientation.set_period(0) self.cbe_quaternion.set_period(0) def destroy(self): self.alive = False self.cleanup_gl() if self.calibrate: self.calibrate.close() @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickIMU.DEVICE_IDENTIFIER def cb_all_data(self, acc_x, acc_y, acc_z, mag_x, mag_y, mag_z, gyr_x, gyr_y, gyr_z, temp): self.acc_x.value = acc_x self.acc_y.value = acc_y self.acc_z.value = acc_z self.mag_x.value = mag_x / 10 self.mag_y.value = mag_y / 10 self.mag_z.value = mag_z / 10 self.gyr_x.value = gyr_x / 14.375 self.gyr_y.value = gyr_y / 14.375 self.gyr_z.value = gyr_z / 14.375 self.temp.value = temp / 100.0 self.all_data_valid = True def cb_quaternion(self, x, y, z, w): self.qua_x = x self.qua_y = y self.qua_z = z self.qua_w = w self.quaternion_valid = True def cb_orientation(self, roll, pitch, yaw): self.roll = roll / 100.0 self.pitch = pitch / 100.0 self.yaw = yaw / 100.0 self.orientation_valid = True def led_clicked(self): if 'On' in self.led_button.text().replace('&', ''): self.led_button.setText('Turn LEDs Off') self.imu.leds_on() elif 'Off' in self.led_button.text().replace('&', ''): self.led_button.setText('Turn LEDs On') self.imu.leds_off() def update_data(self): self.update_counter += 1 if self.quaternion_valid: self.imu_gl.update_orientation(self.qua_w, self.qua_x, self.qua_y, self.qua_z) if self.update_counter == 2: self.update_counter = 0 if self.all_data_valid and self.orientation_valid: self.acceleration_update(self.acc_x.value, self.acc_y.value, self.acc_z.value) self.magnetometer_update(self.mag_x.value, self.mag_y.value, self.mag_z.value) self.gyroscope_update(self.gyr_x.value, self.gyr_y.value, self.gyr_z.value) self.orientation_update(self.roll, self.pitch, self.yaw) self.temperature_update(self.temp.value) def acceleration_update(self, x, y, z): self.acc_y_label.setText(format(x, '.1f')) self.acc_x_label.setText(format(y, '.1f')) self.acc_z_label.setText(format(z, '.1f')) def magnetometer_update(self, x, y, z): # Earth magnetic field: 0.5 Gauss self.mag_x_label.setText(format(x, '.1f')) self.mag_y_label.setText(format(y, '.1f')) self.mag_z_label.setText(format(z, '.1f')) def gyroscope_update(self, x, y, z): self.gyr_x_label.setText(format(x, '.1f')) self.gyr_y_label.setText(format(y, '.1f')) self.gyr_z_label.setText(format(z, '.1f')) def orientation_update(self, r, p, y): self.roll_label.setText(format(r, '.1f')) self.pitch_label.setText(format(p, '.1f')) self.yaw_label.setText(format(y, '.1f')) def temperature_update(self, t): self.tem_label.setText(format(t, '.1f')) def calibrate_clicked(self): self.stop() if self.calibrate is None: self.calibrate = CalibrateWindow(self) self.calibrate.refresh_values() self.calibrate.show() def speed_finished(self): speed = self.speed_spinbox.value() self.imu.set_convergence_speed(speed)
class IMUV3(COMCUPluginBase, Ui_IMUV3): def __init__(self, *args): COMCUPluginBase.__init__(self, BrickletIMUV3, *args) self.setupUi(self) self.imu = self.device self.cbe_all_data = CallbackEmulator(self, self.imu.get_all_data, None, self.cb_all_data, self.increase_error_count) self.imu_gl = IMUV33DWidget(self) self.imu_gl.setFixedSize(200, 200) self.imu_gl_wrapper = None self.state = None self.data_plot_widget = [] self.sensor_data = [CurveValueWrapper() for i in range(23)] self.data_labels = [ self.label_acceleration_x, self.label_acceleration_y, self.label_acceleration_z, self.label_magnetic_field_x, self.label_magnetic_field_y, self.label_magnetic_field_z, self.label_angular_velocity_x, self.label_angular_velocity_y, self.label_angular_velocity_z, self.label_euler_angle_heading, self.label_euler_angle_roll, self.label_euler_angle_pitch, self.label_quaternion_w, self.label_quaternion_x, self.label_quaternion_y, self.label_quaternion_z, self.label_linear_acceleration_x, self.label_linear_acceleration_y, self.label_linear_acceleration_z, self.label_gravity_vector_x, self.label_gravity_vector_y, self.label_gravity_vector_z, self.label_temperature ] self.data_rows = [ [ self.label_acceleration_11, self.label_acceleration_21, self.label_acceleration_22, self.label_acceleration_23, self.label_acceleration_41, self.label_acceleration_42, self.label_acceleration_43, self.label_acceleration_x, self.label_acceleration_y, self.label_acceleration_z ], [ self.label_magnetic_field_11, self.label_magnetic_field_21, self.label_magnetic_field_22, self.label_magnetic_field_23, self.label_magnetic_field_41, self.label_magnetic_field_42, self.label_magnetic_field_43, self.label_magnetic_field_x, self.label_magnetic_field_y, self.label_magnetic_field_z ], [ self.label_angular_velocity_11, self.label_angular_velocity_21, self.label_angular_velocity_22, self.label_angular_velocity_23, self.label_angular_velocity_41, self.label_angular_velocity_42, self.label_angular_velocity_43, self.label_angular_velocity_x, self.label_angular_velocity_y, self.label_angular_velocity_z ], [ self.label_euler_angle_11, self.label_euler_angle_21, self.label_euler_angle_22, self.label_euler_angle_23, self.label_euler_angle_41, self.label_euler_angle_42, self.label_euler_angle_43, self.label_euler_angle_roll, self.label_euler_angle_pitch, self.label_euler_angle_heading ], [ self.label_quaternion_11, self.label_quaternion_21, self.label_quaternion_22, self.label_quaternion_23, self.label_quaternion_24, self.label_quaternion_41, self.label_quaternion_42, self.label_quaternion_43, self.label_quaternion_44, self.label_quaternion_w, self.label_quaternion_x, self.label_quaternion_y, self.label_quaternion_z ], [ self.label_linear_acceleration_11, self.label_linear_acceleration_21, self.label_linear_acceleration_22, self.label_linear_acceleration_23, self.label_linear_acceleration_41, self.label_linear_acceleration_42, self.label_linear_acceleration_43, self.label_linear_acceleration_x, self.label_linear_acceleration_y, self.label_linear_acceleration_z ], [ self.label_gravity_vector_11, self.label_gravity_vector_21, self.label_gravity_vector_22, self.label_gravity_vector_23, self.label_gravity_vector_41, self.label_gravity_vector_42, self.label_gravity_vector_43, self.label_gravity_vector_x, self.label_gravity_vector_y, self.label_gravity_vector_z ], [ self.label_temperature_11, self.label_temperature_21, self.label_temperature_41, self.label_temperature ] ] even_color = QColor(240, 240, 240) odd_color = QColor(255, 255, 255) self.data_color = [(Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color), (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color), (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color), (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color), (Qt.magenta, even_color), (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color), (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color), (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color), (Qt.magenta, odd_color)] even_palette = QPalette() even_palette.setColor(QPalette.Window, even_color) odd_palette = QPalette() odd_palette.setColor(QPalette.Window, odd_color) for i, row in enumerate(self.data_rows): for label in row: if i % 2: label.setPalette(odd_palette) else: label.setPalette(even_palette) label.setAutoFillBackground(True) self.plot_timer = QTimer(self) self.plot_timer.start(100) for i in range(23): self.data_plot_widget.append( PlotWidget( "", [("", self.data_color[i][0], self.sensor_data[i], str)], clear_button=self.clear_graphs, x_scale_visible=False, y_scale_visible=False, curve_outer_border_visible=False, curve_motion='smooth', canvas_color=self.data_color[i][1], external_timer=self.plot_timer, curve_start='right', key=None, y_resolution=0.01)) for w in self.data_plot_widget: w.setMinimumHeight(15) w.setMaximumHeight(25) for i in range(23): self.data_grid.addWidget(self.data_plot_widget[i], i, 4) self.data_grid.setColumnMinimumWidth(2, 75) self.gl_layout = QVBoxLayout() self.gl_layout.addWidget(self.imu_gl) self.layout_bottom.addLayout(self.gl_layout) self.save_orientation.clicked.connect(self.save_orientation_clicked) self.button_detach_3d_view.clicked.connect(self.detach_3d_view_clicked) self.button_calibration.clicked.connect(self.calibration_clicked) self.calibration_color = [ Qt.red, QColor(0xFF, 0xA0, 0x00), Qt.yellow, Qt.darkGreen ] self.calibration = None self.alive = True self.callback_counter = 0 def save_orientation_clicked(self): self.imu_gl.save_orientation() if self.imu_gl_wrapper is not None: self.imu_gl_wrapper.glWidget.save_orientation() self.orientation_label.hide() def cleanup_gl(self): self.state = self.imu_gl.get_state() self.imu_gl.hide() self.imu_gl.cleanup() def restart_gl(self): self.imu_gl = IMUV33DWidget() self.imu_gl.setFixedSize(200, 200) self.gl_layout.addWidget(self.imu_gl) self.imu_gl.show() self.save_orientation.clicked.connect(self.save_orientation_clicked) self.imu_gl.set_state(self.state) def start(self): if not self.alive: return self.parent().add_callback_pre_tab( lambda tab_window: self.cleanup_gl(), 'imu_v3_cleanup_pre_tab') self.parent().add_callback_post_tab( lambda tab_window, tab_index: self.restart_gl(), 'imu_v3_restart_post_tab') self.parent().add_callback_pre_untab( lambda tab_window, tab_index: self.cleanup_gl(), 'imu_v3_cleanup_pre_untab') self.parent().add_callback_post_untab( lambda tab_window: self.restart_gl(), 'imu_v3_restart_post_untab') self.gl_layout.activate() self.cbe_all_data.set_period(50) for w in self.data_plot_widget: w.stop = False def stop(self): for w in self.data_plot_widget: w.stop = True if self.imu_gl_wrapper == None: self.cbe_all_data.set_period(0) def destroy(self): self.alive = False self.cleanup_gl() # Stop callback to fix deadlock with callback emulation thread. self.cbe_all_data.set_period(0) if self.calibration != None: self.calibration.close() if self.imu_gl_wrapper != None: self.imu_gl_wrapper.close() @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickletIMUV3.DEVICE_IDENTIFIER def calibration_clicked(self): if self.calibration is None: self.calibration = Calibration(self) self.button_calibration.setEnabled(False) self.calibration.show() def detach_3d_view_clicked(self): if self.imu_gl_wrapper != None: self.imu_gl_wrapper.close() self.button_detach_3d_view.setEnabled(False) self.imu_gl_wrapper = WrapperWidget(self) self.imu_gl_wrapper.glWidget.set_state(self.imu_gl.get_state()) self.save_orientation.clicked.connect(self.save_orientation_clicked) self.imu_gl_wrapper.show() def cb_all_data(self, data): self.callback_counter += 1 if self.callback_counter == 2: self.callback_counter = 0 self.sensor_data[0].value = data.acceleration[0] / 100.0 self.sensor_data[1].value = data.acceleration[1] / 100.0 self.sensor_data[2].value = data.acceleration[2] / 100.0 self.sensor_data[3].value = data.magnetic_field[0] / 16.0 self.sensor_data[4].value = data.magnetic_field[1] / 16.0 self.sensor_data[5].value = data.magnetic_field[2] / 16.0 self.sensor_data[6].value = data.angular_velocity[0] / 16.0 self.sensor_data[7].value = data.angular_velocity[1] / 16.0 self.sensor_data[8].value = data.angular_velocity[2] / 16.0 self.sensor_data[9].value = data.euler_angle[0] / 16.0 self.sensor_data[10].value = data.euler_angle[1] / 16.0 self.sensor_data[11].value = data.euler_angle[2] / 16.0 self.sensor_data[12].value = data.quaternion[0] / (2**14 - 1) self.sensor_data[13].value = data.quaternion[1] / (2**14 - 1) self.sensor_data[14].value = data.quaternion[2] / (2**14 - 1) self.sensor_data[15].value = data.quaternion[3] / (2**14 - 1) self.sensor_data[16].value = data.linear_acceleration[0] / 100.0 self.sensor_data[17].value = data.linear_acceleration[1] / 100.0 self.sensor_data[18].value = data.linear_acceleration[2] / 100.0 self.sensor_data[19].value = data.gravity_vector[0] / 100.0 self.sensor_data[20].value = data.gravity_vector[1] / 100.0 self.sensor_data[21].value = data.gravity_vector[2] / 100.0 self.sensor_data[22].value = data.temperature for i in range(23): self.data_labels[i].setText("{0:.2f}".format( self.sensor_data[i].value)) self.imu_gl.update_orientation(self.sensor_data[12].value, self.sensor_data[13].value, self.sensor_data[14].value, self.sensor_data[15].value) if self.imu_gl_wrapper is not None: self.imu_gl_wrapper.glWidget.update_orientation( self.sensor_data[12].value, self.sensor_data[13].value, self.sensor_data[14].value, self.sensor_data[15].value) cal_mag = data.calibration_status & 3 cal_acc = (data.calibration_status & (3 << 2)) >> 2 cal_gyr = (data.calibration_status & (3 << 4)) >> 4 cal_sys = (data.calibration_status & (3 << 6)) >> 6 if self.calibration != None: self.calibration.save_calibration.setEnabled( data.calibration_status == 0xFF) self.calibration.mag_color.set_color( self.calibration_color[cal_mag]) self.calibration.acc_color.set_color( self.calibration_color[cal_acc]) self.calibration.gyr_color.set_color( self.calibration_color[cal_gyr]) self.calibration.sys_color.set_color( self.calibration_color[cal_sys]) else: self.imu_gl.update_orientation(data.quaternion[0] / (2**14 - 1), data.quaternion[1] / (2**14 - 1), data.quaternion[2] / (2**14 - 1), data.quaternion[3] / (2**14 - 1)) if self.imu_gl_wrapper is not None: self.imu_gl_wrapper.glWidget.update_orientation( data.quaternion[0] / (2**14 - 1), data.quaternion[1] / (2**14 - 1), data.quaternion[2] / (2**14 - 1), data.quaternion[3] / (2**14 - 1))
class IMUV2(PluginBase, Ui_IMUV2): def __init__(self, *args): PluginBase.__init__(self, BrickIMUV2, *args) self.setupUi(self) self.imu = self.device self.cbe_all_data = CallbackEmulator(self.imu.get_all_data, None, self.cb_all_data, self.increase_error_count) self.imu_gl = IMUV23DWidget(self) self.imu_gl.setFixedSize(200, 200) self.imu_gl_wrapper = None self.data_plot_widget = [] self.sensor_data = [CurveValueWrapper() for i in range(23)] self.data_labels = [self.label_acceleration_x, self.label_acceleration_y, self.label_acceleration_z, self.label_magnetic_field_x, self.label_magnetic_field_y, self.label_magnetic_field_z, self.label_angular_velocity_x, self.label_angular_velocity_y, self.label_angular_velocity_z, self.label_euler_angle_heading, self.label_euler_angle_roll, self.label_euler_angle_pitch, self.label_quaternion_w, self.label_quaternion_x, self.label_quaternion_y, self.label_quaternion_z, self.label_linear_acceleration_x, self.label_linear_acceleration_y, self.label_linear_acceleration_z, self.label_gravity_vector_x, self.label_gravity_vector_y, self.label_gravity_vector_z, self.label_temperature] self.data_rows = [[self.label_acceleration_11, self.label_acceleration_21, self.label_acceleration_22, self.label_acceleration_23, self.label_acceleration_41, self.label_acceleration_42, self.label_acceleration_43, self.label_acceleration_x, self.label_acceleration_y, self.label_acceleration_z], [self.label_magnetic_field_11, self.label_magnetic_field_21, self.label_magnetic_field_22, self.label_magnetic_field_23, self.label_magnetic_field_41, self.label_magnetic_field_42, self.label_magnetic_field_43, self.label_magnetic_field_x, self.label_magnetic_field_y, self.label_magnetic_field_z], [self.label_angular_velocity_11, self.label_angular_velocity_21, self.label_angular_velocity_22, self.label_angular_velocity_23, self.label_angular_velocity_41, self.label_angular_velocity_42, self.label_angular_velocity_43, self.label_angular_velocity_x, self.label_angular_velocity_y, self.label_angular_velocity_z], [self.label_euler_angle_11, self.label_euler_angle_21, self.label_euler_angle_22, self.label_euler_angle_23, self.label_euler_angle_41, self.label_euler_angle_42, self.label_euler_angle_43, self.label_euler_angle_roll, self.label_euler_angle_pitch, self.label_euler_angle_heading], [self.label_quaternion_11, self.label_quaternion_21, self.label_quaternion_22, self.label_quaternion_23, self.label_quaternion_24, self.label_quaternion_41, self.label_quaternion_42, self.label_quaternion_43, self.label_quaternion_44, self.label_quaternion_w, self.label_quaternion_x, self.label_quaternion_y, self.label_quaternion_z], [self.label_linear_acceleration_11, self.label_linear_acceleration_21, self.label_linear_acceleration_22, self.label_linear_acceleration_23, self.label_linear_acceleration_41, self.label_linear_acceleration_42, self.label_linear_acceleration_43, self.label_linear_acceleration_x, self.label_linear_acceleration_y, self.label_linear_acceleration_z], [self.label_gravity_vector_11, self.label_gravity_vector_21, self.label_gravity_vector_22, self.label_gravity_vector_23, self.label_gravity_vector_41, self.label_gravity_vector_42, self.label_gravity_vector_43, self.label_gravity_vector_x, self.label_gravity_vector_y, self.label_gravity_vector_z], [self.label_temperature_11, self.label_temperature_21, self.label_temperature_41, self.label_temperature]] even_color = QColor(240, 240, 240) odd_color = QColor(255, 255, 255) self.data_color = [(Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color), (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color), (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color), (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color), (Qt.magenta, even_color), (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color), (Qt.red, odd_color), (Qt.darkGreen, odd_color), (Qt.blue, odd_color), (Qt.red, even_color), (Qt.darkGreen, even_color), (Qt.blue, even_color), (Qt.magenta, odd_color)] even_palette = QPalette() even_palette.setColor(QPalette.Window, even_color) odd_palette = QPalette() odd_palette.setColor(QPalette.Window, odd_color) for i, row in enumerate(self.data_rows): for label in row: if i % 2: label.setPalette(odd_palette) else: label.setPalette(even_palette) label.setAutoFillBackground(True) self.plot_timer = QTimer(self) self.plot_timer.start(100) for i in range(23): self.data_plot_widget.append(PlotWidget("", [("", self.data_color[i][0], self.sensor_data[i], str)], clear_button=self.clear_graphs, x_scale_visible=False, y_scale_visible=False, curve_outer_border_visible=False, curve_motion_granularity=0.1, canvas_color=self.data_color[i][1], external_timer=self.plot_timer, curve_start='right', key=None, y_resolution=0.01)) for w in self.data_plot_widget: w.setMinimumHeight(15) w.setMaximumHeight(25) for i in range(23): self.data_grid.addWidget(self.data_plot_widget[i], i, 4) self.data_grid.setColumnMinimumWidth(2, 75) self.gl_layout = QVBoxLayout() self.gl_layout.addWidget(self.imu_gl) self.layout_bottom.addLayout(self.gl_layout) self.save_orientation.clicked.connect(self.save_orientation_clicked) self.button_detach_3d_view.clicked.connect(self.detach_3d_view_clicked) self.checkbox_leds.stateChanged.connect(self.led_clicked) self.button_calibration.clicked.connect(self.calibration_clicked) self.calibration_color = [Qt.red, QColor(0xFF, 0xA0, 0x00), Qt.yellow, Qt.darkGreen] self.calibration = None self.alive = True self.callback_counter = 0 self.status_led_action = QAction('Status LED', self) self.status_led_action.setCheckable(True) self.status_led_action.toggled.connect(lambda checked: self.imu.enable_status_led() if checked else self.imu.disable_status_led()) self.set_configs([(0, None, [self.status_led_action])]) reset = QAction('Reset', self) reset.triggered.connect(self.imu.reset) self.set_actions([(0, None, [reset])]) def save_orientation_clicked(self): self.imu_gl.save_orientation() if self.imu_gl_wrapper is not None: self.imu_gl_wrapper.glWidget.save_orientation() self.orientation_label.hide() def cleanup_gl(self): self.state = self.imu_gl.get_state() self.imu_gl.hide() self.imu_gl.cleanup() def restart_gl(self): self.imu_gl = IMUV23DWidget() self.imu_gl.setFixedSize(200, 200) self.gl_layout.addWidget(self.imu_gl) self.imu_gl.show() self.save_orientation.clicked.connect(self.save_orientation_clicked) self.imu_gl.set_state(self.state) def start(self): if not self.alive: return self.parent().add_callback_on_untab(lambda x: self.cleanup_gl(), 'imu_v2_cleanup_on_untab') self.parent().add_callback_post_untab(lambda x: self.restart_gl(), 'imu_v2_restart_post_untab') self.parent().add_callback_on_tab(lambda x: self.cleanup_gl(), 'imu_v2_cleanup_on_tab') self.parent().add_callback_post_tab(lambda x: self.restart_gl(), 'imu_v2_restart_post_tab') self.gl_layout.activate() async_call(self.imu.is_status_led_enabled, None, self.status_led_action.setChecked, self.increase_error_count) async_call(self.imu.are_leds_on, None, self.checkbox_leds.setChecked, self.increase_error_count) self.cbe_all_data.set_period(50) for w in self.data_plot_widget: w.stop = False def stop(self): for w in self.data_plot_widget: w.stop = True if self.imu_gl_wrapper == None: self.cbe_all_data.set_period(0) def destroy(self): self.alive = False self.cleanup_gl() # Stop callback to fix deadlock with callback emulation thread. self.cbe_all_data.set_period(0) if self.calibration != None: self.calibration.close() if self.imu_gl_wrapper != None: self.imu_gl_wrapper.close() @staticmethod def has_device_identifier(device_identifier): return device_identifier == BrickIMUV2.DEVICE_IDENTIFIER def calibration_clicked(self): if self.calibration is None: self.calibration = Calibration(self) self.button_calibration.setEnabled(False) self.calibration.show() def detach_3d_view_clicked(self): if self.imu_gl_wrapper != None: self.imu_gl_wrapper.close() self.button_detach_3d_view.setEnabled(False) self.imu_gl_wrapper = WrapperWidget(self) self.imu_gl_wrapper.glWidget.set_state(self.imu_gl.get_state()) self.save_orientation.clicked.connect(self.save_orientation_clicked) self.imu_gl_wrapper.show() def cb_all_data(self, data): self.callback_counter += 1 if self.callback_counter == 2: self.callback_counter = 0 self.sensor_data[0].value = data.acceleration[0] / 100.0 self.sensor_data[1].value = data.acceleration[1] / 100.0 self.sensor_data[2].value = data.acceleration[2] / 100.0 self.sensor_data[3].value = data.magnetic_field[0] / 16.0 self.sensor_data[4].value = data.magnetic_field[1] / 16.0 self.sensor_data[5].value = data.magnetic_field[2] / 16.0 self.sensor_data[6].value = data.angular_velocity[0] / 16.0 self.sensor_data[7].value = data.angular_velocity[1] / 16.0 self.sensor_data[8].value = data.angular_velocity[2] / 16.0 self.sensor_data[9].value = data.euler_angle[0] / 16.0 self.sensor_data[10].value = data.euler_angle[1] / 16.0 self.sensor_data[11].value = data.euler_angle[2] / 16.0 self.sensor_data[12].value = data.quaternion[0] / (2 ** 14 - 1) self.sensor_data[13].value = data.quaternion[1] / (2 ** 14 - 1) self.sensor_data[14].value = data.quaternion[2] / (2 ** 14 - 1) self.sensor_data[15].value = data.quaternion[3] / (2 ** 14 - 1) self.sensor_data[16].value = data.linear_acceleration[0] / 100.0 self.sensor_data[17].value = data.linear_acceleration[1] / 100.0 self.sensor_data[18].value = data.linear_acceleration[2] / 100.0 self.sensor_data[19].value = data.gravity_vector[0] / 100.0 self.sensor_data[20].value = data.gravity_vector[1] / 100.0 self.sensor_data[21].value = data.gravity_vector[2] / 100.0 self.sensor_data[22].value = data.temperature for i in range(23): self.data_labels[i].setText("{0:.2f}".format(self.sensor_data[i].value)) self.imu_gl.update_orientation(self.sensor_data[12].value, self.sensor_data[13].value, self.sensor_data[14].value, self.sensor_data[15].value) if self.imu_gl_wrapper is not None: self.imu_gl_wrapper.glWidget.update_orientation(self.sensor_data[12].value, self.sensor_data[13].value, self.sensor_data[14].value, self.sensor_data[15].value) cal_mag = data.calibration_status & 3 cal_acc = (data.calibration_status & (3 << 2)) >> 2 cal_gyr = (data.calibration_status & (3 << 4)) >> 4 cal_sys = (data.calibration_status & (3 << 6)) >> 6 if self.calibration != None: self.calibration.save_calibration.setEnabled(data.calibration_status == 0xFF) self.calibration.mag_color.set_color(self.calibration_color[cal_mag]) self.calibration.acc_color.set_color(self.calibration_color[cal_acc]) self.calibration.gyr_color.set_color(self.calibration_color[cal_gyr]) self.calibration.sys_color.set_color(self.calibration_color[cal_sys]) else: self.imu_gl.update_orientation(data.quaternion[0] / (2 ** 14 - 1), data.quaternion[1] / (2 ** 14 - 1), data.quaternion[2] / (2 ** 14 - 1), data.quaternion[3] / (2 ** 14 - 1)) if self.imu_gl_wrapper is not None: self.imu_gl_wrapper.glWidget.update_orientation(data.quaternion[0] / (2 ** 14 - 1), data.quaternion[1] / (2 ** 14 - 1), data.quaternion[2] / (2 ** 14 - 1), data.quaternion[3] / (2 ** 14 - 1)) def led_clicked(self, state): if state == Qt.Checked: self.imu.leds_on() else: self.imu.leds_off()
class SinkSelectorSettings(SettingsSection): NAME = 'Multi-Sink Selector' ELEMENT = SinkSelector Sinks = elements.outputs() def __init__(self, size, Id, parent=None): super().__init__(size, parent) self.id = Id self._sinks = [] self.groupBox = QGroupBox(self) self.groupBox.setTitle('Add/Remove outputs') self.groupBox.resize(self.width(), self.height()) self.vlayout = QVBoxLayout(self.groupBox) self.vlayout.setContentsMargins(0, 5, 0, 0) self.sinksList = QListWidget(self.groupBox) self.sinksList.setAlternatingRowColors(True) self.vlayout.addWidget(self.sinksList) self.buttons = QDialogButtonBox(self.groupBox) self.vlayout.addWidget(self.buttons) self.add = QPushButton('Add') self.remove = QPushButton('Remove') self.buttons.addButton(self.add, QDialogButtonBox.YesRole) self.buttons.addButton(self.remove, QDialogButtonBox.NoRole) self.vlayout.activate() self.add.clicked.connect(self._new_sink) self.remove.clicked.connect(self.__remove_sink) def set_configuration(self, conf): if conf is not None and self.id in conf: conf = deepcopy(conf) for key in conf[self.id]: self.__add_sink(conf[self.id][key], key) else: self.__add_sink({'name': 'AutoSink'}, 'sink0') def get_configuration(self): conf = {} if not (self.groupBox.isCheckable() and not self.groupBox.isChecked()): conf[self.id] = {} for widget, name in self._sinks: conf[self.id][name] = widget.get_settings() return conf def enable_check(self, enable): self.groupBox.setCheckable(enable) self.groupBox.setChecked(False) def _new_sink(self): sinks = sorted(self.Sinks.keys()) sinks.remove('SinkSelector') name, ok = QInputDialog.getItem(self, "Output", "Select output device", sinks, editable=False) if ok: self.__add_sink({'name': name}) def __new_name(self): suff = 0 for _, name in sorted(self._sinks, key=itemgetter(1)): if 'sink' + str(suff) != name: break suff += 1 return 'sink' + str(suff) def __add_sink(self, properties, name=None): widget = OutputWidget(properties, self.sinksList) widget.resize(self.sinksList.width() - 5, 80) item = QListWidgetItem() item.setSizeHint(widget.size()) if name is None: name = self.__new_name() self._sinks.append((widget, name)) self.sinksList.addItem(item) self.sinksList.setItemWidget(item, widget) self.remove.setEnabled(len(self._sinks) > 1) def __remove_sink(self): self._sinks.pop(self.sinksList.currentRow()) self.sinksList.removeItemWidget(self.sinksList.currentItem()) self.sinksList.takeItem(self.sinksList.currentRow()) self.remove.setEnabled(len(self._sinks) > 1)