Image of the current output. I want this to display the polylines as previous data points of where each object has been in past frames.I'm using the library's gmplot and geographiclib.Geodesic to attempt to track objects in a LIDAR payload. The goal is to get an output every iteration of the payload to get a google map graph that shows each object in the payload with the most recent position labeled with the object's ID as well as having a marker showing where it is in latitude and longitude coordinates. In another file, I have an algorithm that uses the x and y coordinates within the LIDAR to determine the correct latitude and longitude of the objects. Getting the marker correct is working.
We have all of the data inside of a JSON file where we have the latitude, longitude, and object ID's listed and indexed by frame. A nested dictionary is being used to hold this data, so that makes the functions in the code easier to read. All of the functions are put together in the function at the bottom of the code called live_graph_coordinates.
The issue comes in when I try to get the polylines to be tracked behind all previous data points of the objects. I use a dictionary to track all previous points of latitude and longitude for their respective ID value, but I'm having trouble getting these to display correctly as well as split into multiple polylines. Does anyone have experience in this library or know anyone who could possibly give a solution to this problem?
# Imports all modules needed for the code
import json
import gmplot
from geographiclib.geodesic import Geodesic
import gmaps
from math import atan2, degrees, sqrt
from pyproj import Proj, transform
import os
geod = Geodesic.WGS84
def parse_json(filename):
# returns list of json objects
# list to hold every string version of each JSON object in separate list within the larger list
split_list = [[]]
# for iterating which JSON object the string is currently being added to
i = 0
# opens JSON file with name file
with open(filename, "r") as file:
for line in file.readlines():
# not the end of the JSON object
if "}," in line:
split_list[i].append(line)
continue
# is the end of the JSON object
elif "}" in line:
# adds the last line of the object to the string
split_list[i].append(line)
# goes to the next list
i += 1
split_list.append([])
continue
# just another part of the string
else:
split_list[i].append(line)
# list of strings that're each JSON objects
json_string_list = []
# iterates over each list from above
for i in split_list:
# creates empty string to convert each to
json_string = ""
for j in i:
json_string += j
# appends the string once it's fully made to the list of JSON objects
json_string_list.append(json_string)
return json_string_list[-2:]
def get_JSON_dict(json_string_list, previous_lat_lng):
# returns x, y lists
json_string_list = json_string_list[0].split("}],")
# adds the }]} back to the the string in each list
for index, stripped_string in enumerate(json_string_list):
add_back = stripped_string + "}]}"
# adds the string back into the list
json_string_list[index] = add_back
# takes out the empty string at index -
json_string_list.pop(-1)
# iterates over the entire JSON string object
for s in json_string_list:
# loads the JSON string as a JSON object
if "{" != s[0]:
d = "{" + s
json_s = json.loads(d)
else:
json_s = json.loads(s)
# finds the frames as keys and iterates over them
for key in json_s.keys():
# iterates over the list within the keys variable
for index, obj in enumerate(json_s[key]):
# splits the string list into an actual list
latitude = obj["latitude"]
longitude = obj["longitude"]
# checks whether or not the ID is already in the dictionary
# if not then it doesn't add it to the dictionary again
if obj["id"] in previous_lat_lng:
# ID is already in the dictionary (doesn't need to be added)
pass
else:
# sets it equal to an empty list to hold latitude and longitude values respectively
previous_lat_lng[obj["id"]] = []
# changes the dictionary to have floats instead of string values for the positions
json_s[key][index]["latitude"] = latitude
json_s[key][index]["longitude"] = longitude
# returns the JSON dictionary
return json_s, previous_lat_lng
def update_dict(lat, lon, previous_lat_lng, id):
# checks whether or not the ID is already within the dictionary
if id in previous_lat_lng.keys():
# appends the current coordinates to the dictionary
previous_lat_lng[id].append([lat, lon])
else:
# creates a 2D list with the new coordinates in the dictionary
previous_lat_lng[id] = [[lat, lon]]
return previous_lat_lng
def graph_data(json_dictionary, cam_lat, cam_lng, frame, previous_lat_lng, color="red", color2="cornflowerblue", edge_width=2.5):
# creates the map plotter
gmap3 = gmplot.GoogleMapPlotter(cam_lat, cam_lng, 20)
for i in range(len(json_dictionary["Frame " + str(frame)])):
# gets the current latitude and longitude
latitude = float(json_dictionary["Frame " + str(frame)][i]["latitude"])
longitude = float(json_dictionary["Frame " + str(frame)][i]["longitude"])
# finds the current id to put into the previous_lat_lng dictionary
current_id = json_dictionary["Frame " + str(frame)][i]["id"]
# updates the previous_lat_lng dictionary to be able to be used in the graphing function
previous_lat_lng = update_dict(latitude, longitude, previous_lat_lng, current_id)
for id in previous_lat_lng.keys():
# creates a list to be plotted on the map
lat_list, lng_list = [], []
for l in previous_lat_lng[id]: # l is a list of coordinates [latitude, longitude]
# adds the latitude coordinate
lat_list.append(l[0])
# adds the longitude coordinate
lng_list.append(l[1])
# plots the line of where the person traveled
gmap3.plot(lat_list, lng_list, color, edge_width, title=id)
gmap3.marker(lat_list[-1], lng_list[-1], color2, title=id)
# changes the directory to save the map to a separate folder within the project folder
os.chdir("maps")
# draws the google map and saves it to the map folder
gmap3.draw("map" + str(frame) + ".html")
# changes the directory back 1 folder to prevent errors
os.chdir("..")
# returns the previous dictionary in order to keep the previous data stored
return previous_lat_lng
def live_graph_coordinates(latitude, longitude, json_file, frame, previous_lat_lng):
# Uses api key to be able to make the coordinates
gmaps.configure(**api key is here**)
# shows the maps in satellite vision
gmaps.figure('SATELLITE')
# parses the json file to get a list of strings which are each a JSON object
json_string_list = parse_json(json_file)
# gets a list of x and y values for every object in the list
json_dictionary, previous_lat_lng = get_JSON_dict(json_string_list, previous_lat_lng)
if json_dictionary != None:
# Graphs all the data points from the JSON file
previous_lat_lng = graph_data(json_dictionary, latitude, longitude, frame, previous_lat_lng)
return previous_lat_lng
else:
# no objects detected
pass
{"Frame 1": [{"id": 533, "classification": "PERSON", "latitude": 33.48799308670221, "longitude": -111.90885153944437}, {"id": 549, "classification": "UNKNOWN", "latitude": 33.48801292738194, "longitude": -111.90885868765811}, {"id": 673, "classification": "PERSON", "latitude": 33.48804833314041, "longitude": -111.90882281530168}, {"id": 680, "classification": "UNKNOWN", "latitude": 33.4880037031338, "longitude": -111.90886720421587}, {"id": 682, "classification": "UNKNOWN", "latitude": 33.48801928916118, "longitude": -111.90877697851846}, {"id": 686, "classification": "PERSON", "latitude": 33.48804053863665, "longitude": -111.90881977666776}, {"id": 687, "classification": "PERSON", "latitude": 33.4880341240495, "longitude": -111.90881708982506}, {"id": 691, "classification": "PERSON", "latitude": 33.48803122508181, "longitude": -111.9088324527267}, {"id": 693, "classification": "UNKNOWN", "latitude": 33.48804587402998, "longitude": -111.90883551218909}, {"id": 694, "classification": "PERSON", "latitude": 33.48803580008242, "longitude": -111.90882961435683}, {"id": 696, "classification": "PERSON", "latitude": 33.48802004624938, "longitude": -111.90881496775653}, {"id": 697, "classification": "UNKNOWN", "latitude": 33.48802187886198, "longitude": -111.90882847417957}, {"id": 698, "classification": "PERSON", "latitude": 33.48801766538075, "longitude": -111.90882289307378}, {"id": 706, "classification": "UNKNOWN", "latitude": 33.4881289113697, "longitude": -111.908896469379}, {"id": 707, "classification": "PERSON", "latitude": 33.48806293756819, "longitude": -111.90880008535265}, {"id": 710, "classification": "UNKNOWN", "latitude": 33.4880314185434, "longitude": -111.90878311481961}, {"id": 711, "classification": "UNKNOWN", "latitude": 33.48804442683758, "longitude": -111.90879309453386}, {"id": 714, "classification": "PERSON", "latitude": 33.488061420726034, "longitude": -111.90879962024852}, {"id": 715, "classification": "PERSON", "latitude": 33.488055189955865, "longitude": -111.90879724325653}],
"Frame 2": [{"id": 533, "classification": "PERSON", "latitude": 33.48799308670221, "longitude": -111.90885153944437}, {"id": 549, "classification": "UNKNOWN", "latitude": 33.48801292738194, "longitude": -111.90885868765811}, {"id": 673, "classification": "PERSON", "latitude": 33.48804833314041, "longitude": -111.90882281530168}, {"id": 680, "classification": "UNKNOWN", "latitude": 33.4880037031338, "longitude": -111.90886720421587}, {"id": 682, "classification": "UNKNOWN", "latitude": 33.48801928916118, "longitude": -111.90877697851846}, {"id": 686, "classification": "PERSON", "latitude": 33.48804053863665, "longitude": -111.90881977666776}, {"id": 687, "classification": "PERSON", "latitude": 33.4880341240495, "longitude": -111.90881708982506}, {"id": 691, "classification": "PERSON", "latitude": 33.48803122508181, "longitude": -111.9088324527267}, {"id": 693, "classification": "UNKNOWN", "latitude": 33.48804587402998, "longitude": -111.90883551218909}, {"id": 694, "classification": "PERSON", "latitude": 33.48803580008242, "longitude": -111.90882961435683}, {"id": 696, "classification": "PERSON", "latitude": 33.48802004624938, "longitude": -111.90881496775653}, {"id": 697, "classification": "UNKNOWN", "latitude": 33.48802187886198, "longitude": -111.90882847417957}, {"id": 698, "classification": "PERSON", "latitude": 33.48801766538075, "longitude": -111.90882289307378}, {"id": 706, "classification": "UNKNOWN", "latitude": 33.4881289113697, "longitude": -111.908896469379}, {"id": 707, "classification": "PERSON", "latitude": 33.48806293756819, "longitude": -111.90880008535265}, {"id": 710, "classification": "UNKNOWN", "latitude": 33.4880314185434, "longitude": -111.90878311481961}, {"id": 711, "classification": "UNKNOWN", "latitude": 33.48804442683758, "longitude": -111.90879309453386}, {"id": 714, "classification": "PERSON", "latitude": 33.488061420726034, "longitude": -111.90879962024852}, {"id": 715, "classification": "PERSON", "latitude": 33.488055189955865, "longitude": -111.90879724325653}],
var latlng = new google.maps.LatLng(33.488199, -111.908902);
var img = new google.maps.MarkerImage('/home/greg/.local/lib/python3.5/site-packages/gmplot/markers/6495ED.png');
var marker = new google.maps.Marker({
title: "3119",
icon: img,
position: latlng
});
marker.setMap(map);
var latlng = new google.maps.LatLng(33.488194, -111.908912);
var img = new google.maps.MarkerImage('/home/greg/.local/lib/python3.5/site-packages/gmplot/markers/6495ED.png');
var marker = new google.maps.Marker({
title: "3218",
icon: img,
position: latlng
});
marker.setMap(map);
var latlng = new google.maps.LatLng(33.488194, -111.908912);
var img = new google.maps.MarkerImage('/home/greg/.local/lib/python3.5/site-packages/gmplot/markers/6495ED.png');
var marker = new google.maps.Marker({
title: "3492",
icon: img,
position: latlng
});
marker.setMap(map);
var latlng = new google.maps.LatLng(33.488194, -111.908912);
var img = new google.maps.MarkerImage('/home/greg/.local/lib/python3.5/site-packages/gmplot/markers/6495ED.png');
var marker = new google.maps.Marker({
title: "3493",
icon: img,
position: latlng
});
marker.setMap(map);
var latlng = new google.maps.LatLng(33.488194, -111.908912);
var img = new google.maps.MarkerImage('/home/greg/.local/lib/python3.5/site-packages/gmplot/markers/6495ED.png');
var marker = new google.maps.Marker({
title: "3236",
icon: img,
position: latlng
});
marker.setMap(map);
var latlng = new google.maps.LatLng(33.488194, -111.908912);
var img = new google.maps.MarkerImage('/home/greg/.local/lib/python3.5/site-packages/gmplot/markers/6495ED.png');
var marker = new google.maps.Marker({
title: "3483",
icon: img,
position: latlng
});
marker.setMap(map);
var latlng = new google.maps.LatLng(33.488194, -111.908912);
var img = new google.maps.MarkerImage('/home/greg/.local/lib/python3.5/site-packages/gmplot/markers/6495ED.png');
var marker = new google.maps.Marker({
title: "3119",
icon: img,
position: latlng
});
marker.setMap(map);
var PolylineCoordinates = [
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
new google.maps.LatLng(33.487887, -111.909013),
new google.maps.LatLng(33.488226, -111.908717),
new google.maps.LatLng(33.487970, -111.908849),
new google.maps.LatLng(33.488199, -111.908902),
new google.maps.LatLng(33.488194, -111.908912),
new google.maps.LatLng(33.487842, -111.908994),
];
As far as I can tell, you are confusing two libraries:
It's not clear what you're trying to do, but these packages are not inter-operable.
With
gmaps
, you should be able to update polylines on a map. I'd suggest looking into the following pages: - this on drawing poly-lines - this page on updating a symbol. You should be able to convert that to polylines.As a side-note, right now, your code is somewhat complicated, which makes it hard for people here to help. You'll get better quality answers if you try to come up with a simple, reproducible example.
Separately, you should definitely not hand-roll your own JSON parsing. Use the
json
library. If you only want to half-parse the JSON (it looks like that's what you're doing), parse everything, then re-dump what you need. Parsing is hard. Don't do it yourself.