Skip to content

Commit

Permalink
Merge branch 'master' into intermediate_path
Browse files Browse the repository at this point in the history
  • Loading branch information
dakk authored Nov 19, 2024
2 parents bc9771f + c56ff4a commit 88d27ca
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 23 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,11 @@ Calculate subsequent steps until the end track point is reached

```python
while not self.routing_obj.end:
res = self.routing_obj.step()
res = self.routing_obj.step() # default step duration is set to 1 hour

# you can call a step with custom timedelta (in hour) at anytime
while not self.routing_obj.end:
res = self.routing_obj.step(timedelta=0.25) # 15min time delta
```
the step method returns a RoutingResult object with the following informations during routing calculation:
```python
Expand Down
28 changes: 27 additions & 1 deletion tests/linearbestisorouter_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ def test_step(self):
res = self.routing_obj.step()
i += 1

self.assertEqual(i, 9)
self.assertEqual(i, 10)
self.assertEqual(not res.path, False)


Expand Down Expand Up @@ -264,3 +264,29 @@ def test_step(self):

self.assertEqual(i, 5)
self.assertEqual(not res.path, False)


class TestRouting_custom_step(unittest.TestCase):
def setUp(self):
grib = mock_grib(2, 180, 0.1)
self.track = [(5, 38), (5.2, 38.2)]
island_route = mock_point_validity(self.track, factor=5)
self.routing_obj = weatherrouting.Routing(
LinearBestIsoRouter,
polar_bavaria38,
self.track,
grib,
datetime.datetime.fromisoformat("2021-04-02T12:00:00"),
pointValidity=island_route.point_validity,
)

def test_step(self):
res = None
i = 0

while not self.routing_obj.end:
res = self.routing_obj.step(timedelta=0.5)
i += 1

self.assertEqual(i, 14)
self.assertEqual(not res.path, False)
34 changes: 34 additions & 0 deletions tests/shortestpathrouter_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,37 @@ def test_step(self):

self.assertEqual(i, 4)
self.assertEqual(not res.path, False)


class TestRouting_custom_step(unittest.TestCase):
def setUp(self):
grib = mock_grib(2, 180, 0.1)
self.track = [(5, 38), (5.2, 38.2)]
island_route = mock_point_validity(self.track)
self.routing_obj = weatherrouting.Routing(
ShortestPathRouter,
None,
self.track,
grib,
datetime.datetime.fromisoformat("2021-04-02T12:00:00"),
pointValidity=island_route.point_validity,
)

def test_step(self):
res = None
i = 0

while not self.routing_obj.end:
res = self.routing_obj.step(timedelta=0.5)
i += 1

self.assertEqual(i, 5)
self.assertEqual(not res.path, False)

path_to_end = res.path + [IsoPoint(self.track[-1])]
self.assertEqual(
res.time, datetime.datetime.fromisoformat("2021-04-02 14:00:00")
)
self.assertEqual(
len(json.dumps(weatherrouting.utils.pathAsGeojson(path_to_end))), 1785
)
24 changes: 16 additions & 8 deletions weatherrouting/routers/linearbestisorouter.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class LinearBestIsoRouter(Router):
)
}

def _route(self, lastlog, time, start, end, isoF): # noqa: C901
def _route(self, lastlog, time, timedelta, start, end, isoF): # noqa: C901
position = start
path = []

Expand All @@ -51,13 +51,21 @@ def generate_path(p):
path = path[::-1]
position = path[-1].pos

if self.grib.getWindAt(time + datetime.timedelta(hours=1), end[0], end[1]):
if self.grib.getWindAt(
time + datetime.timedelta(hours=timedelta), end[0], end[1]
):
if lastlog is not None and len(lastlog.isochrones) > 0:
isoc = isoF(time + datetime.timedelta(hours=1), lastlog.isochrones, end)
isoc = isoF(
time + datetime.timedelta(hours=timedelta),
timedelta,
lastlog.isochrones,
end,
)
else:
nwdist = utils.pointDistance(end[0], end[1], start[0], start[1])
isoc = isoF(
time + datetime.timedelta(hours=1),
time + datetime.timedelta(hours=timedelta),
timedelta,
[[IsoPoint((start[0], start[1]), time=time, nextWPDist=nwdist)]],
end,
)
Expand All @@ -67,7 +75,7 @@ def generate_path(p):
for p in isoc[-1]:
distance_to_end_point = p.pointDistance(end)
if distance_to_end_point < self.getParamValue("minIncrease"):
# (twd,tws) = self.grib.getWindAt (time + datetime.timedelta(hours=1),
# (twd,tws) = self.grib.getWindAt (time + datetime.timedelta(hours=timedelta),
# p.pos[0], p.pos[1])
maxReachDistance = utils.maxReachDistance(p.pos, p.speed)
if distance_to_end_point < abs(maxReachDistance * 1.1):
Expand Down Expand Up @@ -95,7 +103,7 @@ def generate_path(p):
generate_path(minP)

return RoutingResult(
time=time + datetime.timedelta(hours=1),
time=time + datetime.timedelta(hours=timedelta),
path=path,
position=position,
isochrones=isoc,
Expand Down Expand Up @@ -123,5 +131,5 @@ def generate_path(p):

return path

def route(self, lastlog, t, start, end) -> RoutingResult:
return self._route(lastlog, t, start, end, self.calculateIsochrones)
def route(self, lastlog, t, timedelta, start, end) -> RoutingResult:
return self._route(lastlog, t, timedelta, start, end, self.calculateIsochrones)
13 changes: 6 additions & 7 deletions weatherrouting/routers/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def getParamValue(self, code):
raise Exception(f"Invalid param: {code}")
return self.PARAMS[code].value

def calculateShortestPathIsochrones(self, fixedSpeed, t, isocrone, nextwp):
def calculateShortestPathIsochrones(self, fixedSpeed, t, dt, isocrone, nextwp):
"""Calculates isochrones based on shortest path at fixed speed (motoring);
the speed considers reductions / increases derived from leeway"""

Expand All @@ -195,10 +195,10 @@ def pointF(p, tws, twa, dt, brg):
)

return self._calculateIsochrones(
t, isocrone, nextwp, pointF, self.getParamValue("subdiv")
t, dt, isocrone, nextwp, pointF, self.getParamValue("subdiv")
)

def calculateIsochrones(self, t, isocrone, nextwp):
def calculateIsochrones(self, t, dt, isocrone, nextwp):
"""Calculate isochrones depending on routageSpeed from polar"""

def pointF(p, tws, twa, dt, brg):
Expand All @@ -215,7 +215,7 @@ def pointF(p, tws, twa, dt, brg):
return rpd

return self._calculateIsochrones(
t, isocrone, nextwp, pointF, self.getParamValue("subdiv")
t, dt, isocrone, nextwp, pointF, self.getParamValue("subdiv")
)

def _filterValidity(self, isonew, last): # noqa: C901
Expand Down Expand Up @@ -264,9 +264,8 @@ def validLine(a):

return isonew

def _calculateIsochrones(self, t, isocrone, nextwp, pointF, subdiv): # noqa: C901
def _calculateIsochrones(self, t, dt, isocrone, nextwp, pointF, subdiv): # noqa: C901
"""Calcuates isochrones based on pointF next point calculation"""
dt = 1.0 / 60.0 * 60.0
last = isocrone[-1]

newisopoints = []
Expand Down Expand Up @@ -358,5 +357,5 @@ def calculateVMG(self, speed, angle, start, end) -> float:
at current speed / angle"""
return speed * math.cos(angle)

def route(self, lastlog, t, start, end) -> RoutingResult:
def route(self, lastlog, t, timedelta, start, end) -> RoutingResult:
raise Exception("Not implemented")
7 changes: 4 additions & 3 deletions weatherrouting/routers/shortestpathrouter.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ class ShortestPathRouter(LinearBestIsoRouter):
),
}

def route(self, lastlog, t, start, end) -> RoutingResult:
def route(self, lastlog, t, timedelta, start, end) -> RoutingResult:
return self._route(
lastlog,
t,
timedelta,
start,
end,
lambda t, isoc, end: self.calculateShortestPathIsochrones(
self.getParamValue("fixedSpeed"), t, isoc, end
lambda t, dt, isoc, end: self.calculateShortestPathIsochrones(
self.getParamValue("fixedSpeed"), t, timedelta, isoc, end
),
)
11 changes: 8 additions & 3 deletions weatherrouting/routing.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ def get_current_best_path(self) -> List:
last_wp = (self.wp - 1) if self.wp >= len(self.track) else self.wp
return self.algorithm.get_current_best_path(self.log[-1], self.track[last_wp])

def step(self) -> RoutingResult:

def step(self, timedelta=1) -> RoutingResult:
"""Execute a single routing step"""
self.steps += 1

Expand All @@ -119,10 +120,14 @@ def step(self) -> RoutingResult:
nextwp = self.track[self.wp]

if self._startingNewPoint or len(self.log) == 0:
res = self.algorithm.route(None, self.time, self.position, nextwp)
res = self.algorithm.route(
None, self.time, timedelta, self.position, nextwp
)
self._startingNewPoint = False
else:
res = self.algorithm.route(self.log[-1], self.time, self.position, nextwp)
res = self.algorithm.route(
self.log[-1], self.time, timedelta, self.position, nextwp
)

# self.time += 0.2
ff = 100 / len(self.track)
Expand Down

0 comments on commit 88d27ca

Please sign in to comment.