-
Notifications
You must be signed in to change notification settings - Fork 7
/
fgelev.py
executable file
·129 lines (112 loc) · 4.83 KB
/
fgelev.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/usr/bin/env python2
import os
import logging
import pickle
import subprocess
import calc_tile
import sys
from vec2d import vec2d
logging.basicConfig()
logger = logging.getLogger('fgelev')
#logger.setLevel("DEBUG")
class Probe_fgelev(object):
"""A drop-in replacement for Interpolator. Probes elevation via fgelev.
Make sure to use the patched version of fgelev (see osm2city/fgelev/) or
performance is likely to be terrible.
By default, queries are cached. Call save_cache() to
save the cache to disk before freeing the object.
"""
def __init__(self, path_to_fgelev, path_to_scenery, inputfilename, fake=False, cache=True, auto_save_every=50000):
"""Open pipe to fgelev.
Unless disabled by cache=False, initialize the cache and try to read
it from disk. Automatically save the cache to disk every auto_save_every misses.
If fake=True, never do any probing and return 0 on all queries.
"""
self.fake = fake
self.path_to_fgelev = path_to_fgelev
self.PATH_TO_SCENERY = path_to_scenery
self.auto_save_every = auto_save_every
self.h_offset = 0
self.fgelev_pipe = None
if cache:
self.pkl_fname = inputfilename+ '_elev.pkl'
#print (inputfilename)
try:
logger.info("Loading %s", self.pkl_fname)
fpickle = open(self.pkl_fname, 'rb')
self._cache = pickle.load(fpickle)
fpickle.close()
logger.info("OK")
except IOError as reason:
logger.warn("Loading elev cache failed (%s)", reason)
self._cache = {}
else:
self._cache = None
def open_fgelev(self):
logger.info("Spawning fgelev")
fg_root = "/home/shared/fgdata"
self.fgelev_pipe = subprocess.Popen(self.path_to_fgelev + ' --expire 1000000 --fg-root ' + fg_root + ' --fg-scenery '+ self.PATH_TO_SCENERY,
shell=True,
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
"""
This should catch spawn errors, but it doesn't. We
check for sane return values on fgelev calls later.
"""
# if self.fgelev_pipe.poll() != 0:
# raise RuntimeError("Spawning fgelev failed.")
def save_cache(self):
"save cache to disk"
fpickle = open(self.pkl_fname, 'wb')
pickle.dump(self._cache, fpickle, -1)
fpickle.close()
def shift(self, h):
self.h_offset += h
def __call__(self, position, check_btg=False):
"""return elevation at (x,y). We try our cache first. Failing that,
call fgelev.
"""
def really_probe(position):
if check_btg:
btg_file = self.PATH_TO_SCENERY + os.sep + "Terrain" \
+ os.sep + calc_tile.directory_name(position) + os.sep \
+ calc_tile.construct_btg_file_name(position)
print (calc_tile.construct_btg_file_name(position))
if not os.path.exists(btg_file):
logger.error("Terrain File " + btg_file + " does not exist. Set scenery path correctly or fly there with TerraSync enabled")
sys.exit(2)
if not self.fgelev_pipe:
self.open_fgelev()
try:
self.fgelev_pipe.stdin.write(b"%i %g %g\n" % (0, position.lon, position.lat))
self.fgelev_pipe.stdin.flush()
except IOError as reason:
logger.error(reason)
try:
QueuedElev = self.fgelev_pipe.stdout.readline().decode("utf-8")
if ":" in QueuedElev:
line = QueuedElev
else:
line = "foo: 0.00"
elev = float(line.split()[1]) + self.h_offset
except IndexError as reason:
logger.fatal("fgelev returned <%s>, resulting in %s. Did fgelev start OK?", line, reason)
raise RuntimeError("fgelev errors are fatal.")
return elev
if self.fake:
return (0)
position = vec2d(position[0], position[1])
if self._cache == None:
return really_probe(position)
key = (position.lon, position.lat)
try:
elev = self._cache[key]
logger.debug("hit %s %g" % (str(key), elev))
return elev
except KeyError:
#logger.debug("miss (%i) %s" % (len(self._cache), str(key)))
elev = really_probe(position)
#logger.debug(" %g" % elev)
self._cache[key] = elev
if self.auto_save_every and len(self._cache) % self.auto_save_every == 0:
self.save_cache()
return elev