|
|
@@ -4,26 +4,36 @@ from dataclasses import dataclass
|
|
|
from geoplotlib.utils import haversine
|
|
|
import matplotlib.path as mplPath
|
|
|
from os.path import exists
|
|
|
+import random
|
|
|
|
|
|
-docks = pd.read_csv("../berths.csv")
|
|
|
+from de2.routing import get_graph, get_closest_vertex
|
|
|
+
|
|
|
+docks = pd.read_csv("berths.csv")
|
|
|
polygons = {k["lpl_id"]: eval(k["polygon"]) for _, k in docks.iterrows()}
|
|
|
|
|
|
+tugs = pd.read_excel("20230405_Tugs.xlsx", dtype={"MMSI": str, "NAME": str})
|
|
|
+tmap = {}
|
|
|
+for _, row in tugs.iterrows():
|
|
|
+ tmap[row["MMSI"]] = row["NAME"]
|
|
|
+
|
|
|
@dataclass
|
|
|
class Vessel:
|
|
|
mmsi: str
|
|
|
+ name: str
|
|
|
start: int
|
|
|
end: int
|
|
|
location: str
|
|
|
- latlon_s: tuple
|
|
|
- latlon_t: tuple
|
|
|
+ lonlat_s: tuple
|
|
|
+ lonlat_t: tuple
|
|
|
distance: float
|
|
|
+ task: str
|
|
|
|
|
|
def is_inside(lon, lat, polygon):
|
|
|
ppath = mplPath.Path(np.array(polygon))
|
|
|
return ppath.contains_point((lon, lat))
|
|
|
|
|
|
|
|
|
-def get_dock(lat, lon):
|
|
|
+def get_dock(lon, lat):
|
|
|
# loop through all dock indexes and do insideness checks
|
|
|
for pid, poly in polygons.items():
|
|
|
if is_inside(lon, lat, poly):
|
|
|
@@ -37,49 +47,104 @@ def analyze(fname):
|
|
|
df = pd.read_csv(fname, dtype={"mmsi": str})
|
|
|
df.sort_values(by=["ts"], inplace=True)
|
|
|
|
|
|
- res = pd.DataFrame(columns=["mmsi", "start", "end", "location", "source_lon", "source_lat", "target_lon", "target_lat", "distance"])
|
|
|
+ res = pd.DataFrame(columns=["mmsi", "name", "start", "end", "location", "source_lon", "source_lat",
|
|
|
+ "target_lon", "target_lat", "distance", "task"])
|
|
|
+
|
|
|
+ graph = get_graph()
|
|
|
+
|
|
|
+ task = random.choice([0, 1])
|
|
|
+ tasks = ["tugging", "sailing"]
|
|
|
|
|
|
first = df.iloc[0]
|
|
|
- vessel = Vessel(first["mmsi"], first["ts"], -1, get_dock(first["lat"], first["lon"]),
|
|
|
- (first["lat"], first["lon"]), (first["lat"], first["lon"]), 0.0)
|
|
|
+ vessel = Vessel(first["mmsi"], tmap[str(first["mmsi"])], first["ts"], -1, get_dock(first["lon"], first["lat"]),
|
|
|
+ (first["lon"], first["lat"]), (first["lon"], first["lat"]), 0.0, tasks[task])
|
|
|
|
|
|
- if exists("results-de/%s-de.csv" % str(vessel.mmsi)):
|
|
|
+ if exists("../results-de/%s-de.csv" % str(vessel.mmsi)):
|
|
|
print("Already done %s" % str(vessel.mmsi))
|
|
|
return None
|
|
|
- # time = first["ts"]
|
|
|
- # dts = []
|
|
|
+
|
|
|
+ in_dock = get_dock(first["lon"], first["lat"]) != ""
|
|
|
+ time = first["ts"]
|
|
|
for _, row in df.iloc[1:].iterrows():
|
|
|
- # find the distance between the previous point and the current point
|
|
|
- vessel.distance += haversine(vessel.latlon_t[1], vessel.latlon_t[0], row["lon"], row["lat"])
|
|
|
- vessel.latlon_t = row["lat"], row["lon"]
|
|
|
- new_loc = get_dock(row["lat"], row["lon"])
|
|
|
- # dts.append(row["ts"] - time)
|
|
|
- # time = row["ts"]
|
|
|
+ # See if you are at a new location
|
|
|
+ new_loc = get_dock(row["lon"], row["lat"])
|
|
|
if new_loc != vessel.location:
|
|
|
- # new location!
|
|
|
- vessel.end = row["ts"]
|
|
|
- res.loc[len(res.index)] = [vessel.mmsi, vessel.start, vessel.end, vessel.location,
|
|
|
- vessel.latlon_s[1], vessel.latlon_s[0], vessel.latlon_t[1], vessel.latlon_t[0],
|
|
|
- vessel.distance]
|
|
|
- vessel.start = row["ts"]
|
|
|
+ # fix for teleportation issue
|
|
|
+
|
|
|
+ # add intermediate points on which dock/sailing transition is assumed
|
|
|
+ # it is assumed that these points lie on the theoretical trajectory => APPROXIMATION
|
|
|
+ # FIXME: a better solution would be to divide the theoretical path into equal parts instead
|
|
|
+ if in_dock and new_loc != "":
|
|
|
+ # check movement to the next dock: divide the trajectory in 3 equal parts
|
|
|
+ center = (row["lon"] + 2 * vessel.lonlat_t[0]) / 3, (row["lat"] + 2 * vessel.lonlat_t[1]) / 3
|
|
|
+ c, _ = get_closest_vertex(graph, center[0], center[1])
|
|
|
+ center = c["x"], c["y"]
|
|
|
+ p2 = (2 * row["lon"] + vessel.lonlat_t[0]) / 3, (2 * row["lat"] + vessel.lonlat_t[1]) / 3
|
|
|
+ p, _ = get_closest_vertex(graph, p2[0], p2[1])
|
|
|
+ p2 = p["x"], p["y"]
|
|
|
+
|
|
|
+ d1 = haversine(vessel.lonlat_t[0], vessel.lonlat_t[1], center[0], center[1])
|
|
|
+ d2 = haversine(p2[0], p2[1], row["lon"], row["lat"])
|
|
|
+ d3 = haversine(center[0], center[1], p2[0], p2[1])
|
|
|
+ t1 = (row["ts"] + 2 * time) / 3
|
|
|
+ t2 = (2 * row["ts"] + time) / 3
|
|
|
+
|
|
|
+ # add a movement to the next dock
|
|
|
+ res.loc[len(res.index) + 1.5] = [vessel.mmsi, vessel.name, t1, t2, None,
|
|
|
+ center[0], center[1], p2[0], p2[1], d3, vessel.task]
|
|
|
+ else:
|
|
|
+ # divide the trajectory in 2 equal parts
|
|
|
+ center = p2 = (row["lon"] + vessel.lonlat_t[0]) / 2, (row["lat"] + vessel.lonlat_t[1]) / 2
|
|
|
+ c, _ = get_closest_vertex(graph, center[0], center[1])
|
|
|
+ center = c["x"], c["y"]
|
|
|
+
|
|
|
+ d1 = haversine(vessel.lonlat_t[0], vessel.lonlat_t[1], center[0], center[1])
|
|
|
+ d2 = haversine(center[0], center[1], row["lon"], row["lat"])
|
|
|
+ t1 = t2 = (row["ts"] + time) / 2
|
|
|
+
|
|
|
+ # store previous trajectory
|
|
|
+ res.loc[len(res.index)] = [vessel.mmsi, vessel.name, vessel.start, t1, vessel.location,
|
|
|
+ vessel.lonlat_s[0], vessel.lonlat_s[1],
|
|
|
+ center[0], center[1], vessel.distance + d1, vessel.task]
|
|
|
+
|
|
|
+ if new_loc != "":
|
|
|
+ # Randomly pick tugging or sailing
|
|
|
+ task = random.choice([0, 1])
|
|
|
+ vessel.task = tasks[task]
|
|
|
+
|
|
|
+ # store beginning of new trajectory
|
|
|
+ vessel.start = t2
|
|
|
vessel.end = -1
|
|
|
vessel.location = new_loc
|
|
|
- vessel.distance = 0.0
|
|
|
- vessel.latlon_s = vessel.latlon_t
|
|
|
- res.loc[len(res.index)] = [vessel.mmsi, vessel.start, df.iloc[-1]["ts"], vessel.location,
|
|
|
- vessel.latlon_s[1], vessel.latlon_s[0], vessel.latlon_t[1], vessel.latlon_t[0],
|
|
|
- vessel.distance]
|
|
|
+ vessel.distance = d2
|
|
|
+ vessel.lonlat_s = p2
|
|
|
+ vessel.lonlat_t = row["lon"], row["lat"]
|
|
|
+ else:
|
|
|
+ # find the distance between the previous point and the current point
|
|
|
+ vessel.distance += haversine(vessel.lonlat_t[0], vessel.lonlat_t[1], row["lon"], row["lat"])
|
|
|
+ vessel.lonlat_t = row["lon"], row["lat"]
|
|
|
+
|
|
|
+ time = row["ts"]
|
|
|
+ in_dock = new_loc != ""
|
|
|
+
|
|
|
+ res.loc[len(res.index)] = [vessel.mmsi, vessel.name, vessel.start, df.iloc[-1]["ts"], vessel.location,
|
|
|
+ vessel.lonlat_s[0], vessel.lonlat_s[1], vessel.lonlat_t[0], vessel.lonlat_t[1],
|
|
|
+ vessel.distance, vessel.task]
|
|
|
# print("AVG dt:", sum(dts) / len(dts), max(dts), min(dts))
|
|
|
- res.to_csv("../results-de/%s-de.csv" % str(vessel.mmsi))
|
|
|
+ # res.sort_values(by=["start"], inplace=True)
|
|
|
+ res = res.sort_index().reset_index(drop=True)
|
|
|
+ res["velocity"] = res["distance"] / ((res["end"] - res["start"]) / 1000)
|
|
|
+ res.to_csv("results-de/%s-de.csv" % str(vessel.mmsi), index=False)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
+ # print(get_dock(4.242435, 51.27712))
|
|
|
# import sys
|
|
|
# analyze(sys.argv[2])
|
|
|
# analyze("results/205254890.csv")
|
|
|
|
|
|
- TFILE = "../tugs.csv"
|
|
|
+ TFILE = "tugs.csv"
|
|
|
tugs = pd.read_csv(TFILE)
|
|
|
mmsi = tugs["MMSI"].dropna().astype(np.int32)
|
|
|
for idx in mmsi:
|
|
|
- analyze("../results/%s.csv" % str(idx))
|
|
|
+ analyze("results/%s.csv" % str(idx))
|
|
|
print(idx, "done")
|