i can control the Crazyflie using Lighthouse system, but only with the python code, for example https://github.com/bitcraze/crazyflie-l ... equence.py. Now i want to write a new Client-Tab for controlling with LH. I know how to read and change the parameters in new Tab after i learned the Logging and parameter framework video https://www.youtube.com/watch?v=chWrNh73YBw. Now I want to add some features, such as logdata read and setpoint.
My problem is:
1. I tried to write the Tab based on the QualisysTab, but unfortunately, I can only complete the log reading function, but can't make the copter take off with sentpoint function.
2. After I wrote the new log reading function, all the parameters in ParamTab are locked in red and i can't modified them any more.
Does anyone have experience in this area, can you give me a simple template?
here is my code und the new Tab:
Code: Select all
import logging
from PyQt5 import uic
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QMessageBox
from cflib.crazyflie.log import LogConfig
import cfclient
from cfclient.ui.tab import Tab
import math
__author__ = 'Bitcraze AB'
__all__ = ['ExampleTab']
logger = logging.getLogger(__name__)
example_tab_class = uic.loadUiType(cfclient.module_path + "/ui/tabs/exampleTab.ui")[0]
class ExampleTab(Tab, example_tab_class):
"""Tab for plotting logging data"""
_connected_signal = pyqtSignal(str)
_disconnected_signal = pyqtSignal(str)
_log_data_signal = pyqtSignal(int, object, object)
_cmd_data_signal = pyqtSignal(int, object, object)
_pos_data_signal = pyqtSignal(int, object, object)
_log_error_signal = pyqtSignal(object, str)
_param_updated_signal = pyqtSignal(str, str)
def __init__(self, tabWidget, helper, *args):
super(ExampleTab, self).__init__(*args)
self.setupUi(self)
self.tabName = "Example"
self.menuName = "Example Tab"
self.tabWidget = tabWidget
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._cmd_data_signal.connect(self._cmd_data_received)
self._pos_data_signal.connect(self._pos_data_received)
self._param_updated_signal.connect(self._param_updated)
# 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)
# Connect motorPower UI signals
self.motorPower.clicked.connect(
lambda enable:
self._helper.cf.param.set_value("motorPowerSet.enable", str(enable))
)
self._helper.cf.param.add_update_callback(group="motorPowerSet", name="enable", cb=self._param_updated_signal.emit)
# Connect _enable_motors UI signals
self._enable_motors.clicked.connect(
lambda enable:
self._helper.cf.param.set_value("mc_usr.enable_usr", str(enable))
)
self._helper.cf.param.add_update_callback(group="mc_usr", name="enable_usr", cb=self._param_updated_signal.emit)
# Connect UI signals that are in this tab
self.Target_X.valueChanged.connect(self._position_changed)
self.Target_Y.valueChanged.connect(self._position_changed)
self.Target_Z.valueChanged.connect(self._position_changed)
self.Target_Yaw.valueChanged.connect(self._position_changed)
# set original value
self.Target_X.setValue(0)
self.Target_Y.setValue(0)
self.Target_Z.setValue(0)
self.Target_Yaw.setValue(0)
self._eingang.valueChanged.connect(self._eingang_changed)
self._eingang.setValue(5)
def _connected(self, link_uri):
"""Callback when the Crazyflie has been connected"""
logger.debug("Crazyflie connected to {}".format(link_uri))
# aktual position
pos_conf = LogConfig('Position2', 10)
pos_conf.add_variable('kalman.stateX')
pos_conf.add_variable('kalman.stateY')
pos_conf.add_variable('kalman.stateZ')
try:
self._helper.cf.log.add_config(pos_conf)
pos_conf.data_received_cb.add_callback(self._pos_data_signal.emit)
pos_conf.error_cb.add_callback(self._log_error_signal.emit)
pos_conf.start()
except KeyError as e:
logger.warning(str(e))
except AttributeError as e:
logger.warning(str(e))
# control Commander
cmd_conf = LogConfig('MotorCommander', 10) # configure the variable in Plotter
cmd_conf.add_variable('controller.cmd_roll') # add the variable by calling
cmd_conf.add_variable('controller.cmd_pitch')
cmd_conf.add_variable('controller.cmd_yaw')
cmd_conf.add_variable('controller.cmd_thrust')
try:
self._helper.cf.log.add_config(cmd_conf)
cmd_conf.data_received_cb.add_callback(self._cmd_data_signal.emit)
cmd_conf.error_cb.add_callback(self._log_error_signal.emit)
cmd_conf.start()
except KeyError as e:
logger.warning(str(e))
except AttributeError as e:
logger.warning(str(e))
def _disconnected(self, link_uri):
"""Callback for when the Crazyflie has been disconnected"""
logger.debug("Crazyflie disconnected from {}".format(link_uri))
self._enable_motors.setEnabled(False)
def _eingang_changed(self):
self.x = 2 * self._eingang.value()
self._ausgang.setText("%0.3f" % self.x)
def _param_updated(self, name, value):
"""Callback when the registered parameter get's updated"""
logger.debug("Updated {0} to {1}".format(name, value))
if not self._enable_motors.isEnabled():
self._enable_motors.setEnabled(True)
self._enable_motors.setChecked(eval(str(value)))
def _cmd_data_received(self, timestamp, data, log_conf):
"""Callback when the log layer receives new data"""
self.cmd_data.setText( "roll=%0.3f pitch=%0.3f yaw=%0.3f thrust=%0.3f " % (data['controller.cmd_roll'],
data['controller.cmd_pitch'],
data['controller.cmd_yaw'],
data['controller.cmd_thrust']))
def _pos_data_received(self, timestamp, data, log_conf):
self.pos_data.setText(
"X=%0.3f Y=%0.3f Z=%0.3f" % (data['kalman.stateX'],
data['kalman.stateY'],
data['kalman.stateZ']))
def _position_changed(self):
#self.position_input_updated.call(self.Target_X.value(),self.Target_Y.value(),self.Target_Z.value())
if self.sendaktiv.isChecked():
self._cf.commander.send_position_setpoint(self.Target_X.value(),self.Target_Y.value(),
self.Target_Z.value(),self.Target_Yaw.value())
def _logging_error(self, log_conf, msg):
"""Callback from the log layer when an error occurs"""
QMessageBox.about(self, "Example error",
"Error when using log config"
" [{0}]: {1}".format(log_conf.name, msg))