def mavlink_packet(m): '''handle an incoming mavlink packet''' state = mpstate.antenna_state if m.get_type() == 'GPS_RAW' and state.gcs_location is not None: (gcs_lat, gcs_lon) = state.gcs_location bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat, m.lon) mpstate.console.set_status('Antenna', 'Antenna %.0f' % bearing, row=0) if m.get_type() == 'GPS_RAW_INT' and state.gcs_location is not None: (gcs_lat, gcs_lon) = state.gcs_location bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat/1.0e7, m.lon/1.0e7) mpstate.console.set_status('Antenna', 'Antenna %.0f' % bearing, row=0)
def mavlink_packet(m): """handle an incoming mavlink packet""" state = mpstate.antenna_state if m.get_type() == "GPS_RAW" and state.gcs_location is not None: (gcs_lat, gcs_lon) = state.gcs_location bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat, m.lon) mpstate.console.set_status("Antenna", "Antenna %.0f" % bearing, row=0) if m.get_type() == "GPS_RAW_INT" and state.gcs_location is not None: (gcs_lat, gcs_lon) = state.gcs_location bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat / 1.0e7, m.lon / 1.0e7) mpstate.console.set_status("Antenna", "Antenna %.0f" % bearing, row=0)
def projectBearing(self, bearing, startPos, searchArea): '''Projects bearing from startPos until it reaches the edge(s) of searchArea (list of lat/long tuples. Returns the First/Last position(s)''' coPoints = [] #for each line in the search are border, get any overlaps with startPos on bearing(+-180) for point in searchArea: dist = cuav_util.gps_distance(point[0], point[1], searchArea[searchArea.index(point)-1][0], searchArea[searchArea.index(point)-1][1]) theta2 = cuav_util.gps_bearing(point[0], point[1], searchArea[searchArea.index(point)-1][0], searchArea[searchArea.index(point)-1][1]) posn = self.Intersection(startPos, bearing, point, theta2) if posn != 0 and cuav_util.gps_distance(posn[0], posn[1], point[0], point[1]) < dist: coPoints.append(posn) posn = self.Intersection(startPos, (bearing + 180) % 360, point, theta2) if posn != 0 and cuav_util.gps_distance(posn[0], posn[1], point[0], point[1]) < dist: coPoints.append(posn) #if there's more than two points in coPoints, return the furthest away points if len(coPoints) < 2: #print str(len(coPoints)) + " point i-sect" return 0 elif len(coPoints) == 2: return coPoints else: dist = 0 for point in coPoints: for pt in coPoints: if cuav_util.gps_distance(pt[0], pt[1], point[0], point[1]) > dist: dist = cuav_util.gps_distance(pt[0], pt[1], point[0], point[1]) newcoPoints = [point, pt] return newcoPoints
def mouse_event_view(self, event): '''called on mouse events in View window''' x = event.X y = event.Y if self.current_view >= len(self.images): return image = self.images[self.current_view] latlon = cuav_util.gps_position_from_xy(x, y, image.pos, C=self.c_params, shape=image.shape, altitude=image.pos.altitude) if self.last_view_latlon is None or latlon is None: dist = '' else: distance = cuav_util.gps_distance(self.last_view_latlon[0], self.last_view_latlon[1], latlon[0], latlon[1]) bearing = cuav_util.gps_bearing(self.last_view_latlon[0], self.last_view_latlon[1], latlon[0], latlon[1]) dist = "dist %.1f bearing %.1f alt=%.1f shape=%s" % ( distance, bearing, image.pos.altitude, image.shape) print("-> %s %s %s" % (latlon, image.filename, dist)) self.last_view_latlon = latlon
def altitudeCompensation(self, heightAGL, numMaxPoints=100, threshold=5): '''Creates height points (ASL) for each point in searchArea, entry and exit points such that the plane stays a constant altitude above the ground, constrained by a max number of waypoints''' maxDeltaAlt = 0 maxDeltaAltPoints = [] maxDeltapercentAlong = 0 EleModel = mp_elevation.ElevationModel() #make sure the SRTM tiles are downloaded EleModel.GetElevation(self.SearchPattern[0][0], self.SearchPattern[0][1]) #get the ASL height of the airfield home, entry and exit points and initial search pattern # and add the heightAGL to them self.airportHeight = EleModel.GetElevation(self.airfieldHome[0], self.airfieldHome[1]) self.airfieldHome = (self.airfieldHome[0], self.airfieldHome[1], heightAGL+EleModel.GetElevation(self.airfieldHome[0], self.airfieldHome[1])) for point in self.entryPoints: self.entryPoints[self.entryPoints.index(point)] = (point[0], point[1], heightAGL+EleModel.GetElevation(point[0], point[1])) for point in self.exitPoints: self.exitPoints[self.exitPoints.index(point)] = (point[0], point[1], heightAGL+EleModel.GetElevation(point[0], point[1])) for point in self.SearchPattern: self.SearchPattern[self.SearchPattern.index(point)] = (point[0], point[1], heightAGL+EleModel.GetElevation(point[0], point[1])) #keep looping through the search area waypoints and add new waypoints where needed #to maintain const height above terrain print "---Starting terrain tracking optimisation---" while True: maxDeltaAlt = 0 maxDeltaAltPoints = [] maxDeltaPointIndex = 0 for point in self.SearchPattern: if point != self.SearchPattern[-1]: dist = cuav_util.gps_distance(point[0], point[1], self.SearchPattern[self.SearchPattern.index(point)+1][0], self.SearchPattern[self.SearchPattern.index(point)+1][1]) theta = cuav_util.gps_bearing(point[0], point[1], self.SearchPattern[self.SearchPattern.index(point)+1][0], self.SearchPattern[self.SearchPattern.index(point)+1][1]) AltDiff = float(self.SearchPattern[self.SearchPattern.index(point)+1][2] - point[2]) if numpy.around(theta) == numpy.around(self.searchBearing) or numpy.around(theta) == numpy.around((self.searchBearing+180) % 360): #increment 10% along waypoint-to-waypoint and get max height difference for i in range(1, 9): partPoint = cuav_util.gps_newpos(point[0], point[1], theta, (i*dist/10)) partAlt = EleModel.GetElevation(partPoint[0], partPoint[1]) + heightAGL #print "Part = " + str(partAlt) + ", Orig = " + str(point[2]) if numpy.abs(point[2] + ((AltDiff*i)/10) - partAlt) > maxDeltaAlt: maxDeltaAlt = numpy.abs(point[2] + ((AltDiff*i)/10) - partAlt) maxDeltaAltPoint = (partPoint[0], partPoint[1], partAlt) maxDeltaPointIndex = self.SearchPattern.index(point)+1 #print "New max alt diff: " + str(maxDeltaAlt) + ", " + str(partAlt) #now put a extra waypoint in between the two maxDeltaAltPoints if maxDeltaAltPoint is not None: self.SearchPattern.insert(maxDeltaPointIndex, maxDeltaAltPoint) #print "There are " + str(len(self.SearchPattern)) + " points in the search pattern. Max Alt error is " + str(maxDeltaAlt) if len(self.SearchPattern) >= numMaxPoints or threshold > maxDeltaAlt: break print "---Done terrain tracking optimisation---"
def mavlink_packet(m): '''handle an incoming mavlink packet''' state = mpstate.antenna_state if state.gcs_location is None and mpstate.status.wploader.count() > 0: home = mpstate.status.wploader.wp(0) mpstate.antenna_state.gcs_location = (home.x, home.y) print("Antenna home set") if state.gcs_location is None: return if m.get_type() == 'GPS_RAW' and state.gcs_location is not None: (gcs_lat, gcs_lon) = state.gcs_location bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat, m.lon) elif m.get_type() == 'GPS_RAW_INT' and state.gcs_location is not None: (gcs_lat, gcs_lon) = state.gcs_location bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat/1.0e7, m.lon/1.0e7) else: return mpstate.console.set_status('Antenna', 'Antenna %.0f' % bearing, row=0) if abs(bearing - state.last_bearing) > 5 and (time.time() - state.last_announce) > 15: state.last_bearing = bearing state.last_announce = time.time() mpstate.functions.say("Antenna %u" % int(bearing+0.5))
def mavlink_packet(m): '''handle an incoming mavlink packet''' state = mpstate.antenna_state if state.gcs_location is None and mpstate.status.wploader.count() > 0: home = mpstate.status.wploader.wp(0) mpstate.antenna_state.gcs_location = (home.x, home.y) print("Antenna home set") if state.gcs_location is None: return if m.get_type() == 'GPS_RAW' and state.gcs_location is not None: (gcs_lat, gcs_lon) = state.gcs_location bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat, m.lon) elif m.get_type() == 'GPS_RAW_INT' and state.gcs_location is not None: (gcs_lat, gcs_lon) = state.gcs_location bearing = cuav_util.gps_bearing(gcs_lat, gcs_lon, m.lat / 1.0e7, m.lon / 1.0e7) else: return mpstate.console.set_status('Antenna', 'Antenna %.0f' % bearing, row=0) if abs(bearing - state.last_bearing) > 5 and (time.time() - state.last_announce) > 15: state.last_bearing = bearing state.last_announce = time.time() mpstate.functions.say("Antenna %u" % int(bearing + 0.5))
def mouse_event_view(self, event): '''called on mouse events in View window''' x = event.X y = event.Y if self.current_view >= len(self.images): return image = self.images[self.current_view] latlon = cuav_util.gps_position_from_xy(x, y, image.pos, C=self.c_params, shape=image.shape) if self.last_view_latlon is None or latlon is None: dist = '' else: distance = cuav_util.gps_distance(self.last_view_latlon[0], self.last_view_latlon[1], latlon[0], latlon[1]) bearing = cuav_util.gps_bearing(self.last_view_latlon[0], self.last_view_latlon[1], latlon[0], latlon[1]) dist = "dist %.1f bearing %.1f alt=%.1f shape=%s" % (distance, bearing, image.pos.altitude, image.shape) print("-> %s %s %s" % (latlon, image.filename, dist)) self.last_view_latlon = latlon
def CreateSearchPattern(self, width=50.0, overlap=10.0, offset=10, wobble=10, alt=100): '''Generate the waypoints for the search pattern, using alternating strips width is the width (m) of each strip, overlap is the % overlap between strips, alt is the altitude (relative to ground) of the points''' self.SearchPattern = [] #find the nearest point to Airfield Home - use this as a starting point (if entry lanes are not used) if len(self.entryPoints) == 0: nearestdist = cuav_util.gps_distance(self.airfieldHome[0], self.airfieldHome[1], self.searchArea[0][0], self.searchArea[0][1]) nearest = self.searchArea[0] for point in self.searchArea: newdist = cuav_util.gps_distance(self.airfieldHome[0], self.airfieldHome[1], point[0], point[1]) if newdist < nearestdist: nearest = point nearestdist = newdist else: nearestdist = cuav_util.gps_distance(self.entryPoints[0][0], self.entryPoints[0][1], self.searchArea[0][0], self.searchArea[0][1]) nearest = self.searchArea[0] for point in self.searchArea: newdist = cuav_util.gps_distance(self.entryPoints[0][0], self.entryPoints[0][1], point[0], point[1]) #print "dist = " + str(newdist) if newdist < nearestdist: nearest = point nearestdist = newdist #print "Start = " + str(nearest) + ", dist = " + str(nearestdist) #the search pattern will run between the longest side from nearest bearing1 = cuav_util.gps_bearing(nearest[0], nearest[1], self.searchArea[self.searchArea.index(nearest)-1][0], self.searchArea[self.searchArea.index(nearest)-1][1]) bearing2 = cuav_util.gps_bearing(nearest[0], nearest[1], self.searchArea[self.searchArea.index(nearest)+1][0], self.searchArea[self.searchArea.index(nearest)+1][1]) dist1 = cuav_util.gps_distance(nearest[0], nearest[1], self.searchArea[self.searchArea.index(nearest)-1][0], self.searchArea[self.searchArea.index(nearest)-1][1]) dist2 = cuav_util.gps_distance(nearest[0], nearest[1], self.searchArea[self.searchArea.index(nearest)+1][0], self.searchArea[self.searchArea.index(nearest)+1][1]) if dist1 > dist2: self.searchBearing = bearing1 else: self.searchBearing = bearing2 #the search pattern will then run parallel between the two furthest points in the list #searchLine = (0, 0) #for point in self.searchArea: # newdist = cuav_util.gps_distance(point[0], point[1], self.searchArea[self.searchArea.index(point)-1][0], self.searchArea[self.searchArea.index(point)-1][1]) # if newdist > searchLine[0]: # searchLine = (newdist, cuav_util.gps_bearing(point[0], point[1], self.searchArea[self.searchArea.index(point)-1][0], self.searchArea[self.searchArea.index(point)-1][1])) #self.searchBearing = searchLine[1] #need to find the 90 degree bearing to searchBearing that is inside the search area. This #will be the bearing we increment the search rows by #need to get the right signs for the bearings, depending which quadrant the search area is in wrt nearest if not cuav_util.polygon_outside(cuav_util.gps_newpos(nearest[0], nearest[1], (self.searchBearing + 45) % 360, 10), self.searchArea): self.crossBearing = (self.searchBearing + 90) % 360 elif not cuav_util.polygon_outside(cuav_util.gps_newpos(nearest[0], nearest[1], (self.searchBearing + 135) % 360, 10), self.searchArea): self.crossBearing = (self.searchBearing + 90) % 360 self.searchBearing = (self.searchBearing + 180) % 360 elif not cuav_util.polygon_outside(cuav_util.gps_newpos(nearest[0], nearest[1], (self.searchBearing - 45) % 360, 10), self.searchArea): self.crossBearing = (self.searchBearing - 90) % 360 else: self.crossBearing = (self.searchBearing - 90) % 360 self.searchBearing = (self.searchBearing - 180) % 360 print "Search bearing is " + str(self.searchBearing) + "/" + str((self.searchBearing + 180) % 360) print "Cross bearing is: " + str(self.crossBearing) #the distance between runs is this: self.deltaRowDist = width - width*(float(overlap)/100) if self.deltaRowDist <= 0: print "Error, overlap % is too high" return print "Delta row = " + str(self.deltaRowDist) #expand the search area to 1/2 deltaRowDist to ensure full coverage #we are starting at the "nearest" and mowing the lawn parallel to "self.searchBearing" #first waypoint is right near the Search Area boundary (without being on it) (10% of deltaRowDist #on an opposite bearing (so behind the search area) nextWaypoint = cuav_util.gps_newpos(nearest[0], nearest[1], self.crossBearing, self.deltaRowDist/10) print "First = " + str(nextWaypoint) #self.SearchPattern.append(firstWaypoint) #mow the lawn, every 2nd row: while True: pts = self.projectBearing(self.searchBearing, nextWaypoint, self.searchArea) #print "Projecting " + str(nextWaypoint) + " along " + str(self.searchBearing) #check if we're outside the search area if pts == 0: break (nextW, nextnextW) = (pts[0], pts[1]) if cuav_util.gps_distance(nextWaypoint[0], nextWaypoint[1], nextW[0], nextW[1]) < cuav_util.gps_distance(nextWaypoint[0], nextWaypoint[1], nextnextW[0], nextnextW[1]): self.SearchPattern.append(cuav_util.gps_newpos(nextW[0], nextW[1], (self.searchBearing + 180) % 360, (offset+wobble))) self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt) self.SearchPattern.append(cuav_util.gps_newpos(nextnextW[0], nextnextW[1], self.searchBearing, (offset+wobble))) self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt) #now turn 90degrees from bearing and width distance nextWaypoint = cuav_util.gps_newpos(nextnextW[0], nextnextW[1], self.crossBearing, self.deltaRowDist*2) self.searchBearing = (self.searchBearing + 180) % 360 else: self.SearchPattern.append(cuav_util.gps_newpos(nextnextW[0], nextnextW[1], (self.searchBearing + 180) % 360, offset+wobble)) self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt) self.SearchPattern.append(cuav_util.gps_newpos(nextW[0], nextW[1], self.searchBearing, (offset+wobble))) self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt) #now turn 90degrees from bearing and width distance nextWaypoint = cuav_util.gps_newpos(nextW[0], nextW[1], self.crossBearing, self.deltaRowDist*2) self.searchBearing = (self.searchBearing + 180) % 360 print "Next = " + str(nextWaypoint) #go back and do the rows we missed. There still might be one more row to do in # the crossbearing direction, so check for that first nextWaypoint = cuav_util.gps_newpos(nextWaypoint[0], nextWaypoint[1], self.crossBearing, -self.deltaRowDist) pts = self.projectBearing(self.searchBearing, nextWaypoint, self.searchArea) if pts == 0: nextWaypoint = cuav_util.gps_newpos(nextWaypoint[0], nextWaypoint[1], self.crossBearing, -2*self.deltaRowDist) self.crossBearing = (self.crossBearing + 180) % 360 else: self.crossBearing = (self.crossBearing + 180) % 360 while True: pts = self.projectBearing(self.searchBearing, nextWaypoint, self.searchArea) #print "Projecting " + str(nextWaypoint) + " along " + str(self.searchBearing) #check if we're outside the search area if pts == 0: break (nextW, nextnextW) = (pts[0], pts[1]) if cuav_util.gps_distance(nextWaypoint[0], nextWaypoint[1], nextW[0], nextW[1]) < cuav_util.gps_distance(nextWaypoint[0], nextWaypoint[1], nextnextW[0], nextnextW[1]): self.SearchPattern.append(cuav_util.gps_newpos(nextW[0], nextW[1], (self.searchBearing + 180) % 360, offset)) self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt) self.SearchPattern.append(cuav_util.gps_newpos(nextnextW[0], nextnextW[1], self.searchBearing, offset)) self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt) #now turn 90degrees from bearing and width distance nextWaypoint = cuav_util.gps_newpos(nextnextW[0], nextnextW[1], self.crossBearing, self.deltaRowDist*2) self.searchBearing = (self.searchBearing + 180) % 360 else: self.SearchPattern.append(cuav_util.gps_newpos(nextnextW[0], nextnextW[1], (self.searchBearing + 180) % 360, offset)) self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt) self.SearchPattern.append(cuav_util.gps_newpos(nextW[0], nextW[1], self.searchBearing, offset)) self.SearchPattern[-1] =(self.SearchPattern[-1][0], self.SearchPattern[-1][1], alt) #now turn 90degrees from bearing and width distance nextWaypoint = cuav_util.gps_newpos(nextW[0], nextW[1], self.crossBearing, self.deltaRowDist*2) self.searchBearing = (self.searchBearing + 180) % 360 print "Next(alt) = " + str(nextWaypoint) #add in the altitude points (relative to airfield home) for point in self.SearchPattern: self.SearchPattern[self.SearchPattern.index(point)] = (point[0], point[1], alt)