示例#1
0
 def load(self, camera_config, local_config, scale=1.0):
     if camera_config is None:
         if os.path.exists(local_config):
             # load local config file if it exists
             result = props_json.load(local_config, self.config)
             if not result:
                 print("Cannot continue with invalid camera file.")
                 quit()
         else:
             print(
                 "no camera config specified and no local camera config file found:",
                 local_config)
             quit()
     else:
         # seed the camera calibration and distortion coefficients
         # from a known camera config
         print("Setting camera config from:", camera_config)
         props_json.load(camera_config, self.config)
         self.config.setString('name', camera_config)
         props_json.save(local_config, self.config)
     self.get_K()
     if scale:
         # adjust effective K to account for scaling
         self.K = self.K * scale
         self.K[2, 2] = 1.0
     self.config.setLen('mount_ypr', 3, 0)
示例#2
0
    def load_images_info(self):
        # wipe image list (so we don't double load)
        self.image_list = []

        # load image meta info
        meta_dir = os.path.join(self.analysis_dir, "meta")
        images_node = getNode("/images", True)
        for file in sorted(os.listdir(meta_dir)):
            if fnmatch.fnmatch(file, '*.json'):
                name, ext = os.path.splitext(file)
                image_node = images_node.getChild(name, True)
                props_json.load(os.path.join(meta_dir, file), image_node)
                i1 = image.Image(self.analysis_dir, name)
                self.image_list.append(i1)
示例#3
0
    def load(self, create=True):
        if not self.validate_project_dir(create):
            return

        # load project configuration
        result = False
        project_file = os.path.join(self.analysis_dir, "config.json")
        config_node = getNode("/config", True)
        if os.path.isfile(project_file):
            if props_json.load(project_file, config_node):
                # fixme:
                # if 'matcher' in project_dict:
                #     self.matcher_params = project_dict['matcher']
                # root.pretty_print()
                result = True
            else:
                log("Notice: unable to load: ", project_file)
        else:
            log("project: project configuration doesn't exist:", project_file)
        if not result and create:
            log("Continuing with an empty project configuration")
            self.set_defaults()
        elif not result:
            log("Project load failed, aborting...")
            quit()

        # overwrite project_dir with current location (this will get
        # saved out into the config.json, but projects could relocate
        # and it's more important to have the actual current location)
        self.dir_node.setString('project_dir', self.project_dir)
示例#4
0
    def load(self, create=True):
        if not self.validate_project_dir():
            return

        # load project configuration
        result = False
        project_file = os.path.join(self.project_dir, "config.json")
        config_node = getNode("/config", True)
        if os.path.isfile(project_file):
            if props_json.load(project_file, config_node):
                # fixme:
                # if 'matcher' in project_dict:
                #     self.matcher_params = project_dict['matcher']
                # root.pretty_print()
                result = True
            else:
                print("Notice: unable to load: ", project_file)
        else:
            print("Notice: project configuration doesn't exist:", project_file)
        if not result and create:
            print("Continuing with an empty project configuration")
            self.set_defaults()
        elif not result:
            print("aborting...")
            quit()
示例#5
0
    def load_images_info(self):
        # load image meta info
        result = False
        meta_dir = os.path.join(self.analysis_dir, 'meta')
        images_node = getNode("/images", True)

        for file in os.listdir(meta_dir):
            if fnmatch.fnmatch(file, '*.json'):
                name, ext = os.path.splitext(file)
                image_node = images_node.getChild(name, True)
                props_json.load(os.path.join(meta_dir, file), image_node)
        # images_node.pretty_print()
                
        # wipe image list (so we don't double load)
        self.image_list = []
        for name in images_node.getChildren():
            img = image.Image(self.analysis_dir, name)
            self.image_list.append( img )
def set_camera(project_dir,
               camera,
               yaw_deg=0.0,
               pitch_deg=-90.0,
               roll_deg=0.0):
    proj = ProjectMgr.ProjectMgr(project_dir)

    if camera:
        # specified on command line
        camera_file = camera
    else:
        # auto detect camera from image meta data
        camera, make, model, lens_model = proj.detect_camera()
        camera_file = os.path.join("..", "cameras", camera + ".json")
    print("Camera:", camera_file)

    # copy/overlay/update the specified camera config into the existing
    # project configuration
    cam_node = getNode('/config/camera', True)
    tmp_node = PropertyNode()
    if props_json.load(camera_file, tmp_node):
        for child in tmp_node.getChildren(expand=False):
            if tmp_node.isEnum(child):
                # print(child, tmp_node.getLen(child))
                for i in range(tmp_node.getLen(child)):
                    cam_node.setFloatEnum(child, i,
                                          tmp_node.getFloatEnum(child, i))
            else:
                # print(child, type(tmp_node.__dict__[child]))
                child_type = type(tmp_node.__dict__[child])
                if child_type is float:
                    cam_node.setFloat(child, tmp_node.getFloat(child))
                elif child_type is int:
                    cam_node.setInt(child, tmp_node.getInt(child))
                elif child_type is str:
                    cam_node.setString(child, tmp_node.getString(child))
                else:
                    print('Unknown child type:', child, child_type)

        proj.cam.set_mount_params(yaw_deg, pitch_deg, roll_deg)

        # note: dist_coeffs = array[5] = k1, k2, p1, p2, k3

        # ... and save
        proj.save()
    else:
        # failed to load camera config file
        if not camera:
            print("Camera autodetection failed.")
            print(
                "Consider running the new camera script to create a camera config"
            )
            print("and then try running this script again.")
        else:
            print("Provided camera config not found:", camera)
示例#7
0
    def load_area_info(self, area='area-00'):
        # load image meta info for specified sub area
        result = False
        meta_dir = os.path.join(self.project_dir, 'meta')
        images_node = getNode("/images", True)

        area_file = os.path.join(self.project_dir, area, 'image_list')
        area_list = pickle.load(open(area_file, 'rb'))
        for name in area_list:
            meta_file = os.path.join(meta_dir, name + ".json")
            image_node = images_node.getChild(name, True)
            props_json.load(meta_file, image_node)
        # images_node.pretty_print()

        # wipe image list (so we don't double load)
        self.image_list = []
        for name in images_node.getChildren():
            image = Image.Image(meta_dir, name)
            self.image_list.append(image)

        # make sure our matcher gets a copy of the image list
        self.render.setImageList(self.image_list)
    for row in full_list:
        writer.writerow(row)

# copy config.json from first listed source project
print("Copying config.json from source project")
config_src = os.path.join(args.source[0], "ImageAnalysis", "config.json")
config_dest = os.path.join(analysis_dir, "config.json")
if os.path.exists(config_src):
    shutil.copyfile(config_src, config_dest)

# assemble the collective smart.json file
print("Combining all the smart.json files")
smart_node = getNode("/smart", True)
for p in args.source:
    smart_src = os.path.join(p, "ImageAnalysis", "smart.json")
    props_json.load(smart_src, smart_node)
smart_dst = os.path.join(project_dir, "ImageAnalysis", "smart.json")
props_json.save(smart_dst, smart_node)

# assemble the collective annotations.json file
print("Combining any annotations.json files")
ann_node = getNode("/annotations", True)
ann_list = []
for p in args.source:
    ann_src = os.path.join(p, "ImageAnalysis", "annotations.json")
    if os.path.exists(ann_src):
        f = open(ann_src, 'r')
        ann_list += json.load(f)
ann_dst = os.path.join(project_dir, "ImageAnalysis", "annotations.json")
f = open(ann_dst, 'w')
json.dump(ann_list, f, indent=4)
示例#9
0
def load(analysis_dir):
    surface_file = os.path.join(analysis_dir, "smart.json")
    props_json.load(surface_file, smart_node)
示例#10
0
args = parser.parse_args()

#file = args.movie
scale = args.scale
skip_frames = args.skip_frames

# pathname work
abspath = os.path.abspath(args.movie)
filename, ext = os.path.splitext(abspath)
dirname = os.path.dirname(args.movie)
output_csv = filename + ".csv"
camera_config = dirname + "/camera.json"

# load config file if it exists
config = PropertyNode()
props_json.load(camera_config, config)
cam_yaw = config.getFloatEnum('mount_ypr', 0)
cam_pitch = config.getFloatEnum('mount_ypr', 1)
cam_roll = config.getFloatEnum('mount_ypr', 2)

# setup camera calibration and distortion coefficients
if args.select_cam:
    # set the camera calibration from known preconfigured setups
    name, K, dist = cam_calib.set_camera_calibration(args.select_cam)
    config.setString('name', name)
    config.setFloat("fx", K[0][0])
    config.setFloat("fy", K[1][1])
    config.setFloat("cu", K[0][2])
    config.setFloat("cv", K[1][2])
    for i, d in enumerate(dist):
        config.setFloatEnum("dist_coeffs", i, d)
示例#11
0
    def load(self, filename, host="localhost", port=6499):
        print "Tuner.load " + str(port)
        basename = os.path.basename(str(filename))
        fileroot, ext = os.path.splitext(basename)

        if filename == "":
            error = QtGui.QErrorMessage(self)
            error.showMessage(
                "Error, you must specify an autopilot config file name")
            return
        elif not os.path.exists(filename):
            error = QtGui.QErrorMessage(self)
            error.showMessage(filename + ": does not exist")
            return

        try:
            props_json.load(filename, root)
        except:
            error = QtGui.QErrorMessage(self)
            error.showMessage(filename + ": parse error:\n" +
                              str(sys.exc_info()[1]))
            return

        self.filename = str(filename)
        self.fileroot, ext = os.path.splitext(self.filename)

        # Route follow parameters
        self.L1 = L1Controller(changefunc=self.onChange, host=host, port=port)
        L1_node = getNode('/L1_controller', create=True)
        self.L1.parse(L1_node)
        self.tabs.addTab(self.L1.get_widget(), "L1")

        # PID controller parameters
        print root.getChild('component')
        len = root.getLen('component')
        #comp_node = getNode('/component', create=True)
        for i in range(len):
            node_name = 'component[%d]' % i
            print node_name
            node = root.getChild(node_name)
            comp_type = node.getString('module')
            if comp_type == 'pid_component':
                pid = Component(index=i,
                                changefunc=self.onChange,
                                host=host,
                                port=port,
                                type="pid")
            elif comp_type == 'pid_vel_component':
                pid = Component(index=i,
                                changefunc=self.onChange,
                                host=host,
                                port=port,
                                type="vel")
            elif comp_type == 'summer':
                pid = Component(index=i,
                                changefunc=self.onChange,
                                host=host,
                                port=port,
                                type="sum")
            else:
                print "unknown ..."
                next
            pid.parse(node)
            self.components.append(pid)
            self.tabs.addTab(pid.get_widget(), pid.get_name())
示例#12
0
from control import navigation
from drivers import pilot_helper
from health import health
from mission import mission_mgr
from util import myprof, timer

parser = argparse.ArgumentParser(description="Rice Creak UAS flight code")
parser.add_argument("--config", required=True, help="path to config tree")
parser.add_argument("--verbose",
                    action="store_true",
                    help="enable additional console verbocity")
args = parser.parse_args()

# load master config file
config_file = os.path.join(args.config, "main.json")
result = props_json.load(config_file, root)
if result:
    print("Loaded master configuration file:", config_file)
    if args.verbose:
        root.pretty_print()
    config_node = getNode("/config")
    config_node.setString("path", args.config)
else:
    print("*** Cannot load master config file:", config_file)
    print()
    print("Cannot continue without a valid configuration, sorry.")
    exit(-1)

# shared property nodes
comms_node = getNode("/comms", True)
imu_node = getNode("/sensors/imu", True)
示例#13
0
    camera = camera.replace(' ', '_')
    return camera


image1 = args.image1
image2 = args.image2

cam1 = detect_camera(image1)
cam2 = detect_camera(image2)
print(cam1)
print(cam2)

cam1_node = getNode("/camera1", True)
cam2_node = getNode("/camera2", True)

if props_json.load(os.path.join("../cameras", cam1 + ".json"), cam1_node):
    print("successfully loaded cam1 config")
if props_json.load(os.path.join("../cameras", cam2 + ".json"), cam2_node):
    print("successfully loaded cam2 config")

tmp = []
for i in range(9):
    tmp.append(cam1_node.getFloatEnum('K', i))
K1 = np.copy(np.array(tmp)).reshape(3, 3)
print("K1:", K1)

tmp = []
for i in range(5):
    tmp.append(cam1_node.getFloatEnum('dist_coeffs', i))
dist1 = np.array(tmp)
print("dist1:", dist1)
示例#14
0
# PropertyNode() branch that can't have a value, only childredn
imu.az = -9.80
# this should work
root.sensors.imu[2].az = -9.81

root.pretty_print()

print "alt_m:", root.sensors.gps[5].alt_m

config = getNode('/', create=True)
#file = '/home/curt/Source/AuraUAS/aura-data/config/main-skywalker.xml'
#props_xml.load(file, config)
#props_xml.save("testing.xml", config)
#props_json.save("testing.json", config)
newroot = PropertyNode()
props_json.load("/home/curt/Source/AuraUAS/aura-data/config/main-skywalker.json", newroot)
print "pretty:"
newroot.pretty_print()
quit()

print "sensor children:", sensors.getChildren()
for child in sensors.getChildren():
    node = sensors.getChild(child)
    print node

global_tasks = getNode("/config/mission/global_tasks");
print "global_tasks children:", global_tasks.getChildren()
print global_tasks.task[0].name

a = getNode("/task/home", True)
b = getNode("/task/home", True)
示例#15
0
proj = project.ProjectMgr(args.project)

if args.camera:
    # specified on command line
    camera_file = args.camera
else:
    # auto detect camera from image meta data
    camera_name, make, model, lens_model = proj.detect_camera()
    camera_file = os.path.join("..", "cameras", camera_name + ".json")
print("Camera:", camera_file)

# copy/overlay/update the specified camera config into the existing
# project configuration
cam_node = getNode('/config/camera', True)
tmp_node = PropertyNode()
if props_json.load(camera_file, tmp_node):
    props_json.overlay(cam_node, tmp_node)
    camera.set_mount_params(args.yaw_deg, args.pitch_deg, args.roll_deg)

    # note: dist_coeffs = array[5] = k1, k2, p1, p2, k3

    # ... and save
    proj.save()
else:
    # failed to load camera config file
    if not args.camera:
        print("Camera autodetection failed.")
        print(
            "Consider running the new camera script to create a camera config")
        print("and then try running this script again.")
    else:
示例#16
0
# pathname work
abspath = os.path.abspath(args.video)
basename, ext = os.path.splitext(abspath)
srtname = basename + ".srt"
dirname = basename + "_frames"
print("basename:", basename)
print("srtname:", srtname)
print("dirname:", dirname)

local_config = os.path.join(dirname, "camera.json")
config = PropertyNode()
if args.camera:
    # seed the camera calibration and distortion coefficients from a
    # known camera config
    print('Setting camera config from:', args.camera)
    props_json.load(args.camera, config)
    config.setString('name', args.camera)
    props_json.save(local_config, config)
elif os.path.exists(local_config):
    # load local config file if it exists
    props_json.load(local_config, config)
K_list = []
for i in range(9):
    K_list.append( config.getFloatEnum('K', i) )
K = np.copy(np.array(K_list)).reshape(3,3)
dist = []
for i in range(5):
    dist.append( config.getFloatEnum("dist_coeffs", i) )

# check for required input files
if not os.path.isfile(args.video):
示例#17
0
from props import getNode
import props_json

parser = argparse.ArgumentParser(description='autogen messages code.')
parser.add_argument('input', help='message definition file')
parser.add_argument('--namespace',
                    default="message",
                    help='optional namespace (for C++)')
args = parser.parse_args()

if not os.path.isfile(args.input):
    print("Specified input file not found:", args.input)
    quit()

root = getNode("/", True)
props_json.load(args.input, root)
# root.pretty_print()

if not root.hasChild("messages"):
    print("No message definition found in:", args.input)
    quit()

type_code = {
    "double": 'd',
    "float": 'f',
    "uint64_t": "Q",
    "int64_t": "q",
    "uint32_t": 'L',
    "int32_t": 'l',
    "uint16_t": 'H',
    "int16_t": 'h',
示例#18
0
# PropertyNode() branch that can't have a value, only childredn
imu.az = -9.80
# this should work
root.sensors.imu[2].az = -9.81

root.pretty_print()

print "alt_m:", root.sensors.gps[5].alt_m

config = getNode('/', create=True)
#file = '/home/curt/Source/AuraUAS/aura-data/config/main-skywalker.xml'
#props_xml.load(file, config)
#props_xml.save("testing.xml", config)
#props_json.save("testing.json", config)
newroot = PropertyNode()
props_json.load(
    "/home/curt/Source/AuraUAS/aura-data/config/main-skywalker.json", newroot)
print "pretty:"
newroot.pretty_print()
quit()

print "sensor children:", sensors.getChildren()
for child in sensors.getChildren():
    node = sensors.getChild(child)
    print node

global_tasks = getNode("/config/mission/global_tasks")
print "global_tasks children:", global_tasks.getChildren()
print global_tasks.task[0].name

a = getNode("/task/home", True)
b = getNode("/task/home", True)
parser.add_argument('--yaw-deg', required=True, type=float,
                    help='camera yaw mounting offset from aircraft')
parser.add_argument('--pitch-deg', required=True, type=float,
                    help='camera pitch mounting offset from aircraft')
parser.add_argument('--roll-deg', required=True, type=float,
                    help='camera roll mounting offset from aircraft')

args = parser.parse_args()

proj = ProjectMgr.ProjectMgr(args.project)

# copy/overlay/update the specified camera config into the existing
# project configuration
cam_node = getNode('/config/camera', True)
tmp_node = PropertyNode()
props_json.load(args.camera, tmp_node)
for child in tmp_node.getChildren(expand=False):
    if tmp_node.isEnum(child):
        # print(child, tmp_node.getLen(child))
        for i in range(tmp_node.getLen(child)):
            cam_node.setFloatEnum(child, i, tmp_node.getFloatEnum(child, i))
    else:
        # print(child, type(tmp_node.__dict__[child]))
        child_type = type(tmp_node.__dict__[child])
        if child_type is float:
            cam_node.setFloat(child, tmp_node.getFloat(child))
        elif child_type is int:
            cam_node.setInt(child, tmp_node.getInt(child))
        elif child_type is str:
            cam_node.setString(child, tmp_node.getString(child))
        else:
示例#20
0
    def load(self, cal_file):
        config = PropertyNode()
        try:
            name, ext = os.path.splitext(cal_file)
            if ext == '.json':
                props_json.load(cal_file, config)
                self.valid = True
            elif ext == '.xml':
                props_xml.load(cal_file, config)
                self.valid = True
            else:
                return False
        except:
            print cal_file + ": load error:\n" + str(sys.exc_info()[1])
            return False

        root.pretty_print()
        
        self.min_temp = config.getFloat('min_temp_C')
        self.max_temp = config.getFloat('max_temp_C')
        
        node = config.getChild('p')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.p_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.p_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('q')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.q_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.q_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('r')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.r_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.r_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('ax')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.ax_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.ax_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('ay')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.ay_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.ay_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('az')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.az_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.az_scale = np.array([p1, p2, p3], dtype=np.float64)

        tokens = config.getString('mag_affine').split()
        if len(tokens) == 16:
            r = 0
            c = 0
            for i, x in enumerate(tokens):
                self.mag_affine[r,c] = float(x)
                c += 1
                if c > 3:
                    c = 0
                    r += 1
            self.mag_affine_inv = np.linalg.inv(self.mag_affine)
        else:
            print "mag_affine requires 16 values"
        #print 'mag_affine:\n', self.mag_affine
        #print 'mag_affine_inv:\n', self.mag_affine_inv

        return True
示例#21
0
    def load(self, cal_file):
        config = PropertyNode()
        try:
            name, ext = os.path.splitext(cal_file)
            if ext == '.json':
                props_json.load(cal_file, config)
                self.valid = True
            elif ext == '.xml':
                props_xml.load(cal_file, config)
                self.valid = True
            else:
                return False
        except:
            print(cal_file + ": load error:\n" + str(sys.exc_info()[1]))
            return False

        root.pretty_print()

        self.min_temp = config.getFloat('min_temp_C')
        self.max_temp = config.getFloat('max_temp_C')

        node = config.getChild('p')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.p_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.p_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('q')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.q_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.q_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('r')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.r_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.r_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('ax')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.ax_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.ax_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('ay')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.ay_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.ay_scale = np.array([p1, p2, p3], dtype=np.float64)

        node = config.getChild('az')
        if node:
            p1, p2, p3 = node.getString('bias').split()
            self.az_bias = np.array([p1, p2, p3], dtype=np.float64)
            p1, p2, p3 = node.getString('scale').split()
            self.az_scale = np.array([p1, p2, p3], dtype=np.float64)

        tokens = config.getString('mag_affine').split()
        if len(tokens) == 16:
            r = 0
            c = 0
            for i, x in enumerate(tokens):
                self.mag_affine[r, c] = float(x)
                c += 1
                if c > 3:
                    c = 0
                    r += 1
            self.mag_affine_inv = np.linalg.inv(self.mag_affine)
        else:
            print("mag_affine requires 16 values")
        #print 'mag_affine:\n', self.mag_affine
        #print 'mag_affine_inv:\n', self.mag_affine_inv

        return True
示例#22
0
# pathname work
abspath = os.path.abspath(args.movie)
filename, ext = os.path.splitext(abspath)
movie_log = filename + ".csv"
movie_config = filename + ".json"
# combinations that seem to work on linux
# ext = avi, fourcc = MJPG
# ext = avi, fourcc = XVID
# ext = mov, fourcc = MP4V

tmp_movie = filename + "_tmp.mov"
output_movie = filename + "_hud.mov"

# load config file if it exists
config = PropertyNode()
props_json.load(movie_config, config)
cam_yaw = config.getFloat('cam_yaw_deg')
cam_pitch = config.getFloat('cam_pitch_deg')
cam_roll = config.getFloat('cam_roll_deg')

# load movie log
movie = []
with open(movie_log, 'rb') as f:
    for line in f:
        movie.append( re.split('[,\s]+', line.rstrip()) )

flight_imu = []
flight_gps = []
flight_filter = []
flight_air = []
flight_pilot = []