diff --git a/sw/ground_segment/python/messages_app/messagesframe.py b/sw/ground_segment/python/messages_app/messagesframe.py index 7b3308ff62..c597cd8cbb 100644 --- a/sw/ground_segment/python/messages_app/messagesframe.py +++ b/sw/ground_segment/python/messages_app/messagesframe.py @@ -19,7 +19,7 @@ BORDER = 1 class MessagesFrame(wx.Frame): def message_recv(self, ac_id, name, values): - if self.aircrafts.has_key(ac_id) and self.aircrafts[ac_id].messages.has_key(name): + if ac_id in self.aircrafts and name in self.aircrafts[ac_id].messages: if time.time() - self.aircrafts[ac_id].messages[name].last_seen < 0.2: return @@ -109,12 +109,12 @@ class MessagesFrame(wx.Frame): field_panel.Layout() def gui_update(self, ac_id, name, values): - if not self.aircrafts.has_key(ac_id): + if ac_id not in self.aircrafts: self.add_new_aircraft(ac_id) aircraft = self.aircrafts[ac_id] - if not aircraft.messages.has_key(name): + if name not in aircraft.messages: self.add_new_message(aircraft, name) aircraft.messages_book.SetPageImage(aircraft.messages[name].index, 1) diff --git a/sw/ground_segment/python/settings_app/settingsapp.py b/sw/ground_segment/python/settings_app/settingsapp.py index 5562ff9182..d32fa699ee 100755 --- a/sw/ground_segment/python/settings_app/settingsapp.py +++ b/sw/ground_segment/python/settings_app/settingsapp.py @@ -12,38 +12,38 @@ import settings_xml_parse DEFAULT_AC_IDS = [ 11 ] # biwhirly def Usage(scmd): - lpathitem = scmd.split('/') - fmt = '''Usage: %s [-h | --help] [-a AC_ID | --ac_id=AC_ID] + lpathitem = scmd.split('/') + fmt = '''Usage: %s [-h | --help] [-a AC_ID | --ac_id=AC_ID] where \t-h | --help print this message \t-a AC_ID | --ac_id=AC_ID where AC_ID is an aircraft ID to use for settings (multiple IDs may passed) ''' - print fmt % lpathitem[-1] + print(fmt % lpathitem[-1]) def GetOptions(): - options = {'ac_id':[]} - try: - optlist, left_args = getopt.getopt(sys.argv[1:],'h:a:', ['help', 'ac_id=']) - except getopt.GetoptError: - # print help information and exit: - Usage(sys.argv[0]) - sys.exit(2) - for o, a in optlist: - if o in ("-h", "--help"): - Usage(sys.argv[0]) - sys.exit() - elif o in ("-a", "--ac_id"): - options['ac_id'].append(int(a)) + options = {'ac_id':[]} + try: + optlist, left_args = getopt.getopt(sys.argv[1:],'h:a:', ['help', 'ac_id=']) + except getopt.GetoptError: + # print help information and exit: + Usage(sys.argv[0]) + sys.exit(2) + for o, a in optlist: + if o in ("-h", "--help"): + Usage(sys.argv[0]) + sys.exit() + elif o in ("-a", "--ac_id"): + options['ac_id'].append(int(a)) - return options + return options class SettingsApp(wx.App): def OnInit(self): options = GetOptions() if len(options['ac_id']) > 0: - ac_ids = options['ac_id'] + ac_ids = options['ac_id'] else: - ac_ids = DEFAULT_AC_IDS + ac_ids = DEFAULT_AC_IDS self.main = settingsframe.create(None, ac_ids) self.main.Show() self.SetTopWindow(self.main) diff --git a/sw/ground_segment/python/settings_app/settingsframe.py b/sw/ground_segment/python/settings_app/settingsframe.py index 10a8f1132e..97aff05ae7 100644 --- a/sw/ground_segment/python/settings_app/settingsframe.py +++ b/sw/ground_segment/python/settings_app/settingsframe.py @@ -17,82 +17,82 @@ SLIDER_FACTOR = 100 # Wraps TextCtrl to provide added functionality class TextCtrlSetting(wx.TextCtrl): - update_callback = None - def __init__(self, parent, setting): - self.setting = setting - wx.TextCtrl.__init__(self, parent=parent, name=setting.shortname, id=setting.index) - self.Bind(wx.EVT_TEXT, self.onEvtText, self) + update_callback = None + def __init__(self, parent, setting): + self.setting = setting + wx.TextCtrl.__init__(self, parent=parent, name=setting.shortname, id=setting.index) + self.Bind(wx.EVT_TEXT, self.onEvtText, self) - def RegisterUpdateCallback(self, cb): - self.update_callback = cb - - def onEvtText(self, event): - index = int(self.GetId()) - try: - value = float(self.GetValue()) - self.update_callback(index, value) - except: - return + def RegisterUpdateCallback(self, cb): + self.update_callback = cb - # helper function to toggle edit box boldness (bold = user-set, normal=downlink-received) - def setBold(self, bold): - font = self.GetFont() - if (bold): - font.SetWeight(wx.FONTWEIGHT_BOLD) - else: - font.SetWeight(wx.FONTWEIGHT_NORMAL) - self.SetFont(font) + def onEvtText(self, event): + index = int(self.GetId()) + try: + value = float(self.GetValue()) + self.update_callback(index, value) + except: + return - def SetSettingValue(self, value): - if (self.setting.step < 1): - self.SetValue("%.2f" % float(value)) - else: - self.SetValue("%i" % int(float(value))) + # helper function to toggle edit box boldness (bold = user-set, normal=downlink-received) + def setBold(self, bold): + font = self.GetFont() + if (bold): + font.SetWeight(wx.FONTWEIGHT_BOLD) + else: + font.SetWeight(wx.FONTWEIGHT_NORMAL) + self.SetFont(font) + + def SetSettingValue(self, value): + if (self.setting.step < 1): + self.SetValue("%.2f" % float(value)) + else: + self.SetValue("%i" % int(float(value))) # Wraps slider class SettingCtrl(wx.Slider): - update_callback = None - def __init__(self, parent, setting): - self.setting = setting - max_v = int(setting.max_value) * SLIDER_FACTOR - min_v = int(setting.min_value) * SLIDER_FACTOR - if (min_v >= max_v): - max_v = max_v + 1 - wx.Slider.__init__(self, parent=parent, minValue=min_v, maxValue=max_v, style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS, size=(200, 30), id=setting.index + SLIDER_ID_OFFSET) - self.SetLineSize(setting.step * SLIDER_FACTOR) - self.Bind(wx.EVT_MOUSEWHEEL, self.sliderWheel, self) - self.Bind(wx.EVT_SLIDER, self.OnEvtSlider, self) + update_callback = None + def __init__(self, parent, setting): + self.setting = setting + max_v = int(setting.max_value) * SLIDER_FACTOR + min_v = int(setting.min_value) * SLIDER_FACTOR + if (min_v >= max_v): + max_v = max_v + 1 + wx.Slider.__init__(self, parent=parent, minValue=min_v, maxValue=max_v, style=wx.SL_HORIZONTAL | wx.SL_AUTOTICKS, size=(200, 30), id=setting.index + SLIDER_ID_OFFSET) + self.SetLineSize(setting.step * SLIDER_FACTOR) + self.Bind(wx.EVT_MOUSEWHEEL, self.sliderWheel, self) + self.Bind(wx.EVT_SLIDER, self.OnEvtSlider, self) - def RegisterUpdateCallback(self, cb): - self.update_callback = cb + def RegisterUpdateCallback(self, cb): + self.update_callback = cb - def OnEvtSlider(self, event): - slider = event.GetEventObject() - self.update_callback(slider.GetSettingIndex(), slider.GetSettingValue()) + def OnEvtSlider(self, event): + slider = event.GetEventObject() + self.update_callback(slider.GetSettingIndex(), slider.GetSettingValue()) - # Called on mouse wheel events (default handler seems backwards?) - def sliderWheel(self, event): - slider = event.GetEventObject() - if (event.GetWheelRotation() > 0): - slider.SetValue(slider.GetValue() + slider.GetLineSize()) - else: - slider.SetValue(slider.GetValue() - slider.GetLineSize()) - self.update_callback(slider.GetSettingIndex(), slider.GetSettingValue()) - - def GetSettingIndex(self): - index = int(self.GetId()) - if index >= SLIDER_ID_OFFSET: - index = index - SLIDER_ID_OFFSET - return index + # Called on mouse wheel events (default handler seems backwards?) + def sliderWheel(self, event): + slider = event.GetEventObject() + if (event.GetWheelRotation() > 0): + slider.SetValue(slider.GetValue() + slider.GetLineSize()) + else: + slider.SetValue(slider.GetValue() - slider.GetLineSize()) + self.update_callback(slider.GetSettingIndex(), slider.GetSettingValue()) - def SetSettingValue(self, value): - self.SetValue(int(float(value)) * SLIDER_FACTOR) + def GetSettingIndex(self): + index = int(self.GetId()) + if index >= SLIDER_ID_OFFSET: + index = index - SLIDER_ID_OFFSET + return index - def GetSettingValue(self): - if (self.setting.step < 1): - return float(self.GetValue()) / SLIDER_FACTOR - else: - return int(self.GetValue()) / SLIDER_FACTOR + def SetSettingValue(self, value): + self.SetValue(int(float(value)) * SLIDER_FACTOR) + + def GetSettingValue(self): + if (self.setting.step < 1): + return float(self.GetValue()) / SLIDER_FACTOR + else: + return int(self.GetValue()) / SLIDER_FACTOR class SettingsFrame(wx.Frame): edits = [] @@ -106,77 +106,77 @@ class SettingsFrame(wx.Frame): self.Bind( wx.EVT_CLOSE, self.OnClose) for setting_group in self.settings.groups: - page = wx.Panel(self.book) - vert_box = wx.BoxSizer(orient=wx.VERTICAL) + page = wx.Panel(self.book) + vert_box = wx.BoxSizer(orient=wx.VERTICAL) - for setting in setting_group.member_list: - horz_box = wx.BoxSizer(orient=wx.HORIZONTAL) + for setting in setting_group.member_list: + horz_box = wx.BoxSizer(orient=wx.HORIZONTAL) - text = wx.StaticText(page, label=setting.shortname, size=(100,30)) + text = wx.StaticText(page, label=setting.shortname, size=(100,30)) - # Edit - edit = TextCtrlSetting(page, setting) - edit.RegisterUpdateCallback(self.editUpdate) - self.edits.append(edit) + # Edit + edit = TextCtrlSetting(page, setting) + edit.RegisterUpdateCallback(self.editUpdate) + self.edits.append(edit) - # Slider - slider = SettingCtrl(page, setting) - slider.RegisterUpdateCallback(self.updateEditFromSlider) - self.sliders.append(slider) + # Slider + slider = SettingCtrl(page, setting) + slider.RegisterUpdateCallback(self.updateEditFromSlider) + self.sliders.append(slider) - # Button - button = wx.Button(page, id=setting.index + BUTTON_ID_OFFSET, label="Apply") - self.Bind(wx.EVT_BUTTON, self.onButton) + # Button + button = wx.Button(page, id=setting.index + BUTTON_ID_OFFSET, label="Apply") + self.Bind(wx.EVT_BUTTON, self.onButton) - horz_box.AddWindow(text) - horz_box.AddWindow(edit) - horz_box.AddWindow(slider) - horz_box.AddWindow(button) - - vert_box.AddWindow(horz_box) - - page.SetSizer(vert_box) - self.book.AddPage(page, setting_group.name) + horz_box.AddWindow(text) + horz_box.AddWindow(edit) + horz_box.AddWindow(slider) + horz_box.AddWindow(button) + + vert_box.AddWindow(horz_box) + + page.SetSizer(vert_box) + + self.book.AddPage(page, setting_group.name) self.settings.RegisterCallback(self.onUpdate) # Copy slider value into associated edit box def updateEditFromSlider(self, index, value): - self.edits[index].ChangeValue(str(value)) - self.edits[index].setBold(True) + self.edits[index].ChangeValue(str(value)) + self.edits[index].setBold(True) # Called on edit box update def editUpdate(self, index, value): - self.sliders[index].SetSettingValue(value) - self.edits[index].setBold(True) + self.sliders[index].SetSettingValue(value) + self.edits[index].setBold(True) # Called on button push def onButton(self, event): - button = event.GetEventObject() - index = int(button.GetId()) - if index >= BUTTON_ID_OFFSET: - index = index - BUTTON_ID_OFFSET - self.settings.lookup[index].value = self.sliders[index].GetSettingValue() - self.settings.SendSetting(index) + button = event.GetEventObject() + index = int(button.GetId()) + if index >= BUTTON_ID_OFFSET: + index = index - BUTTON_ID_OFFSET + self.settings.lookup[index].value = self.sliders[index].GetSettingValue() + self.settings.SendSetting(index) # Called for remote settings updates def onUpdate(self, index, value, fromRemote): - # Schedule the call for later via wx (run after events) - # to prevent crashy crashy - wx.CallAfter(self.update_value, index, value, fromRemote) - + # Schedule the call for later via wx (run after events) + # to prevent crashy crashy + wx.CallAfter(self.update_value, index, value, fromRemote) + # Called to update GUI with new values def update_value(self, index, value, fromRemote): editCtrl = self.edits[index] if fromRemote and editCtrl.FindFocus() == editCtrl: - # don't process remote updates if the control is focused - return - editCtrl.SetSettingValue(value) - editCtrl.setBold(not fromRemote) - self.sliders[index].SetSettingValue(value) - + # don't process remote updates if the control is focused + return + editCtrl.SetSettingValue(value) + editCtrl.setBold(not fromRemote) + self.sliders[index].SetSettingValue(value) + def OnClose(self, event): - # need to forward close to canvas so that ivy is shut down, otherwise ivy hangs the shutdown - self.settings.OnClose() - self.Destroy() - + # need to forward close to canvas so that ivy is shut down, otherwise ivy hangs the shutdown + self.settings.OnClose() + self.Destroy() diff --git a/sw/lib/python/messages_tool.py b/sw/lib/python/messages_tool.py index 64b69a8525..32be0aa843 100644 --- a/sw/lib/python/messages_tool.py +++ b/sw/lib/python/messages_tool.py @@ -1,4 +1,4 @@ -from __future__ import print_function +from __future__ import absolute_import, print_function import messages_xml_map from ivy.std_api import * diff --git a/sw/lib/python/messages_xml_map.py b/sw/lib/python/messages_xml_map.py index 91c4c4f90b..c508e57a01 100755 --- a/sw/lib/python/messages_xml_map.py +++ b/sw/lib/python/messages_xml_map.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from __future__ import print_function +from __future__ import absolute_import, print_function import os import sys @@ -42,14 +42,14 @@ def ParseMessages(): tree = etree.parse( messages_path) for the_class in tree.xpath("//class[@name]"): class_name = the_class.attrib['name'] - if not message_dictionary.has_key(class_name): + if class_name not in message_dictionary: message_dictionary_id_name[class_name] = {} message_dictionary_name_id[class_name] = {} message_dictionary[class_name] = {} message_dictionary_types[class_name] = {} for the_message in the_class.xpath("message[@name]"): message_name = the_message.attrib['name'] - if the_message.attrib.has_key('id'): + if 'id' in the_message.attrib: message_id = the_message.attrib['id'] else: message_id = the_message.attrib['ID'] diff --git a/sw/lib/python/settings_tool.py b/sw/lib/python/settings_tool.py index 54c004dbbe..6b902a0db5 100755 --- a/sw/lib/python/settings_tool.py +++ b/sw/lib/python/settings_tool.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from __future__ import print_function +from __future__ import absolute_import, print_function from ivy.std_api import * import os @@ -29,6 +29,9 @@ class IvySettingsInterface(PaparazziACSettings): setting_index = int(message_values[1]) setting_value = message_values[2] + if _SHOW_IVY_MSGS_: + print("Got setting with index: %s value %s " % (setting_index, setting_value)) + # Store value from message self.lookup[setting_index].value = setting_value @@ -36,20 +39,17 @@ class IvySettingsInterface(PaparazziACSettings): if self.update_callback != None: self.update_callback(setting_index, setting_value, fromRemote) - if _SHOW_IVY_MSGS_: - print("index: %s value %s " % (setting_index, setting_value)) - # Called for DL_VALUE (from aircraft) def OnValueMsg(self, agent, *larg): # Extract field values - message_values = larg[0].split(' ') + message_values = filter(None, larg[0].split(' ')) message_values = message_values[0:1] + message_values[2:] self.ProcessMessage(message_values, True) # Called for DL_SETTING (from ground) def OnSettingMsg(self, agent, *larg): # Extract field values - message_values = larg[0].split(' ') + message_values = filter(None, larg[0].split(' ')) self.ProcessMessage(message_values, False) def RegisterCallback(self, callback_function): diff --git a/sw/lib/python/settings_xml_parse.py b/sw/lib/python/settings_xml_parse.py index b7000578d8..0d2258e227 100755 --- a/sw/lib/python/settings_xml_parse.py +++ b/sw/lib/python/settings_xml_parse.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -from __future__ import print_function +from __future__ import absolute_import, print_function import os import sys @@ -19,7 +19,8 @@ class PaparazziACSettings: def __init__(self, ac_id): self.ac_id = ac_id paparazzi_home = os.getenv("PAPARAZZI_HOME") - conf_xml_path = "%s/conf/conf.xml" % paparazzi_home + paparazzi_conf = os.path.join(paparazzi_home, 'conf') + conf_xml_path = os.path.join(paparazzi_conf, 'conf.xml') conf_tree = etree.parse(conf_xml_path) # extract aircraft node from conf.xml file ac_node = conf_tree.xpath('/conf/aircraft[@ac_id=%i]' % ac_id) @@ -27,56 +28,78 @@ class PaparazziACSettings: print("Aircraft ID %i not found." % ac_id) # get settings file path from aircraft xml node - settings_xml_path = "%s/conf/%s" % (paparazzi_home, ac_node[0].attrib['settings']) + settings_xml_files = filter(None, ac_node[0].attrib['settings'].split(' ')) + settings_xml_paths = [os.path.join(paparazzi_conf, s) for s in settings_xml_files] + #print("settings_xml_paths: %s" % settings_xml_paths) # save AC name for reference self.name = ac_node[0].attrib['name'] - tree = etree.parse(settings_xml_path) - index = 0 # keep track of index/id of setting starting at 0 - for the_tab in tree.xpath("//dl_settings"): - if the_tab.attrib.has_key('NAME'): - setting_group = PaparazziSettingsGroup(the_tab.attrib['NAME']) - elif the_tab.attrib.has_key('NAME'): - setting_group = PaparazziSettingsGroup(the_tab.attrib['name']) - else: - continue + for settings_file in settings_xml_paths: + #print("parsing settings file", settings_file) + tree = etree.parse(settings_file) - for the_setting in the_tab.xpath('dl_setting'): - if the_setting.attrib.has_key('shortname'): - name = the_setting.attrib['shortname'] - elif the_setting.attrib.has_key('VAR'): - name = the_setting.attrib['VAR'] - else: - name = the_setting.attrib['var'] - settings = PaparazziSetting(name) - settings.index = index - if the_setting.attrib.has_key('MIN'): - settings.min_value = float(the_setting.attrib['MIN']) - else: - settings.min_value = float(the_setting.attrib['min']) - if the_setting.attrib.has_key('MAX'): - settings.max_value = float(the_setting.attrib['MAX']) - else: - settings.max_value = float(the_setting.attrib['max']) - if the_setting.attrib.has_key('STEP'): - settings.step = float(the_setting.attrib['STEP']) - else: - settings.step = float(the_setting.attrib['step']) + for the_tab in tree.xpath("//dl_settings"): + try: + if 'NAME' in the_tab.attrib: + setting_group_name = the_tab.attrib['NAME'] + else: + setting_group_name = the_tab.attrib['name'] + except: + #print("Could not read name of settings group") + continue - if (the_setting.attrib.has_key('values')): - settings.values = the_setting.attrib['values'].split('|') - count = int((settings.max_value - settings.min_value + settings.step) / settings.step) - if (len(settings.values) != count): - print("Warning: wrong number of values (%i) for %s (expected %i)" % (len(settings.values), name, count)) + #print("parsing setting group:", setting_group_name) + setting_group = PaparazziSettingsGroup(setting_group_name) - setting_group.member_list.append(settings) - self.lookup.append(settings) - self.name_lookup[name] = settings - index = index + 1 + for the_setting in the_tab.xpath('dl_setting'): + try: + if 'shortname' in the_setting.attrib: + name = the_setting.attrib['shortname'] + elif 'VAR' in the_setting.attrib: + name = the_setting.attrib['VAR'] + else: + name = the_setting.attrib['var'] + except: + print("Could not get name for setting in group", setting_group) + continue - self.groups.append(setting_group) + settings = PaparazziSetting(name) + settings.index = index + print("add setting with index", index) + + try: + if 'MIN' in the_setting.attrib: + settings.min_value = float(the_setting.attrib['MIN']) + else: + settings.min_value = float(the_setting.attrib['min']) + + if 'MAX' in the_setting.attrib: + settings.max_value = float(the_setting.attrib['MAX']) + else: + settings.max_value = float(the_setting.attrib['max']) + + if 'STEP' in the_setting.attrib: + settings.step = float(the_setting.attrib['STEP']) + else: + settings.step = float(the_setting.attrib['step']) + except: + print("Could not get min/max/step for setting", name) + continue + + if 'values' in the_setting.attrib: + settings.values = the_setting.attrib['values'].split('|') + count = int((settings.max_value - settings.min_value + settings.step) / settings.step) + if (len(settings.values) != count): + print("Warning: possibly wrong number of values (%i) for %s (expected %i)" % (len(settings.values), name, count)) + + setting_group.member_list.append(settings) + self.lookup.append(settings) + self.name_lookup[name] = settings + index = index + 1 + + self.groups.append(setting_group) def GetACName(self): return self.name