4 simple kml export for logfiles 5 Thomas Gubler <thomasgubler@gmail.com> 7 from __future__
import print_function
9 from builtins
import range
11 from argparse
import ArgumentParser
14 from pymavlink
import mavutil
19 mainstate_field =
'STAT.MainState' 20 position_field_types = [
21 [
'Lon',
'Lat',
'Alt'],
25 colors = [simplekml.Color.red, simplekml.Color.green, simplekml.Color.blue,
26 simplekml.Color.violet, simplekml.Color.yellow, simplekml.Color.orange,
27 simplekml.Color.burlywood, simplekml.Color.azure, simplekml.Color.lightblue,
28 simplekml.Color.lawngreen, simplekml.Color.indianred, simplekml.Color.hotpink]
35 '''add a point to the kml file''' 39 position_data[2] +=
float(args.aoff)
40 kml_linestring.coords.addcoordinates([position_data])
44 '''saves the kml file''' 47 print(
"KML written to %s" % filename)
50 def add_data(t, msg, msg_types, vars, fields, field_types, position_field_type):
53 mtype = msg.get_type()
54 if mtype
not in msg_types:
57 for i
in range(0, len(fields)):
58 if mtype
not in field_types[i]:
61 v = mavutil.evaluate_expression(f, vars)
66 if f == mainstate_field:
70 if (v != add_data.mainstate_current
and 71 add_data.mainstate_current >= 0):
72 add_data.new_linestring =
True 73 add_data.mainstate_current = v
78 add_data.position_data[i] = v
81 gps_measurement_ready =
True 82 for v
in add_data.position_data:
84 gps_measurement_ready =
False 85 if not gps_measurement_ready:
92 if add_data.new_linestring:
93 if add_data.current_kml_linestring
is not None:
94 kml_linestrings.append(add_data.current_kml_linestring)
96 name =
"".join([args.source,
":",
str(add_data.mainstate_current)])
97 add_data.current_kml_linestring = \
98 kml.newlinestring(name=name, altitudemode=
'absolute')
102 add_data.current_kml_linestring.extrude = 1
103 add_data.current_kml_linestring.style.linestyle.color = \
104 colors[max([add_data.mainstate_current, 0])]
106 add_data.new_linestring =
False 109 add_data.current_kml_linestring)
110 add_data.last_time = msg._timestamp
113 if (msg._timestamp - add_data.last_time) > 0.1:
115 add_data.current_kml_linestring)
116 add_data.last_time = msg._timestamp
119 add_data.position_data = [
None for n
in position_field_type]
123 '''process one file''' 124 print(
"Processing %s" % filename)
125 mlog = mavutil.mavlink_connection(filename, notimestamps=args.notimestamps)
130 fields = [args.source +
"." + s
for s
in position_field_type]
131 fields.append(mainstate_field)
135 re_caps = re.compile(
'[A-Z_][A-Z0-9_]+')
138 caps = set(re.findall(re_caps, f))
139 msg_types = msg_types.union(caps)
140 field_types.append(caps)
142 add_data.new_linestring =
True 143 add_data.mainstate_current = -1
144 add_data.current_kml_linestring =
None 145 add_data.position_data = [
None for n
in position_field_type]
146 add_data.last_time = 0
149 msg = mlog.recv_match(args.condition)
152 tdays = (msg._timestamp - time.timezone) / (24 * 60 * 60)
154 add_data(tdays, msg, msg_types, mlog.messages, fields, field_types, position_field_type)
158 '''attempt to detect whether APM or PX4 attributes names are in use''' 159 position_field_type_default = position_field_types[0]
161 msg = mlog.recv_match(source)
164 position_field_selection = [spelling
for spelling
in position_field_types
if hasattr(msg, spelling[0])]
166 return position_field_selection[0]
if position_field_selection
else position_field_type_default
169 if __name__ ==
'__main__':
170 parser = ArgumentParser(description=__doc__)
171 parser.add_argument(
"--no-timestamps", dest=
"notimestamps",
172 action=
'store_true', help=
"Log doesn't have timestamps")
173 parser.add_argument(
"--condition", default=
None,
174 help=
"select packets by a condition [default: %(default)s]")
175 parser.add_argument(
"--aoff", default=0.,
176 help=
"Altitude offset for paths that go through the" 177 "ground in google earth [default: %(default)s]")
178 parser.add_argument(
"-o",
"--output", dest=
"filename_out", default=
"mav.kml",
179 help=
"Output filename [default: %(default)s] ")
180 parser.add_argument(
"-s",
"--source", default=
"GPOS",
181 help=
"Select position data source" 182 "(GPOS or GPS) [default: %(default)s]")
183 parser.add_argument(
"-e",
"--extrude", default=
False,
185 help=
"Extrude paths to ground [default: %(default)s]")
186 parser.add_argument(
"logs", metavar=
"LOG", nargs=
"+")
188 args = parser.parse_args()
192 if os.path.exists(f):
195 if len(filenames) == 0:
196 print(
"No files to process")
199 for fi
in range(0, len(filenames)):