Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions dronecan_gui_tool/panels/esc_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ def __init__(self, esc_index, parent):
self._temperature_label = QLabel('Temp: NC', self)
self._rpm_label = QLabel('RPM: NC', self)
self._power_rating_pct_label = QLabel('RAT: NC', self)
self._fps_label = QLabel('FPS: 0', self)

self._fps_count = 0
self._fps_window_start = time.time()
self._fps_last_msg_time = 0

layout = QHBoxLayout(self)

Expand All @@ -67,6 +72,7 @@ def __init__(self, esc_index, parent):
status_layout.addWidget(self._temperature_label)
status_layout.addWidget(self._rpm_label)
status_layout.addWidget(self._power_rating_pct_label)
status_layout.addWidget(self._fps_label)
status_layout.addStretch()
status_layout.addWidget(self._spinbox)
status_layout.addWidget(self._zero_button)
Expand All @@ -92,9 +98,25 @@ def view_mode_set_value(self, value):
self._slider.setValue(value)
self._spinbox.setValue(value)

def check_fps_timeout(self):
now = time.time()
if self._fps_last_msg_time > 0 and now - self._fps_last_msg_time >= 1.0:
self._fps_label.setText('FPS: 0.0')
self._fps_count = 0
self._fps_window_start = now
self._fps_last_msg_time = 0

def update_status(self, idx, error_count, voltage, current, temperature_celsius, rpm, power_rating_pct):
if idx != self._index:
return
now = time.time()
self._fps_count += 1
self._fps_last_msg_time = now
elapsed = now - self._fps_window_start
if elapsed >= 1.0:
self._fps_label.setText(f'FPS: {self._fps_count / elapsed:.1f}')
self._fps_count = 0
self._fps_window_start = now
if error_count is not None:
self._error_count_label.setText(f'Err: {error_count}')
if voltage is not None:
Expand Down Expand Up @@ -288,6 +310,8 @@ def _update_view_mode(self):
def _do_broadcast(self):
try:
self._update_view_mode()
for sl in self._sliders:
sl.check_fps_timeout()
if not self._view_mode.isChecked():
if not self._pause.isChecked():
if self._safety_enable.checkState():
Expand Down
2 changes: 1 addition & 1 deletion dronecan_gui_tool/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# Andrew Tridgell
#
#
__version__ = 1, 2, 28
__version__ = 1, 2, 29



49 changes: 35 additions & 14 deletions dronecan_gui_tool/widgets/node_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,21 @@
from .node_monitor import node_health_to_color, node_mode_to_color
from .file_server import FileServer_PathKey
from ..am32_rtttl import AM32_Rtttl
from typing import Optional


logger = getLogger(__name__)


REQUEST_PRIORITY = 30

class ConfigParamEntry:
def __init__(self, index, response):
self._index = index
self._value = response.value
self._name = response.name
self._response = response;
self._sync=True

class FieldValueWidget(QLineEdit):
def __init__(self, parent, initial_value=None):
Expand Down Expand Up @@ -656,7 +664,7 @@ def update_callback(value, is_melody=False):
else:
self._table.item(index, self.VALUE_COLUMN).setText(str(value))

win = ConfigParamEditWindow(self, self._node, self._target_node_id, self._params[index], update_callback)
win = ConfigParamEditWindow(self, self._node, self._target_node_id, self._params[index]._response, update_callback)
win.show()

def _on_fetch_response(self, index, e):
Expand All @@ -679,14 +687,17 @@ def _on_fetch_response(self, index, e):
self.window().show_message('%d params fetched successfully', index)
return

self._params.append(e.response)
# create a parameter structure including the index from the response
param = ConfigParamEntry(index, e.response)

self._params.append(param)
self._table.setRowCount(self._table.rowCount() + 1)
self._table.set_row(self._table.rowCount() - 1, (index, e.response))

try:
index += 1
self.window().show_message('Requesting index %d', index)
self._node.defer(0.1, lambda: self._node.request(dronecan.uavcan.protocol.param.GetSet.Request(index=index),
self._node.defer(0.01, lambda: self._node.request(dronecan.uavcan.protocol.param.GetSet.Request(index=index),
self._target_node_id,
partial(self._on_fetch_response, index),
priority=REQUEST_PRIORITY))
Expand Down Expand Up @@ -740,9 +751,9 @@ def _do_save_to_file(self):
print("save to file", param_file)
f = open(param_file, "w")
for p in self._params:
value = p.value
name = p.name
value_string = self.param_as_string(value, AM32_Rtttl.is_am32_melody_param(p))
value = p._value
name = p._name
value_string = self.param_as_string(value, AM32_Rtttl.is_am32_melody_param(p._response))
if value_string:
f.write("%s %s\n" % (name, value_string))
f.close()
Expand All @@ -753,12 +764,12 @@ def _on_send_response(self, e):
else:
for i in range(len(self._params)):
p = self._params[i]
name = str(p.name)
name = str(p._name)
if name == str(e.response.name):
logger.info('set %s to %s' % (name, self.param_as_string(e.response.value)))
self._table.item(i, self.VALUE_COLUMN).setText(self.param_as_string(e.response.value, AM32_Rtttl.is_am32_melody_param(p)))
self._table.item(i, self.VALUE_COLUMN).setText(self.param_as_string(e.response.value, AM32_Rtttl.is_am32_melody_param(p._response)))

def save_param(self, name, old_value, str_value):
def save_param(self, name, old_value, str_value, index: Optional[int] = None, delay: Optional[float] = None):
value_type = dronecan.get_active_union_field(old_value)
v = old_value

Expand All @@ -774,8 +785,16 @@ def save_param(self, name, old_value, str_value):
raise RuntimeError('bad parameter type on save')

try:
request = dronecan.uavcan.protocol.param.GetSet.Request(name=name, value=v)
self._node.request(request, self._target_node_id, self._on_send_response, priority=REQUEST_PRIORITY)
if index is None:
request = dronecan.uavcan.protocol.param.GetSet.Request(name=name, value=v)
else:
request = dronecan.uavcan.protocol.param.GetSet.Request(index=index, value=v)

if delay is None:
self._node.request(request, self._target_node_id, self._on_send_response, priority=REQUEST_PRIORITY)
else:
self._node.defer(delay, lambda: self._node.request(request, self._target_node_id, self._on_send_response, priority=REQUEST_PRIORITY))

except Exception as ex:
show_error('Node error', 'Could not send param set request', ex, self)

Expand All @@ -787,11 +806,12 @@ def _do_load_from_file(self):
return
pdict = {}
for p in self._params:
pdict[str(p.name)] = p.value
pdict[str(p._name)] = p

param_file = os.path.normcase(os.path.abspath(param_file[0]))
print("load from file", param_file)
f = open(param_file, "r")
delay = 0.0
for line in f.readlines():
a = line.split()
name = a[0]
Expand All @@ -804,9 +824,10 @@ def _do_load_from_file(self):
else:
value = a[1]
if name in pdict:
s = self.param_as_string(pdict[name])
s = self.param_as_string(pdict[name]._value)
if s != value:
self.save_param(name, pdict[name], value)
self.save_param(name, pdict[name]._value, value, pdict[name]._index, delay)
delay += 0.02
f.close()

def _do_execute_opcode(self, opcode):
Expand Down