mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-26 16:30:07 +08:00
[tools] Phyton-based Airframe File Editor
Squashed commit of the following: commit 67afebebdf3a2743b6c97ebac1a267c16aeff9b6 Author: Felix Ruess <felix.ruess@gmail.com> Date: Mon Sep 30 18:02:23 2013 +0200 [tools] airframe editor: minor fixes and pep8 commit f7ea77c13ea6d9df89afc098d033dae88d876b7d Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Mar 5 17:41:22 2013 +0100 New Group identification tag commit 0c20d2824ec4739954e7ee6930ec9c99966683fa Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Mar 5 16:28:47 2013 +0100 Delete old grouping tags to avoid growing in time commit 43902b8810711dba167c87fc9c35babc9c833a31 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Mar 5 16:01:09 2013 +0100 Better xml loading error handling commit a2590591708787fa2ba13b69dc8f64ea932d5979 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Mar 5 14:13:28 2013 +0100 Run xml_airframe standalone for batch conversions commit 1092bf0db9785e9434e41a69a460e6e00a19e81e Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Mar 5 14:07:48 2013 +0100 Save DTD path and initial comment from airframe.xml commit bf2a10603e20a66d7de3f6a097a4c5f091695047 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Mar 5 10:12:15 2013 +0100 Do not forget airframe name commit 44ddc63a181219c74e9a25d4c3a2a6a1e96acdb8 Author: Christophe De Wagter <dewagter@gmail.com> Date: Fri Feb 15 16:28:48 2013 +0100 Commenting change in airframe commit 172724335a78abd140f442518857e65a46e5ed97 Author: Christophe De Wagter <dewagter@gmail.com> Date: Fri Feb 15 16:26:26 2013 +0100 XML Structure commit 15e6cc8daf05b00d64b93f86a1b1322d991fffad Author: Christophe De Wagter <dewagter@gmail.com> Date: Fri Feb 15 09:26:12 2013 +0100 MenuBar commit 896303a1717e9efa5824bc3765267c55434ee0b9 Author: Christophe De Wagter <dewagter@gmail.com> Date: Thu Feb 14 22:39:11 2013 +0100 auto-grep commit 808339828f7e6c69d92112f91064716b59f66cc5 Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 21:55:21 2013 +0100 Search for defines commit 28bfce357b7b047c54d960dda992acd12a5a898e Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 20:35:23 2013 +0100 Show section content - editable commit 2dbfc5aed93d0f336c6509cab74d94f97c4b9d61 Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 18:54:26 2013 +0100 Boards commit 97ebb81240795ba4740018f17fc31e9a695111db Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 17:53:35 2013 +0100 Finally Fixed XML Output commit b27ddfb401abf8c7aa81770db9f0410ab66da27f Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 16:25:38 2013 +0100 Better Size Management commit e7fa8a66786d2ad15236211e80852f188a608b0f Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 07:54:12 2013 +0100 Rename commit 129bdda836b8d7d3064f7b79e54a7cae8a29bae9 Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 02:16:14 2013 +0100 Generate Nice and Grouped XML commit b6fc1f53ade5fc7f0e6b6cdadc9d07ab1307c414 Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 01:24:22 2013 +0100 Editor Update commit 996e70fe0db7737325ec24b0960e504aff58b105 Author: Christophe De Wagter <dewagter@gmail.com> Date: Wed Feb 13 00:28:34 2013 +0100 Restructure commit abcaedb90ae5f3de1ea520e354337008c06f3db2 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 18:48:13 2013 +0100 Automatic Airframe Re-Origanization commit 2faeb74a7d604d3a07b647692737af063bf9e2f6 Author: Felix Ruess <felix.ruess@gmail.com> Date: Tue Feb 12 17:40:38 2013 +0100 fix typo commit c991428d6411277a4d293a2e8e50b4da091ede96 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 16:54:17 2013 +0100 Pretty Print commit 8eac7f8f2cfe8b5eeaf4e2e90ec470be0a56dacc Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 15:38:19 2013 +0100 Open Files commit daf9a4723d71222e111b1c1274e45273eb275029 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 14:54:45 2013 +0100 Open File commit fb0a2eb10451bb19989ef35311ac10d69ba0f937 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 14:47:15 2013 +0100 Cleanup commit 6d7aeef7bf31e7c05738d8ccd90e91468bae24db Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 14:29:33 2013 +0100 Grouped paparazzi commit 2ec961acd51fd64337697152c92f49b82c560048 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 13:29:32 2013 +0100 paparazzi.py commit d0cb88cbbb7dc763d5a5545948c494fcad906b26 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 10:10:57 2013 +0100 Attempt to add comments in xml commit c10455d93e700438c91e34198d96bda5791d5aa9 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 10:10:33 2013 +0100 Paparazzi-Common commit 74214985f45b4c590af3702c2ec6a9e351b45895 Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 09:54:15 2013 +0100 Rename for Clarity commit 8ce5ecbd2477dffba9c06ca8e51357e83783aaef Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 09:48:54 2013 +0100 Module for gui stuff commit 293d776409c150e826b37d815a6198176fc2cacb Author: Christophe De Wagter <dewagter@gmail.com> Date: Tue Feb 12 09:12:26 2013 +0100 Read SubBlocks commit f166629579088fb905dfdfdfcc52632c524eb506 Author: Christophe De Wagter <dewagter@gmail.com> Date: Mon Feb 11 23:15:33 2013 +0100 DataGrid commit ab06a1e1f6a50aaa1fe92109993fe3ea80ba3cdb Author: Christophe De Wagter <dewagter@gmail.com> Date: Mon Feb 11 21:59:50 2013 +0100 Solve Merge Errors commit 90e3f626ad46657ebc9720e15de8b39e327afeea Author: Christophe De Wagter <dewagter@gmail.com> Date: Mon Feb 11 21:27:52 2013 +0100 TreeView commit 730cb7960d9c291ec3a9a2cdd3d05606c0d7c2b7 Author: Felix Ruess <felix.ruess@gmail.com> Date: Mon Feb 11 19:02:42 2013 +0100 get paparazzi_home from env, indentation 4spaces as in pep8 commit 2df5c4c972ec994fe3d42810e26c3b4166acc381 Author: Christophe De Wagter <dewagter@gmail.com> Date: Mon Feb 11 17:49:50 2013 +0100 Airframe Editor commit f71e2dd434121ecc16dbd2c682e1b6f89281388b Author: Christophe De Wagter <dewagter@gmail.com> Date: Mon Feb 11 15:55:02 2013 +0100 Phyton-based Airframe File Editor
This commit is contained in:
committed by
Felix Ruess
parent
81d3759f73
commit
84be7ddba2
@@ -73,8 +73,8 @@
|
||||
<define name="PITCH_NEUTRAL_DEFAULT" value="0"/>
|
||||
</section>
|
||||
|
||||
<!-- Local magnetic field -->
|
||||
<section name="AHRS" prefix="AHRS_">
|
||||
<!-- Local magnetic field -->
|
||||
<define name="H_X" value="0.51562740288882"/>
|
||||
<define name="H_Y" value="-0.05707735220832"/>
|
||||
<define name="H_Z" value="0.85490967783446"/>
|
||||
@@ -236,7 +236,7 @@
|
||||
<load name="nav_line.xml"/>
|
||||
</modules>
|
||||
|
||||
<!-- --------------------------------------------------------------------------- -->
|
||||
<!--+-+-+-+-+-+-+- PHOTOGRAMMETRY -+-+-+-+-+-+-+-->
|
||||
|
||||
|
||||
<section name="Photogrammetry" prefix="PHOTOGRAMMETRY_">
|
||||
|
||||
Executable
+358
@@ -0,0 +1,358 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import pygtk
|
||||
import gtk
|
||||
pygtk.require('2.0')
|
||||
|
||||
from os import path
|
||||
|
||||
# Owm Modules
|
||||
import gui_dialogs
|
||||
import xml_airframe
|
||||
import paparazzi
|
||||
|
||||
|
||||
# Airframe File
|
||||
airframe_file = path.join(paparazzi.airframes_dir, "examples/quadrotor_lisa_m_2_pwm_spektrum.xml")
|
||||
|
||||
|
||||
class AirframeEditor:
|
||||
|
||||
# General Functions
|
||||
|
||||
def load_airframe_xml(self):
|
||||
global airframe_file
|
||||
self.tvcolumn.set_title(airframe_file.replace(paparazzi.airframes_dir, ""))
|
||||
[e, self.xml, self.xml_header] = xml_airframe.load(airframe_file)
|
||||
if e:
|
||||
gui_dialogs.error_loading_xml(e.__str__())
|
||||
raise e
|
||||
xml_airframe.fill_tree(self.xml, self.treestore)
|
||||
|
||||
def update_combo(self, combo, c_list):
|
||||
combo.set_sensitive(False)
|
||||
combo.get_model().clear()
|
||||
for i in c_list:
|
||||
combo.append_text(i)
|
||||
combo.set_active(0)
|
||||
combo.set_sensitive(True)
|
||||
|
||||
# CallBack Functions
|
||||
|
||||
def find_firmwares(self, widget):
|
||||
list_of_firmwares = paparazzi.get_list_of_firmwares()
|
||||
self.update_combo(self.firmwares_combo, list_of_firmwares)
|
||||
|
||||
def find_modules(self, widget):
|
||||
list_of_modules = paparazzi.get_list_of_modules()
|
||||
self.update_combo(self.modules_combo, list_of_modules)
|
||||
|
||||
def find_subsystems(self, widget):
|
||||
self.textbox.set_text(self.firmwares_combo.get_active_text())
|
||||
list_of_subsystems = paparazzi.get_list_of_subsystems(self.firmwares_combo.get_active_text())
|
||||
self.update_combo(self.subsystems_combo, list_of_subsystems)
|
||||
|
||||
def find_boards(self, widget):
|
||||
list_of_boards = paparazzi.get_list_of_boards()
|
||||
self.update_combo(self.boards_combo, list_of_boards)
|
||||
|
||||
def find_module_defines(self, widget):
|
||||
mod = paparazzi.get_module_information(self.modules_combo.get_active_text())
|
||||
print(mod.description)
|
||||
txt = mod.description + "\n"
|
||||
for d in mod.defines:
|
||||
txt += "define: " + d[0].__str__() + " = " + d[1].__str__() + "; [" + d[2].__str__() + "] // " + d[3].__str__() + "\n"
|
||||
for c in mod.configures:
|
||||
txt += "configure: " + c[0].__str__() + " = " + c[1].__str__() + "; [" + c[2].__str__() + "] // " + c[3].__str__() + "\n"
|
||||
self.text_box.set_text(txt)
|
||||
self.gridstore.clear()
|
||||
for d in mod.defines:
|
||||
self.gridstore.append(["define", d[0], d[1], d[2], d[3]])
|
||||
|
||||
def reorganize_xml(self, widget):
|
||||
self.xml = xml_airframe.reorganize_airframe_xml(self.xml)
|
||||
xml_airframe.fill_tree(self.xml, self.treestore)
|
||||
|
||||
def about(self, widget):
|
||||
gui_dialogs.about(paparazzi.home_dir)
|
||||
|
||||
def open(self, widget):
|
||||
global airframe_file
|
||||
filename = gui_dialogs.filechooser(paparazzi.airframes_dir)
|
||||
if filename == "":
|
||||
print("No file selected")
|
||||
return
|
||||
airframe_file = filename
|
||||
self.load_airframe_xml()
|
||||
|
||||
def search(self, widget):
|
||||
ret = paparazzi.search(self.textbox.get_text())
|
||||
self.text_box.set_text(ret)
|
||||
print(ret)
|
||||
|
||||
# Tree Callbacks
|
||||
|
||||
def select_section(self, widget):
|
||||
#get data from highlighted selection
|
||||
treeselection = self.datagrid.get_selection()
|
||||
(model, row_iter) = treeselection.get_selected()
|
||||
if row_iter is not None:
|
||||
name_of_data = self.gridstore.get_value(row_iter, 1)
|
||||
#print("Selected ",name_of_data)
|
||||
self.textbox.set_text(name_of_data)
|
||||
# xml_airframe.defines(self.treestore.get_value(row_iter, 1), self.gridstore)
|
||||
|
||||
def select(self, widget):
|
||||
#get data from highlighted selection
|
||||
treeselection = self.treeview.get_selection()
|
||||
(model, row_iter) = treeselection.get_selected()
|
||||
if row_iter is not None:
|
||||
name_of_data = self.treestore.get_value(row_iter, 0)
|
||||
#print("Selected ",name_of_data)
|
||||
self.textbox.set_text(name_of_data)
|
||||
xml_airframe.defines(self.treestore.get_value(row_iter, 1), self.gridstore)
|
||||
|
||||
# Constructor Functions
|
||||
|
||||
def fill_tree_from_airframe(self):
|
||||
|
||||
# create a TreeStore with one string column to use as the model
|
||||
self.treestore = gtk.TreeStore(str, object)
|
||||
|
||||
# create the TreeView using treestore
|
||||
self.treeview = gtk.TreeView(self.treestore)
|
||||
|
||||
# create the TreeViewColumn to display the data
|
||||
self.tvcolumn = gtk.TreeViewColumn('')
|
||||
|
||||
# add self.tvcolumn to treeview
|
||||
self.treeview.append_column(self.tvcolumn)
|
||||
self.treeview.connect("cursor-changed", self.select)
|
||||
self.cell = gtk.CellRendererText()
|
||||
self.tvcolumn.pack_start(self.cell, True)
|
||||
self.tvcolumn.add_attribute(self.cell, 'text', 0)
|
||||
self.treeview.set_reorderable(True)
|
||||
|
||||
def fill_datagrid_from_section(self):
|
||||
|
||||
# create a TreeStore with one string column to use as the model
|
||||
self.gridstore = gtk.ListStore(str, str, str, str, str)
|
||||
|
||||
self.datagrid = gtk.TreeView(self.gridstore)
|
||||
|
||||
self.type_column = gtk.TreeViewColumn('Type')
|
||||
self.name_column = gtk.TreeViewColumn('Name')
|
||||
self.value_column = gtk.TreeViewColumn('Value')
|
||||
self.unit_column = gtk.TreeViewColumn('Unit')
|
||||
self.desc_column = gtk.TreeViewColumn('Description')
|
||||
|
||||
self.datagrid.append_column(self.type_column)
|
||||
self.datagrid.append_column(self.name_column)
|
||||
self.datagrid.append_column(self.value_column)
|
||||
self.datagrid.append_column(self.unit_column)
|
||||
self.datagrid.append_column(self.desc_column)
|
||||
self.datagrid.connect("cursor-changed", self.select_section)
|
||||
|
||||
self.type_cell = gtk.CellRendererText()
|
||||
self.type_cell.Editable = False
|
||||
self.name_cell = gtk.CellRendererText()
|
||||
self.name_cell.Editable = False
|
||||
self.value_cell = gtk.CellRendererText()
|
||||
self.value_cell.Editable = True
|
||||
self.value_cell.set_property("editable", True)
|
||||
self.unit_cell = gtk.CellRendererText()
|
||||
self.unit_cell.Editable = False
|
||||
self.desc_cell = gtk.CellRendererText()
|
||||
self.desc_cell.Editable = False
|
||||
|
||||
self.type_column.pack_start(self.type_cell, True)
|
||||
self.type_column.add_attribute(self.type_cell, 'text', 0)
|
||||
self.name_column.pack_start(self.name_cell, True)
|
||||
self.name_column.add_attribute(self.name_cell, 'text', 1)
|
||||
self.value_column.pack_start(self.value_cell, True)
|
||||
self.value_column.add_attribute(self.value_cell, 'text', 2)
|
||||
self.unit_column.pack_start(self.unit_cell, True)
|
||||
self.unit_column.add_attribute(self.unit_cell, 'text', 3)
|
||||
self.desc_column.pack_start(self.desc_cell, True)
|
||||
self.desc_column.add_attribute(self.desc_cell, 'text', 4)
|
||||
|
||||
self.datagrid.set_search_column(1)
|
||||
self.name_column.set_sort_column_id(0)
|
||||
self.datagrid.set_reorderable(True)
|
||||
|
||||
|
||||
def destroy(self, widget, data=None):
|
||||
gtk.main_quit()
|
||||
|
||||
def __init__(self):
|
||||
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
|
||||
self.window.set_title("Paparazzi Airframe File Editor")
|
||||
|
||||
self.my_vbox = gtk.VBox()
|
||||
|
||||
# MenuBar
|
||||
mb = gtk.MenuBar()
|
||||
|
||||
# File
|
||||
filemenu = gtk.Menu()
|
||||
|
||||
# File Title
|
||||
filem = gtk.MenuItem("File")
|
||||
filem.set_submenu(filemenu)
|
||||
|
||||
openm = gtk.MenuItem("Open")
|
||||
openm.connect("activate", self.open)
|
||||
filemenu.append(openm)
|
||||
|
||||
exitm = gtk.MenuItem("Exit")
|
||||
exitm.connect("activate", gtk.main_quit)
|
||||
filemenu.append(exitm)
|
||||
|
||||
mb.append(filem)
|
||||
|
||||
# Help
|
||||
helpmenu = gtk.Menu()
|
||||
|
||||
# Help Title
|
||||
helpm = gtk.MenuItem("Help")
|
||||
helpm.set_submenu(helpmenu)
|
||||
|
||||
aboutm = gtk.MenuItem("About")
|
||||
aboutm.connect("activate", self.about)
|
||||
helpmenu.append(aboutm)
|
||||
|
||||
mb.append(helpm)
|
||||
|
||||
self.my_vbox.pack_start(mb, False)
|
||||
|
||||
##### Buttons
|
||||
self.btnExit = gtk.Button("Exit")
|
||||
self.btnExit.connect("clicked", self.destroy)
|
||||
self.btnExit.set_tooltip_text("Close application")
|
||||
|
||||
self.btnOpen = gtk.Button("Open")
|
||||
self.btnOpen.connect("clicked", self.open)
|
||||
|
||||
self.btnRun = gtk.Button("Reorganize XML")
|
||||
self.btnRun.connect("clicked", self.reorganize_xml)
|
||||
|
||||
self.btnFirmwares = gtk.Button("Firmwares")
|
||||
self.btnFirmwares.connect("clicked", self.find_firmwares)
|
||||
|
||||
self.btnSubSystem = gtk.Button("SubSystems")
|
||||
self.btnSubSystem.connect("clicked", self.find_subsystems)
|
||||
|
||||
self.btnModules = gtk.Button("Add Modules")
|
||||
self.btnModules.connect("clicked", self.find_modules)
|
||||
|
||||
self.btnModuleDefines = gtk.Button("Define")
|
||||
self.btnModuleDefines.connect("clicked", self.find_module_defines)
|
||||
|
||||
self.btnAbout = gtk.Button("About")
|
||||
self.btnAbout.connect("clicked", self.about)
|
||||
|
||||
self.toolbar = gtk.HBox()
|
||||
self.toolbar.pack_start(self.btnOpen)
|
||||
self.toolbar.pack_start(self.btnRun)
|
||||
self.toolbar.pack_start(self.btnAbout)
|
||||
self.toolbar.pack_start(self.btnExit)
|
||||
|
||||
self.my_vbox.pack_start(self.toolbar, False)
|
||||
|
||||
|
||||
|
||||
self.firmwares_combo = gtk.combo_box_entry_new_text()
|
||||
self.find_firmwares(self.firmwares_combo)
|
||||
self.firmwares_combo.connect("changed", self.find_subsystems)
|
||||
|
||||
self.subsystems_combo = gtk.combo_box_entry_new_text()
|
||||
|
||||
self.boards_combo = gtk.combo_box_entry_new_text()
|
||||
self.find_boards(self.boards_combo)
|
||||
|
||||
|
||||
self.firmwarebar = gtk.HBox()
|
||||
self.firmwarebar.pack_start(self.btnFirmwares)
|
||||
self.firmwarebar.pack_start(self.btnSubSystem)
|
||||
self.firmwarebar.pack_start(self.firmwares_combo)
|
||||
self.firmwarebar.pack_start(self.boards_combo)
|
||||
self.firmwarebar.pack_start(self.subsystems_combo)
|
||||
|
||||
self.modules_combo = gtk.combo_box_entry_new_text()
|
||||
self.find_modules(self.modules_combo)
|
||||
self.modules_combo.connect("changed", self.find_module_defines)
|
||||
|
||||
#self.modulebar = gtk.HBox()
|
||||
self.firmwarebar.pack_start(self.btnModules)
|
||||
self.firmwarebar.pack_start(self.btnModuleDefines)
|
||||
self.firmwarebar.pack_start(self.modules_combo)
|
||||
|
||||
#self.my_vbox.pack_start(self.modulebar)
|
||||
|
||||
self.my_vbox.pack_start(self.firmwarebar, False)
|
||||
|
||||
|
||||
|
||||
|
||||
##### Middle
|
||||
|
||||
self.editor = gtk.HBox()
|
||||
|
||||
self.fill_tree_from_airframe()
|
||||
|
||||
self.scrolltree = gtk.ScrolledWindow()
|
||||
self.scrolltree.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self.scrolltree.add(self.treeview)
|
||||
self.scrolltree.set_size_request(400,600)
|
||||
|
||||
self.editor.pack_start(self.scrolltree)
|
||||
|
||||
self.fill_datagrid_from_section()
|
||||
self.datagrid.set_size_request(900, 600)
|
||||
self.editor.pack_start(self.datagrid)
|
||||
|
||||
self.my_vbox.pack_start(self.editor)
|
||||
|
||||
self.text_box = gtk.Label("")
|
||||
self.text_box.set_size_request(600, 1000)
|
||||
|
||||
self.scrolltext = gtk.ScrolledWindow()
|
||||
self.scrolltext.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
|
||||
self.scrolltext.add_with_viewport(self.text_box)
|
||||
self.scrolltext.set_size_request(400, 100)
|
||||
|
||||
self.my_vbox.pack_start(self.scrolltext)
|
||||
|
||||
self.load_airframe_xml()
|
||||
|
||||
##### Bottom
|
||||
|
||||
self.searchbar = gtk.HBox()
|
||||
|
||||
self.textbox = gtk.Entry()
|
||||
#self.textbox.connect("changed",self.textchanged)
|
||||
|
||||
self.btnSearch = gtk.Button("Search...")
|
||||
self.btnSearch.connect("clicked", self.search)
|
||||
|
||||
self.searchbar.pack_start(self.textbox)
|
||||
self.searchbar.pack_start(self.btnSearch)
|
||||
|
||||
self.my_vbox.pack_start(self.searchbar, False)
|
||||
|
||||
self.window.add(self.my_vbox)
|
||||
self.window.show_all()
|
||||
self.window.connect("destroy", self.destroy)
|
||||
|
||||
def main(self):
|
||||
gtk.main()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
if len(sys.argv) > 1:
|
||||
airframe_file = sys.argv[1]
|
||||
gui = AirframeEditor()
|
||||
gui.main()
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import gtk
|
||||
from os import path
|
||||
|
||||
|
||||
if gtk.pygtk_version < (2, 3, 90):
|
||||
print("Please upgrade your pygtk")
|
||||
raise SystemExit
|
||||
|
||||
|
||||
def filechooser(pathname):
|
||||
dialog = gtk.FileChooserDialog("Open ...", None,
|
||||
gtk.FILE_CHOOSER_ACTION_OPEN,
|
||||
(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
|
||||
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
|
||||
|
||||
dialog.set_default_response(gtk.RESPONSE_OK)
|
||||
dialog.set_current_folder(pathname)
|
||||
|
||||
filter = gtk.FileFilter()
|
||||
filter.set_name("Airframe File")
|
||||
filter.add_pattern("*.xml")
|
||||
dialog.add_filter(filter)
|
||||
|
||||
response = dialog.run()
|
||||
filename = ""
|
||||
if response == gtk.RESPONSE_OK:
|
||||
filename = dialog.get_filename()
|
||||
elif response == gtk.RESPONSE_CANCEL:
|
||||
print("No file selected")
|
||||
|
||||
return filename
|
||||
|
||||
|
||||
def error_loading_xml(s):
|
||||
err_msg = gtk.MessageDialog(None, gtk.DIALOG_DESTROY_WITH_PARENT,
|
||||
gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE,
|
||||
"Error Loading XML: " + s)
|
||||
err_msg.run()
|
||||
err_msg.destroy()
|
||||
|
||||
|
||||
def about(home):
|
||||
about_d = gtk.AboutDialog()
|
||||
about_d.set_program_name("Paparazzi Airframe Editor")
|
||||
about_d.set_version("0.1")
|
||||
about_d.set_copyright("(c) GPL v2")
|
||||
about_d.set_comments("Airframe Editor")
|
||||
about_d.set_website("http://paparazzi.github.io")
|
||||
about_d.set_logo(gtk.gdk.pixbuf_new_from_file(path.join(home, "data/pictures/penguin_icon.png")))
|
||||
about_d.run()
|
||||
about_d.destroy()
|
||||
|
||||
Executable
+95
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import glob
|
||||
|
||||
from collections import namedtuple
|
||||
from os import path, getenv
|
||||
#from subprocess import call
|
||||
import commands
|
||||
|
||||
import lxml.etree as ET
|
||||
|
||||
# if PAPARAZZI_HOME not set, then assume the tree containing this
|
||||
# file is a reasonable substitute
|
||||
home_dir = getenv("PAPARAZZI_HOME", path.normpath(path.join(
|
||||
path.dirname(path.abspath(__file__)), '../../../')))
|
||||
|
||||
# Directories
|
||||
firmwares_dir = path.join(home_dir, "conf/firmwares/")
|
||||
modules_dir = path.join(home_dir, "conf/modules/")
|
||||
airframes_dir = path.join(home_dir, "conf/airframes/")
|
||||
boards_dir = path.join(home_dir, "conf/boards/")
|
||||
|
||||
# Structures
|
||||
PprzModule = namedtuple("PprzModule", "description defines configures")
|
||||
|
||||
# List Of Stuff
|
||||
def get_list_of_files(directory, extension):
|
||||
mylist = glob.glob(path.join(directory, "*" + extension))
|
||||
mylist.sort()
|
||||
ret = []
|
||||
for it in mylist:
|
||||
ret.append( it.replace(directory, "").replace(extension, ""))
|
||||
return ret
|
||||
|
||||
def get_list_of_modules():
|
||||
return get_list_of_files( modules_dir, ".xml")
|
||||
|
||||
def get_list_of_firmwares():
|
||||
return get_list_of_files( firmwares_dir, ".makefile")
|
||||
|
||||
def get_list_of_boards():
|
||||
return get_list_of_files( boards_dir, ".makefile")
|
||||
|
||||
def get_list_of_subsystems(firmware):
|
||||
subsys_dir = path.join( firmwares_dir, "subsystems/" + firmware + "/")
|
||||
# \todo how about shared
|
||||
#subsys_dir = path.join( firmwares_dir, "subsystems/shared/" )
|
||||
return get_list_of_files(subsys_dir, ".makefile")
|
||||
|
||||
def get_list_of_servo_drivers():
|
||||
# \todo where do we know this?
|
||||
return ["Ppm", "Asctec", "Scilab"]
|
||||
|
||||
def get_module_information(module_name):
|
||||
str_desc = ""
|
||||
lst_def = []
|
||||
lst_conf = []
|
||||
try:
|
||||
xml = ET.parse(path.join(modules_dir, module_name + ".xml"))
|
||||
root = xml.getroot().find("doc")
|
||||
str_desc = root.find("description").text
|
||||
for block in root.iter("define"):
|
||||
lst_def.append([block.get("name"), block.get("value"), block.get("unit"), block.get("description")])
|
||||
for block in root.iter("configure"):
|
||||
lst_conf.append([block.get("name"), block.get("value"), block.get("unit"), block.get("description")])
|
||||
except (IOError, ET.XMLSyntaxError) as e:
|
||||
print(e.__str__())
|
||||
|
||||
return PprzModule(description=str_desc, defines=lst_def, configures=lst_conf)
|
||||
|
||||
|
||||
def search(string):
|
||||
#return call(["grep", "-r", string , home_dir + "/sw/airborne/"])
|
||||
#return system("grep -r " + string + " " + home_dir + "/sw/airborne/")
|
||||
cmd = "grep -r " + string + " " + home_dir + "/sw/airborne/"
|
||||
status, output = commands.getstatusoutput(cmd)
|
||||
return output.replace(home_dir + "/sw/airborne/", "")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("====HOME==== ", home_dir)
|
||||
print("----MODULES---- ", modules_dir)
|
||||
print(get_list_of_modules())
|
||||
for mod in get_list_of_modules():
|
||||
print(mod, " ---> ", get_module_information(mod))
|
||||
print("----FIRMWARES---- ", firmwares_dir)
|
||||
print(get_list_of_firmwares())
|
||||
for firm in get_list_of_firmwares():
|
||||
print(firm, " ---> ", get_list_of_subsystems(firm))
|
||||
print("shared", " ---> ", get_list_of_subsystems("shared"))
|
||||
print("----BOARDS---- ", firmwares_dir)
|
||||
print(get_list_of_boards())
|
||||
|
||||
Executable
+195
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import lxml.etree as ET
|
||||
import StringIO
|
||||
|
||||
import xml_common
|
||||
import paparazzi
|
||||
|
||||
|
||||
def find_and_add(source, target, search):
|
||||
temp = source.getroot().findall("./" + search)
|
||||
for t in temp:
|
||||
xml_common.indent(t, 1)
|
||||
target.extend(temp)
|
||||
|
||||
|
||||
def find_and_add_sections_with_name(source, target, find_name):
|
||||
temp = source.getroot().findall("./*[@name='" + find_name + "']")
|
||||
for t in temp:
|
||||
xml_common.indent(t, 1)
|
||||
target.extend(temp)
|
||||
|
||||
|
||||
group_identification_string = " ************************* "
|
||||
|
||||
|
||||
def find_or_add_group(source, target, search):
|
||||
groupname = group_identification_string + search + group_identification_string
|
||||
target.append(ET.Comment(groupname))
|
||||
for block in source.getroot():
|
||||
if isinstance(block, ET._Comment):
|
||||
if block.__str__() == "<!--" + groupname + "-->":
|
||||
source.getroot().remove(block)
|
||||
|
||||
|
||||
def reorganize_airframe_xml(airframe_xml):
|
||||
some_file_like_object = StringIO.StringIO("<airframe/>")
|
||||
airframe_xml_tree = ET.parse(some_file_like_object)
|
||||
airframe = airframe_xml_tree.getroot()
|
||||
|
||||
if 'name' not in airframe_xml.getroot().attrib:
|
||||
print("Airframe has no name!")
|
||||
else:
|
||||
airframe.set('name', airframe_xml.getroot().get('name'))
|
||||
|
||||
find_or_add_group(airframe_xml, airframe, "FIRMWARE")
|
||||
find_and_add(airframe_xml, airframe, "firmware")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "AUTOPILOT")
|
||||
|
||||
find_or_add_group(airframe_xml, airframe, "MODULES")
|
||||
find_and_add(airframe_xml, airframe, "modules")
|
||||
|
||||
find_or_add_group(airframe_xml, airframe, "ACTUATORS")
|
||||
find_and_add(airframe_xml, airframe, "servos")
|
||||
find_and_add(airframe_xml, airframe, "commands")
|
||||
find_and_add(airframe_xml, airframe, "ap_only_commands")
|
||||
find_and_add(airframe_xml, airframe, "rc_commands")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "AUTO1")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "SERVO_MIXER_GAINS")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "MIXER")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "MIXING")
|
||||
find_and_add(airframe_xml, airframe, "command_laws")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "TRIM")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "FAILSAFE")
|
||||
|
||||
find_or_add_group(airframe_xml, airframe, "SENSORS")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "ADC")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "INFRARED")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "IMU")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "AHRS")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "INS")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "XSENS")
|
||||
|
||||
find_or_add_group(airframe_xml, airframe, "GAINS")
|
||||
# Fixedwing
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "HORIZONTAL CONTROL")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "VERTICAL CONTROL")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "AGGRESSIVE")
|
||||
# Rotorcraft
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "STABILIZATION_RATE")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "STABILIZATION_ATTITUDE")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "GUIDANCE_V")
|
||||
find_and_add_sections_with_name(airframe_xml, airframe, "GUIDANCE_H")
|
||||
|
||||
find_or_add_group(airframe_xml, airframe, "MISC")
|
||||
|
||||
find_and_add(airframe_xml, airframe, "*")
|
||||
|
||||
xml_common.indent(airframe)
|
||||
|
||||
temp = airframe.findall("./*")
|
||||
for t in temp:
|
||||
t.tail = "\n\n "
|
||||
|
||||
#print(etree.tostring(airframe))
|
||||
#ET.ElementTree(airframe_xml_tree).write('test.xml')
|
||||
return airframe_xml_tree
|
||||
|
||||
|
||||
def get_airframe_header(airframe_file):
|
||||
try:
|
||||
with open(airframe_file) as inputFileHandle:
|
||||
fullfile = inputFileHandle.read()
|
||||
pos = fullfile.find("<airframe")
|
||||
if pos > 0:
|
||||
return fullfile[0:pos]
|
||||
else:
|
||||
return ""
|
||||
except IOError:
|
||||
return ""
|
||||
|
||||
|
||||
def add_text_before_file(text_file, new_string):
|
||||
try:
|
||||
fullfile = ""
|
||||
with open(text_file) as inputFileHandle:
|
||||
fullfile = inputFileHandle.read()
|
||||
inputFileHandle.close()
|
||||
with open(text_file, 'w') as outputFileHandle:
|
||||
outputFileHandle.write(new_string)
|
||||
outputFileHandle.write(fullfile)
|
||||
outputFileHandle.close()
|
||||
except IOError:
|
||||
return
|
||||
|
||||
|
||||
def load(airframe_file):
|
||||
try:
|
||||
my_xml = ET.parse(airframe_file)
|
||||
return [None, my_xml, get_airframe_header(airframe_file)]
|
||||
except (IOError, ET.XMLSyntaxError, ET.XMLSyntaxError) as e:
|
||||
print(" ERROR: Loading XML failed: ")
|
||||
print(e)
|
||||
quit()
|
||||
|
||||
|
||||
def fill_tree_children(block, tree, parent):
|
||||
for elem in block:
|
||||
ename = elem.get("name")
|
||||
if ename is None:
|
||||
ename = ""
|
||||
# Only add sub-blocks if there are children
|
||||
if len(elem) or ((block.tag != "section") & (block.tag != "load")):
|
||||
if not isinstance(elem, ET._Comment):
|
||||
piter = tree.append(parent, [elem.tag.__str__() + " " + ename, elem])
|
||||
fill_tree_children(elem, tree, piter)
|
||||
|
||||
|
||||
def fill_tree(my_xml, tree):
|
||||
root = my_xml.getroot()
|
||||
|
||||
tree.clear()
|
||||
add_place = None
|
||||
for block in root:
|
||||
if not isinstance(block, ET._Comment):
|
||||
name = block.get("name")
|
||||
if name is None:
|
||||
name = ""
|
||||
|
||||
# print(block.tag.__str__() + " " + name)
|
||||
piter = tree.append(add_place, [block.tag.__str__() + " " + name, block])
|
||||
fill_tree_children(block, tree, piter)
|
||||
else:
|
||||
add_place = tree.append(None, [block.__str__().replace("<!--" + group_identification_string, "[").replace(
|
||||
group_identification_string + "-->", "]"), block])
|
||||
|
||||
|
||||
def defines(elem, grid):
|
||||
grid.clear()
|
||||
for e in elem.findall("./define"):
|
||||
grid.append(["define", e.get("name"), e.get("value"), e.get("unit"), e.get("description")])
|
||||
for e in elem.findall("./configure"):
|
||||
grid.append(["configure", e.get("name"), e.get("value"), e.get("unit"), e.get("description")])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
outputfile = 'test.xml'
|
||||
if len(sys.argv) > 1:
|
||||
airframe_file = sys.argv[1]
|
||||
if len(sys.argv) > 2:
|
||||
outputfile = sys.argv[2]
|
||||
if len(sys.argv) > 3:
|
||||
outputfile = airframe_file
|
||||
else:
|
||||
airframe_file = "../../../conf/airframes/CDW/yapa_xsens.xml"
|
||||
|
||||
print(airframe_file)
|
||||
[e, airframe, hdr] = load(airframe_file)
|
||||
xml = reorganize_airframe_xml(airframe)
|
||||
ET.ElementTree(xml.getroot()).write(outputfile)
|
||||
add_text_before_file(outputfile, hdr)
|
||||
@@ -0,0 +1,27 @@
|
||||
from __future__ import print_function
|
||||
|
||||
|
||||
def indent(elem, level=0, more_sibs=False):
|
||||
i = "\n"
|
||||
num_kids = len(elem)
|
||||
if level:
|
||||
i += (level-1) * ' '
|
||||
#print(level, elem.tag, num_kids, more_sibs)
|
||||
if num_kids:
|
||||
if not elem.text or not elem.text.strip():
|
||||
elem.text = i + " "
|
||||
if level:
|
||||
elem.text += ' '
|
||||
count = 0
|
||||
for kid in elem:
|
||||
indent(kid, level+1, count < num_kids - 1)
|
||||
count += 1
|
||||
if not elem.tail or not elem.tail.strip():
|
||||
elem.tail = i
|
||||
if more_sibs:
|
||||
elem.tail += ' '
|
||||
else:
|
||||
if level and (not elem.tail or not elem.tail.strip()):
|
||||
elem.tail = i
|
||||
if more_sibs:
|
||||
elem.tail += ' '
|
||||
Reference in New Issue
Block a user