def Generate_Waypoints( self ):
"""
RGM-109E Tactical Tomahawk for WiC MW
En Route Navigation for TERCOM mid-course guidance
Rather than running straight to the target and have everyone
and their grandmother shoot at the Tomahawk, we'd prefer the
missile to fly low and sneak around on the sides of the map,
using a set of waypoints. It will take longer to get there,
but it allows the Tomahawk to minimize radar detection and
maintain the element of surprise.
Calculate the shortest 2D world waypoints (X, Z) for the
cruise missile to navigate thru to approach the terminal
acquisition area (kill box). Upon arrival, missile will
need to transition from en-route control (mid-course) to
terminal guidance, pitching up to about 100wm height and then
diving onto the target.
1500 +------------------+--------------------+
| (*7) Delta (*6) Charlie (*5) |
| 1490,0,10 November 1490,0,1490 |
| 1490,0,750 |
| Grid | Grid |
| D | C |
| | |
X 750 +-(*8) Whiskey-----+----------Echo (*4)-+
axis | 750,0,10 | 750,0,1490 |
| | |
| Grid | Grid |
| A | B |
| 10,0,750 |
| 10,0,10 Sierra 10,0,1490 |
| (*1) Alpha (*2) Bravo (*3) |
0 +------------------+--------------------+
750 1500
Z axis
Navigation nodes
alpha: 1 sierra: 2 bravo: 3 echo: 4
charlie: 5 november: 6 delta: 7 whiskey: 8
Implement ECMP routing for salvo fires against target grids
having equidistant paths?
"""
INAV_MAX_COST = 32768
def SPF(graph, start, end, visted=[], distances={}, predecessors={} ):
# Dijkstra Shortest Path First (SPF) Algorithm
# http://code.activestate.com/recipes/119466-dijkstras-algorithm-for-shortest-paths/
# http://rebrained.com/?p=392
# First time init
if not visited: distances[start]=0
# Terminal node: find path to it and return
if start==end:
path=[]
while end != None:
path.append(end)
end=predecessors.get(end,None)
self.Host.Owner.ChatMessage("dndebug: spf dist = %s, waypoints = %s" % ( distances[start], path[::-1] ) )
return path[::-1]
# Process adj nodes and keep track of predecessors
for neighbor in graph[start]:
if neighbor not in visited:
neighbordist = distances.get(neighbor,INAV_MAX_COST)
tentativedist = distances[start] + graph[start][neighbor]
if tentativedist < neighbordist:
distances[neighbor] = tentativedist
predecessors[neighbor]=start
# adj nodes processed, mark current node as visited
visited.append(start)
# Find the closest unvisited node to the start
unvisiteds = dict((k, distances.get(k,INAV_MAX_COST)) for k in graph if k not in visited)
closestnode = min(unvisiteds, key=unvisiteds.get)
# Now take the closest node and recurse, making it current
return SPF(graph,closestnode,end,visited,distances,predecessors)
nodes = {
1: math.Vector3( 10, 0, 10 ),
2: math.Vector3( 10, 0, 750 ),
3: math.Vector3( 10, 0, 1490 ),
4: math.Vector3( 750, 0, 1490 ),
5: math.Vector3( 1490, 0, 1490 ),
6: math.Vector3( 1490, 0, 750 ),
7: math.Vector3( 1490, 0, 10 ),
8: math.Vector3( 750, 0, 10 )
}
# Get the nearest ingress & egress enroute waypoints for missile
# launch location and desired target coordinates (terminal basket).
start_max_dist = INAV_MAX_COST
end_max_dist = INAV_MAX_COST
for i in nodes:
len_to_start = ( math.Vector3( self.current_state ) - nodes[i] ).Length2D()
len_to_end = ( math.Vector3( self.PN_Terminal_Basket ) - nodes[i] ).Length2D()
if len_to_start < start_max_dist:
start_wp = i
start_max_dist = len_to_start
if len_to_end < end_max_dist:
end_wp = i
end_max_dist = len_to_end
# link path costs
graph = {
1: { 2: 7, 3: 14, 4: 21, 5:28, 6:21, 7:14, 8:7 },
2: { 1: 7, 3: 7, 4: 14, 5:21, 6:28, 7:21, 8:14 },
3: { 1: 14, 2: 7, 4: 7, 5:14, 6:21, 7:28, 8:21 },
4: { 1: 21, 2: 14, 3: 7, 5:7, 6:14, 7:21, 8:28 },
5: { 1: 28, 2: 21, 3: 14, 4:7, 6:7, 7:14, 8:21 },
6: { 1: 21, 2: 28, 3: 21, 4:14, 5:7, 7:7, 8:14 },
7: { 1: 14, 2: 21, 3: 28, 4:21, 5:14, 6:7, 8:7 },
8: { 1: 7, 2: 14, 3: 21, 4:28, 5:21, 6:14, 7:7 }
}
self.ENR_waypoints = SPF(graph, start_wp, end_wp)
self.Host.Owner.ChatMessage("dndebug: enr_waypoints = %s" % self.ENR_waypoints, 1 )
return True