2 module for loading/saving waypoints 4 from __future__
import print_function
5 from builtins
import range
6 from builtins
import object
12 from google.protobuf
import text_format
20 '''MAVLink WP error class''' 22 Exception.__init__(self, msg)
27 '''MAVLink waypoint loader''' 28 def __init__(self, target_system=0, target_component=0):
34 mavutil.mavlink.MAV_CMD_NAV_FENCE_POLYGON_VERTEX_EXCLUSION : (255,0,0),
35 mavutil.mavlink.MAV_CMD_NAV_FENCE_POLYGON_VERTEX_INCLUSION : (0,255,0)
39 '''return number of waypoints''' 43 '''return a waypoint''' 52 '''return true if waypoint is a loiter waypoint''' 53 loiter_cmds = [mavutil.mavlink.MAV_CMD_NAV_LOITER_UNLIM,
54 mavutil.mavlink.MAV_CMD_NAV_LOITER_TURNS,
55 mavutil.mavlink.MAV_CMD_NAV_LOITER_TIME,
56 mavutil.mavlink.MAV_CMD_NAV_LOITER_TO_ALT]
58 if (self.
wpoints[i].command
in loiter_cmds):
63 def add(self, w, comment=''):
69 self.wpoints.append(w)
72 def insert(self, idx, w, comment=''):
73 '''insert a waypoint''' 74 if idx >= self.
count():
83 self.wpoints.insert(idx, w)
88 '''reindex waypoints''' 89 for i
in range(self.
count()):
95 '''add a point via latitude/longitude/altitude''' 97 frame = mavutil.mavlink.MAV_FRAME_GLOBAL_TERRAIN_ALT
99 frame = mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT
100 p = mavutil.mavlink.MAVLink_mission_item_message(self.
target_system,
104 mavutil.mavlink.MAV_CMD_NAV_WAYPOINT,
112 if w.seq == self.
count():
114 if self.
count() <= idx:
115 raise MAVWPError(
'adding waypoint at idx=%u past end of list (count=%u)' % (idx, self.
count()))
120 '''remove a waypoint''' 121 self.wpoints.remove(w)
126 '''clear waypoint list''' 131 '''read a version 100 waypoint''' 133 2 : mavutil.mavlink.MAV_CMD_NAV_TAKEOFF,
134 3 : mavutil.mavlink.MAV_CMD_NAV_RETURN_TO_LAUNCH,
135 4 : mavutil.mavlink.MAV_CMD_NAV_LAND,
136 24: mavutil.mavlink.MAV_CMD_NAV_TAKEOFF,
137 26: mavutil.mavlink.MAV_CMD_NAV_LAND,
138 25: mavutil.mavlink.MAV_CMD_NAV_WAYPOINT ,
139 27: mavutil.mavlink.MAV_CMD_NAV_LOITER_UNLIM
143 if line.startswith(
'#'):
144 comment = line[1:].lstrip()
151 raise MAVWPError(
"invalid waypoint line with %u values" % len(a))
152 if mavutil.mavlink10():
153 fn = mavutil.mavlink.MAVLink_mission_item_message
155 fn = mavutil.mavlink.MAVLink_waypoint_message
170 if not w.command
in cmdmap:
171 raise MAVWPError(
"Unknown v100 waypoint action %u" % w.command)
173 w.command = cmdmap[w.command]
178 '''read a version 110 waypoint''' 181 if line.startswith(
'#'):
182 comment = line[1:].lstrip()
189 raise MAVWPError(
"invalid waypoint line with %u values" % len(a))
190 if mavutil.mavlink10():
191 fn = mavutil.mavlink.MAVLink_mission_item_message
193 fn = mavutil.mavlink.MAVLink_waypoint_message
208 if w.command == 0
and w.seq == 0
and self.
count() == 0:
210 w.command = mavutil.mavlink.MAV_CMD_NAV_WAYPOINT
215 if not HAVE_PROTOBUF:
217 'Cannot read mission file in protobuf format without protobuf ' 218 'library. Try "easy_install protobuf".')
221 mission = mission_pb2.Mission()
222 text_format.Merge(file.read(), mission)
223 defaults = mission_pb2.Waypoint()
225 defaults.current =
False 226 defaults.autocontinue =
True 227 defaults.param1 = 0.0
228 defaults.param2 = 0.0
229 defaults.param3 = 0.0
230 defaults.param4 = 0.0
236 defaults.MergeFrom(mission.defaults)
237 for seq, waypoint
in enumerate(mission.waypoint):
244 if explicit_seq
and not warned_seq:
246 'Waypoint file %s: mixes explicit and implicit ' 247 'sequence numbers' % (file,))
251 current = defaults.current
254 w = mavutil.mavlink.MAVLink_mission_item_message(
259 waypoint.current
or current,
260 waypoint.autocontinue
or defaults.autocontinue,
261 waypoint.param1
or defaults.param1,
262 waypoint.param2
or defaults.param2,
263 waypoint.param3
or defaults.param3,
264 waypoint.param4
or defaults.param4,
265 waypoint.x
or defaults.x,
266 waypoint.y
or defaults.y,
267 waypoint.z
or defaults.z)
271 '''load waypoints from a file. 272 returns number of waypoints loaded''' 273 f = open(filename, mode=
'r') 274 version_line = f.readline().strip() 275 if version_line ==
"QGC WPL 100":
277 elif version_line ==
"QGC WPL 110":
279 elif version_line ==
"QGC WPL PB 110":
283 raise MAVWPError(
"Unsupported waypoint format '%s'" % version_line)
292 mission = mission_pb2.Mission()
294 waypoint = mission.waypoint.add()
295 waypoint.command = w.command
296 waypoint.frame = w.frame
298 waypoint.current = w.current
299 waypoint.autocontinue = w.autocontinue
300 waypoint.param1 = w.param1
301 waypoint.param2 = w.param2
302 waypoint.param3 = w.param3
303 waypoint.param4 = w.param4
307 with open(filename,
'w')
as f:
308 f.write(
'QGC WPL PB 110\n')
309 f.write(text_format.MessageToString(mission))
312 '''save waypoints to a file''' 313 f = open(filename, mode=
'w')
314 f.write(
"QGC WPL 110\n")
316 if getattr(w,
'comment',
None):
317 f.write(
"# %s\n" % w.comment)
318 f.write(
"%u\t%u\t%u\t%u\t%f\t%f\t%f\t%f\t%f\t%f\t%f\t%u\n" % (
319 w.seq, w.current, w.frame, w.command,
320 w.param1, w.param2, w.param3, w.param4,
321 w.x, w.y, w.z, w.autocontinue))
325 '''see if cmd is a MAV_CMD with a latitide/longitude. 326 We check if it has Latitude and Longitude params in the right indexes''' 327 mav_cmd = mavutil.mavlink.enums[
'MAV_CMD']
328 if not cmd
in mav_cmd:
330 if not mav_cmd[cmd].param.get(5,
'').startswith(
'Latitude'):
332 if not mav_cmd[cmd].param.get(6,
'').startswith(
'Longitude'):
338 '''return a list waypoint indexes in view order''' 345 while idx < self.
count():
354 while idx < self.
count():
357 if w.x != 0
or w.y != 0:
361 if w.command == mavutil.mavlink.MAV_CMD_DO_JUMP:
364 if w.x != 0
or w.y != 0:
368 if w.command == mavutil.mavlink.MAV_CMD_NAV_FENCE_POLYGON_VERTEX_EXCLUSION:
369 if exclusion_start == -1:
370 exclusion_count =
int(w.param1)
371 exclusion_start = idx
372 if idx == exclusion_start + exclusion_count - 1:
374 ret.append(exclusion_start)
376 if w.command == mavutil.mavlink.MAV_CMD_NAV_FENCE_POLYGON_VERTEX_INCLUSION:
377 if inclusion_start == -1:
378 inclusion_count =
int(w.param1)
379 inclusion_start = idx
380 if idx == inclusion_start + inclusion_count - 1:
382 ret.append(inclusion_start)
386 exc_zones = [mavutil.mavlink.MAV_CMD_NAV_FENCE_POLYGON_VERTEX_EXCLUSION,
387 mavutil.mavlink.MAV_CMD_NAV_FENCE_POLYGON_VERTEX_INCLUSION]
389 if w2
is not None and w.command
not in exc_zones
and w2.command
in exc_zones:
396 '''return a polygon for the waypoints''' 404 points.append((w.x, w.y))
408 '''return a list of polygons for the waypoints''' 411 while len(done) != self.
count():
418 '''return a list of polygon indexes lists for the waypoints''' 421 while len(done) != self.
count():
428 '''MAVLink rally point error class''' 430 Exception.__init__(self, msg)
434 '''MAVLink Rally points and Rally Land ponts loader''' 435 def __init__(self, target_system=0, target_component=0):
442 '''return number of rally points''' 446 '''return rally point i''' 450 '''reset counters and indexes''' 457 '''add rallypoint to end of list''' 459 print(
"Can't have more than 10 rally points, not adding.")
462 self.rally_points.append(p)
466 '''add a point via latitude/longitude''' 468 self.
rally_count(), 0, lat, lon, alt, break_alt, land_dir, flags)
472 '''clear all point lists (rally and rally_land)''' 477 '''remove a rally point''' 479 print(
"Invalid rally point number %u" % i)
480 self.rally_points.pop(i-1)
483 def move(self, i, lat, lng, change_time=True):
484 '''move a rally point''' 486 print(
"Invalid rally point number %u" % i)
492 def set_alt(self, i, alt, break_alt=None, change_time=True):
493 '''set rally point altitude(s)''' 495 print(
"Inavlid rally point number %u" % i)
498 if break_alt
is not None:
504 '''load rally and rally_land points from a file. 505 returns number of points loaded''' 506 f = open(filename, mode=
'r') 509 if line.startswith(
'#'):
518 if (a[0].lower() ==
"rally"):
525 '''save fence points to a file''' 526 f = open(filename, mode=
'w')
528 f.write(
"RALLY %f\t%f\t%f\t%f\t%f\t%d\n" % (p.lat * 1e-7, p.lng * 1e-7, p.alt,
529 p.break_alt, p.land_dir, p.flags))
533 '''MAVLink fence error class''' 535 Exception.__init__(self, msg)
539 '''MAVLink geo-fence loader''' 540 def __init__(self, target_system=0, target_component=0):
547 '''return number of points''' 556 self.points.append(p)
560 '''reindex waypoints''' 561 for i
in range(self.
count()):
564 w.count = self.
count()
570 '''add a point via latitude/longitude''' 572 self.
count(), 0, lat, lon)
576 '''clear point list''' 581 '''load points from a file. 582 returns number of points loaded''' 583 f = open(filename, mode=
'r') 586 if line.startswith(
'#'):
599 '''save fence points to a file''' 600 f = open(filename, mode=
'w')
602 f.write(
"%f\t%f\n" % (p.lat, p.lng))
605 def move(self, i, lat, lng, change_time=True):
606 '''move a fence point''' 607 if i < 0
or i >= self.
count():
608 print(
"Invalid fence point number %u" % i)
615 if i == self.
count() - 1:
622 '''remove a fence point''' 623 if i < 0
or i >= self.
count():
624 print(
"Invalid fence point number %u" % i)
630 if i == self.
count():
637 '''return a polygon for the fence''' 639 for fp
in self.
points[1:]:
640 points.append((fp.lat, fp.lng))
def move(self, i, lat, lng, change_time=True)
def add_latlon(self, lat, lon)
def move(self, i, lat, lng, change_time=True)
def polygon(self, done=None)
def _read_waypoints_pb_110(self, file)
def __init__(self, target_system=0, target_component=0)
def remove(self, i, change_time=True)
def add(self, w, comment='')
def __init__(self, target_system=0, target_component=0)
def is_location_command(self, cmd)
def save_as_pb(self, filename)
def wp_is_loiter(self, i)
def insert(self, idx, w, comment='')
def add_latlonalt(self, lat, lon, altitude, terrain_alt=False)
def _read_waypoints_v100(self, file)
def create_and_append_rally_point(self, lat, lon, alt, break_alt, land_dir, flags)
def append_rally_point(self, p)
def view_indexes(self, done=None)
def set_alt(self, i, alt, break_alt=None, change_time=True)
def _read_waypoints_v110(self, file)
def __init__(self, target_system=0, target_component=0)