Completed camera control server in lua and more work on merging algorithm

This commit is contained in:
Pax1601 2024-02-28 18:58:40 +01:00
parent 05e0cc393a
commit 832568aa00
14 changed files with 403 additions and 65 deletions

View File

@ -582,7 +582,8 @@ export class Map extends L.Map {
setCameraControlMode(newCameraControlMode: string) {
this.#cameraControlMode = newCameraControlMode;
this.#broadcastPosition();
if (this.#slaveDCSCamera)
this.#broadcastPosition();
}
/* Event handlers */
@ -773,7 +774,7 @@ export class Map extends L.Map {
try {
groundElevation = parseFloat(response);
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("PUT", `http://localhost:${this.#cameraControlPort}`);
xmlHttp.open("PUT", `http://127.0.0.1:${this.#cameraControlPort}`);
xmlHttp.setRequestHeader("Content-Type", "application/json");
const C = 40075016.686;
@ -981,7 +982,7 @@ export class Map extends L.Map {
#checkCameraPort(){
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("OPTIONS", `http://localhost:${this.#cameraControlPort}`);
xmlHttp.open("OPTIONS", `http://127.0.0.1:${this.#cameraControlPort}`);
xmlHttp.onload = (res: any) => {
if (xmlHttp.status == 200)
this.#setSlaveDCSCameraAvailable(true);

View File

@ -0,0 +1,214 @@
local _prevLuaExportStart = LuaExportStart
local _prevLuaExportBeforeNextFrame = LuaExportBeforeNextFrame
local _prevLuaExportStop = LuaExportStop
local server = nil
local port = 3003
local headers = "Access-Control-Allow-Origin: *\r\nAccess-Control-Allow-Methods: PUT, OPTIONS\r\nAccess-Control-Allow-Headers: *\r\nAccess-Control-Max-Age: 86400\r\nVary: Accept-Encoding, Origin\r\nKeep-Alive: timeout=2, max=100\r\nConnection: Keep-Alive\r\n\r\n"
function startTCPServer()
log.write('OLYMPUSCAMERACONTROL.EXPORT.LUA', log.INFO, 'Starting TCP Server')
package.path = package.path..";"..lfs.currentdir().."/LuaSocket/?.lua"
package.cpath = package.cpath..";"..lfs.currentdir().."/LuaSocket/?.dll"
socket = require("socket")
server = assert(socket.bind("127.0.0.1", port))
if server then
server:setoption("tcp-nodelay", true)
server:settimeout(0)
log.write('OLYMPUSCAMERACONTROL.EXPORT.LUA', log.INFO, 'TCP Server listening on port ' .. port)
else
log.write('OLYMPUSCAMERACONTROL.EXPORT.LUA', log.INFO, 'TCP Server did not start successfully')
end
end
function receiveTCP()
if server then
-- Accept a new connection without blocking
local client = server:accept()
if client then
-- Set the timeout of the connection to 5ms
client:settimeout(0)
client:setoption("tcp-nodelay", true)
local acc = ""
local data = ""
-- Start receiving data, accumulate it in acc
while data ~= nil do
-- Receive a new line
data, err, partial = client:receive('*l')
if data then
-- If we receive an empty string it means the header section of the message is over
if data == "" then
-- Is this an OPTIONS request?
if string.find(acc, "OPTIONS") ~= nil then
client:send("HTTP/1.1 200 OK\r\n" .. headers)
client:close()
-- Is this a PUT request?
elseif string.find(acc, "PUT") ~= nil then
-- Extract the length of the body
local contentLength = string.match(acc, "Content%-Length: (%d+)")
if contentLength ~= nil then
-- Receive the body
body, err, partial = client:receive(tonumber(contentLength))
if body ~= nil then
local lat = string.match(body, '"lat":%s*([%+%-]?[%d%.]+)%s*[},]')
local lng = string.match(body, '"lng":%s*([%+%-]?[%d%.]+)%s*[},]')
local alt = string.match(body, '"alt":%s*([%+%-]?[%d%.]+)%s*[},]')
local mode = string.match(body, '"mode":%s*"(%a+)"%s*[},]')
if lat ~= nil and lng ~= nil then
client:send("HTTP/1.1 200 OK\r\n" .. headers)
local position = {}
position["lat"] = tonumber(lat)
position["lng"] = tonumber(lng)
if alt ~= nil then
position["alt"] = tonumber(alt)
end
-- F11 view
if mode == "live" or mode == nil then
LoSetCommand(158)
-- F10 view
elseif mode == "map" then
LoSetCommand(15)
end
client:send(setCameraPosition(position))
client:close()
else
client:send("HTTP/1.1 500 ERROR\r\n" .. headers)
client:close()
end
else
log.write('OLYMPUSCAMERACONTROL.EXPORT.LUA', log.ERROR, err)
end
end
client:close()
break
end
else
-- Keep accumulating the incoming data
acc = acc .. " " .. data
end
end
end
end
end
end
function stopTCPServer()
if server then
log.write('OLYMPUSCAMERACONTROL.EXPORT.LUA', log.INFO, 'Stopping TCP Server')
server:close()
end
server = nil
end
function setCameraPosition(position)
-- Get the old camera position
local oldPos = LoGetCameraPosition()
-- Extract the commanded position
local point = LoGeoCoordinatesToLoCoordinates(position.lng, position.lat)
local pointNorth = LoGeoCoordinatesToLoCoordinates(position.lng, position.lat + 0.1)
-- Compute the local map rotation and scale and send it back to the server
local rotation = math.atan2(pointNorth.z - point.z, pointNorth.x - point.x)
-- If no altitude is provided, preserve the current camera altitude
local altitude = nil
if position.alt == nil then
altitude = oldPos.p.y
else
altitude = position.alt
end
-- Set the camera position
local pos =
{
x = {x = 0, y = -1, z = 0},
y = {x = 1, y = 0, z = 0},
z = {x = 0, y = 0, z = 1},
p = {x = point.x, y = altitude, z = point.z}
}
LoSetCameraPosition(pos)
return '{"northRotation": ' .. rotation .. '}'
end
LuaExportStart = function()
package.path = package.path..";"..lfs.currentdir().."/LuaSocket/?.lua"
package.cpath = package.cpath..";"..lfs.currentdir().."/LuaSocket/?.dll"
startTCPServer()
-- call original
if _prevLuaExportStart then
_status, _result = pcall(_prevLuaExportStart)
if not _status then
log.write('OLYMPUSCAMERACONTROL.EXPORT.LUA', log.ERROR, 'ERROR Calling other LuaExportStart from another script', _result)
end
end
end
LuaExportBeforeNextFrame = function()
receiveTCP()
-- call original
if _prevLuaExportBeforeNextFrame then
_status, _result = pcall(_prevLuaExportBeforeNextFrame)
if not _status then
log.write('OLYMPUSCAMERACONTROL.EXPORT.LUA', log.ERROR, 'ERROR Calling other LuaExportBeforeNextFrame from another script', _result)
end
end
end
LuaExportStop = function()
stopTCPServer()
-- call original
if _prevLuaExportStop then
_status, _result = pcall(_prevLuaExportStop)
if not _status then
log.write('OLYMPUSCAMERACONTROL.EXPORT.LUA', log.ERROR, 'ERROR Calling other LuaExportStop from another script', _result)
end
end
end
function serializeTable(val, name, skipnewlines, depth)
skipnewlines = skipnewlines or false
depth = depth or 0
local tmp = string.rep(" ", depth)
if name then
if type(name) == "number" then
tmp = tmp .. "[" .. name .. "]" .. " = "
else
tmp = tmp .. name .. " = "
end
end
if type(val) == "table" then
tmp = tmp .. "{" .. (not skipnewlines and "\n" or "")
for k, v in pairs(val) do
tmp = tmp .. serializeTable(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and "\n" or "")
end
tmp = tmp .. string.rep(" ", depth) .. "}"
elseif type(val) == "number" then
tmp = tmp .. tostring(val)
elseif type(val) == "string" then
tmp = tmp .. string.format("%q", val)
elseif type(val) == "boolean" then
tmp = tmp .. (val and "true" or "false")
else
tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\""
end
return tmp
end

View File

@ -10,7 +10,7 @@
"request": "launch",
"program": "main.py",
"console": "integratedTerminal",
"args": ["./configs/NTTR/config.yml"]
"args": ["./configs/Caucasus/HighResolution.yml"]
}
]
}

View File

@ -0,0 +1,37 @@
import sys
from fastkml import kml
from pygeoif.geometry import Polygon
import json
import math
# constants
C = 40075016.686 # meters, Earth equatorial circumference
R = C / (2 * math.pi) # meters, Earth equatorial radius
W = 10000 # meters, size of the square around the airbase
if len(sys.argv) == 1:
print("Please provide a json file as first argument. You can also drop the json file on this script to run it.")
else:
input_file = sys.argv[1]
k = kml.KML()
ns = '{http://www.opengis.net/kml/2.2}'
d = kml.Document(ns, 'docid', 'doc name', 'doc description')
k.append(d)
with open(input_file) as jp:
j = json.load(jp)
for point in j['airbases'].values():
p = kml.Placemark(ns, 'id', 'name', 'description')
lat = point['latitude']
lng = point['longitude']
latDelta = math.degrees(W / R)
lngDelta = math.degrees(W / (R * math.cos(math.radians(lat))))
p.geometry = Polygon([(lng - lngDelta, lat - latDelta), (lng - lngDelta, lat + latDelta), (lng + lngDelta, lat + latDelta), (lng + lngDelta, lat - latDelta)])
d.append(p)
with open(input_file.removesuffix('.json')+'.kml', 'w') as kp:
kp.writelines(k.to_string(prettyprint=True))

View File

@ -0,0 +1,5 @@
{
'output_directory': '.\Caucasus', # Where to save the output files
'boundary_file': '.\configs\Caucasus\airbases.kml', # Input kml file setting the boundary of the map to create
'zoom_factor': 0.1 # [0: maximum zoom in (things look very big), 1: maximum zoom out (things look very small)]
}

View File

@ -2,7 +2,7 @@
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom">
<Document>
<name>Senza titolo</name>
<gx:CascadingStyle kml:id="__managed_style_2F9039BE1B2F0ACE3361">
<gx:CascadingStyle kml:id="__managed_style_280E5494AE2F24E92C22">
<Style>
<IconStyle>
<scale>1.2</scale>
@ -25,7 +25,7 @@
</BalloonStyle>
</Style>
</gx:CascadingStyle>
<gx:CascadingStyle kml:id="__managed_style_1FB08D70372F0ACE3361">
<gx:CascadingStyle kml:id="__managed_style_1EB9027B622F24E92C22">
<Style>
<IconStyle>
<Icon>
@ -47,57 +47,34 @@
</BalloonStyle>
</Style>
</gx:CascadingStyle>
<StyleMap id="__managed_style_0152B588AD2F0ACE3361">
<StyleMap id="__managed_style_0F57E9B9782F24E92C22">
<Pair>
<key>normal</key>
<styleUrl>#__managed_style_1FB08D70372F0ACE3361</styleUrl>
<styleUrl>#__managed_style_1EB9027B622F24E92C22</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#__managed_style_2F9039BE1B2F0ACE3361</styleUrl>
<styleUrl>#__managed_style_280E5494AE2F24E92C22</styleUrl>
</Pair>
</StyleMap>
<Placemark id="0389FD622C2F0ACE3361">
<Placemark id="0975D432582F24E92C1E">
<name>Poligono senza titolo</name>
<LookAt>
<longitude>-115.0437621195802</longitude>
<latitude>36.2404454323581</latitude>
<altitude>568.1069300877758</altitude>
<longitude>37.25019544589698</longitude>
<latitude>44.41771380726969</latitude>
<altitude>-138.6844933247498</altitude>
<heading>0</heading>
<tilt>0</tilt>
<gx:fovy>35</gx:fovy>
<range>21582.08160380367</range>
<range>3831683.119853139</range>
<altitudeMode>absolute</altitudeMode>
</LookAt>
<styleUrl>#__managed_style_0152B588AD2F0ACE3361</styleUrl>
<styleUrl>#__managed_style_0F57E9B9782F24E92C22</styleUrl>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-115.0657741984423,36.20908708202413,0 -115.0064821223275,36.20969233542438,0 -115.0077003574054,36.25251471885595,0 -115.0604905801644,36.25236266770626,0 -115.0657741984423,36.20908708202413,0
</coordinates>
</LinearRing>
</outerBoundaryIs>
</Polygon>
</Placemark>
<Placemark id="077CD022A52F0ACE74D0">
<name>Poligono senza titolo</name>
<LookAt>
<longitude>-115.144039076036</longitude>
<latitude>36.07599823986274</latitude>
<altitude>636.6854074835677</altitude>
<heading>0</heading>
<tilt>0</tilt>
<gx:fovy>35</gx:fovy>
<range>14114.14487087633</range>
<altitudeMode>absolute</altitudeMode>
</LookAt>
<styleUrl>#__managed_style_0152B588AD2F0ACE3361</styleUrl>
<Polygon>
<outerBoundaryIs>
<LinearRing>
<coordinates>
-115.1866576903507,36.06787728722109,0 -115.1107872218999,36.06765965614163,0 -115.1145241760975,36.10294242539007,0 -115.1779590799479,36.10179027153036,0 -115.1866576903507,36.06787728722109,0
32.46459319237173,45.67416695848307,0 32.2740650283415,45.2221541106433,0 33.22174616520244,44.4837859435444,0 34.05427109764131,44.2149221586376,0 34.96485577272431,44.60230684639296,0 35.50552864748745,44.8069362633187,0 36.446105774871,44.84425518198143,0 36.76914203317659,44.70347050722764,0 38.22313992004164,44.3163345847565,0 39.43106567523965,43.72064977016311,0 40.23832274382622,43.06831352526857,0 41.01327578994438,42.67925159935859,0 41.34464189582403,42.34329512558789,0 41.16749495371268,41.74956946999534,0 40.80780496107725,41.39360013128164,0 39.98364177441992,41.27272565351572,0 39.42209428526464,41.27830763089842,0 38.82136897872954,41.2291415593637,0 38.78900701766597,39.59331113999448,0 46.4826445997655,39.11657164682355,0 46.83937081793388,45.04996086829865,0 46.88987497227086,47.59122144470205,0 32.29992865035658,47.73230965442627,0 32.46459319237173,45.67416695848307,0
</coordinates>
</LinearRing>
</outerBoundaryIs>

View File

@ -0,0 +1,5 @@
{
'output_directory': '.\Caucasus', # Where to save the output files
'boundary_file': '.\configs\Caucasus\LowResolution.kml', # Input kml file setting the boundary of the map to create
'zoom_factor': 0.5 # [0: maximum zoom in (things look very big), 1: maximum zoom out (things look very small)]
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
{
'output_directory': '.\Caucasus', # Where to save the output files
'boundary_file': '.\configs\Caucasus\MediumResolution.kml', # Input kml file setting the boundary of the map to create
'zoom_factor': 0.25 # [0: maximum zoom in (things look very big), 1: maximum zoom out (things look very small)]
}

View File

@ -0,0 +1 @@
{"airbases":{"1":{"callsign":"Anapa-Vityazevo","coalition":"neutral","latitude":45.013174733771677,"longitude":37.359783477555922},"10":{"callsign":"Gudauta","coalition":"neutral","latitude":43.124233340197144,"longitude":40.564175768400638},"11":{"callsign":"Batumi","coalition":"neutral","latitude":41.603279859649049,"longitude":41.609275483509791},"12":{"callsign":"Senaki-Kolkhi","coalition":"neutral","latitude":42.238728081573278,"longitude":42.061021312855914},"13":{"callsign":"Kobuleti","coalition":"neutral","latitude":41.93210535345338,"longitude":41.876483823101026},"14":{"callsign":"Kutaisi","coalition":"neutral","latitude":42.179153937689627,"longitude":42.495684077400142},"15":{"callsign":"Mineralnye Vody","coalition":"neutral","latitude":44.218646823806807,"longitude":43.100679733081456},"16":{"callsign":"Nalchik","coalition":"neutral","latitude":43.510071438529849,"longitude":43.625108736097914},"17":{"callsign":"Mozdok","coalition":"neutral","latitude":43.791303250938249,"longitude":44.620327262102009},"18":{"callsign":"Tbilisi-Lochini","coalition":"neutral","latitude":41.674720064437075,"longitude":44.946875226153338},"19":{"callsign":"Soganlug","coalition":"neutral","latitude":41.641163266786613,"longitude":44.947183065316693},"2":{"callsign":"Krasnodar-Center","coalition":"neutral","latitude":45.087429883845076,"longitude":38.925202300775062},"20":{"callsign":"Vaziani","coalition":"neutral","latitude":41.637735936261556,"longitude":45.019090938460067},"21":{"callsign":"Beslan","coalition":"neutral","latitude":43.208500987380937,"longitude":44.588922553542936},"3":{"callsign":"Novorossiysk","coalition":"neutral","latitude":44.673329604126899,"longitude":37.786226060479564},"4":{"callsign":"Krymsk","coalition":"neutral","latitude":44.961383022734175,"longitude":37.985886938697085},"5":{"callsign":"Maykop-Khanskaya","coalition":"neutral","latitude":44.67144025735508,"longitude":40.021427482235985},"6":{"callsign":"Gelendzhik","coalition":"neutral","latitude":44.56767458600406,"longitude":38.004146350528103},"7":{"callsign":"Sochi-Adler","coalition":"neutral","latitude":43.439378434050852,"longitude":39.924231880466095},"8":{"callsign":"Krasnodar-Pashkovsky","coalition":"neutral","latitude":45.0460996415433,"longitude":39.203066906324537},"9":{"callsign":"Sukhumi-Babushara","coalition":"neutral","latitude":42.852741071634995,"longitude":41.142447588488196}},"frameRate":60,"load":0,"sessionHash":"K2n7kpGE9yOaYE4G","time":"1709136685634"}

File diff suppressed because one or more lines are too long

View File

@ -1,6 +0,0 @@
{
'output_directory': '.\LasVegas', # Where to save the output files
'boundary_file': '.\configs\LasVegas\boundary.kml', # Input kml file setting the boundary of the map to create
'zoom_factor': 0.02, # [0: maximum zoom in (things look very big), 1: maximum zoom out (things look very small)]
'geo_width': 1.14
}

View File

@ -2,7 +2,6 @@ import sys
import yaml
import json
import requests
import time
from pyproj import Geod
from fastkml import kml
@ -11,6 +10,9 @@ from datetime import timedelta
import map_generator
# Port on which the camera control module is listening
port = 3003
if len(sys.argv) == 1:
print("Please provide a configuration file as first argument. You can also drop the configuration file on this script to run it.")
else:
@ -53,9 +55,12 @@ else:
if 'geo_width' not in map_config:
# Let the user input the size of the screen to compute resolution
data = json.dumps({'lat': features[0].geometry.bounds[1], 'lng': features[0].geometry.bounds[0], 'alt': 1350 + map_config['zoom_factor'] * (25000 - 1350)})
r = requests.put('http://localhost:8080', data = data)
print("The F10 map in your DCS installation was setup. Please, use the measure tool and measure the width of the screen in Nautical Miles")
data = json.dumps({'lat': features[0].geometry.bounds[1], 'lng': features[0].geometry.bounds[0], 'alt': 1350 + map_config['zoom_factor'] * (25000 - 1350), 'mode': 'map'})
try:
r = requests.put(f'http://127.0.0.1:{port}', data = data)
print("The F10 map in your DCS installation was setup. Please, use the measure tool and measure the width of the screen in Nautical Miles")
except:
print("No running DCS instance detected. You can still run the algorithm if you already took the screenshots, otherwise you will not be able to produce a map.")
map_config['geo_width'] = input("Insert the width of the screen in Nautical Miles: ")
map_config['mpps'] = float(map_config['geo_width']) * 1852 / screen_config['width']
@ -72,7 +77,7 @@ else:
print(f"Estimated time to complete: {timedelta(seconds=total_time * 0.15)} (hh:mm:ss)")
input("Press enter to continue...")
map_generator.run(map_config)
map_generator.run(map_config, port)

View File

@ -5,6 +5,7 @@ import time
import os
import yaml
import json
import numpy
from fastkml import kml
from shapely import wkt, Point
@ -19,7 +20,7 @@ tot_futs = 0
# constants
C = 40075016.686 # meters, Earth equatorial circumference
R = C / (2 * math.pi)
R = C / (2 * math.pi) # meters, Earth equatorial radius
def deg_to_num(lat_deg, lon_deg, zoom):
lat_rad = math.radians(lat_deg)
@ -60,9 +61,9 @@ def extract_tiles(n, screenshots_XY, params):
n_height = params['n_height']
XY = screenshots_XY[n]
if (os.path.exists(os.path.join(output_directory, "screenshots", f"{f}_{n}.jpg"))):
if (os.path.exists(os.path.join(output_directory, "screenshots", f"{f}_{n}_{zoom}.jpg"))):
# Open the source screenshot
img = Image.open(os.path.join(output_directory, "screenshots", f"{f}_{n}.jpg"))
img = Image.open(os.path.join(output_directory, "screenshots", f"{f}_{n}_{zoom}.jpg"))
# Compute the Web Mercator Projection position of the top left corner of the most centered tile
X_center, Y_center = XY[0], XY[1]
@ -84,6 +85,7 @@ def extract_tiles(n, screenshots_XY, params):
try:
os.mkdir(os.path.join(output_directory, "tiles", str(zoom), str(X)))
except FileExistsError:
# Ignore this error, it means one other thread has already created the folder
continue
except Exception as e:
raise e
@ -91,33 +93,53 @@ def extract_tiles(n, screenshots_XY, params):
n += 1
else:
raise Exception(f"{os.path.join(output_directory, 'screenshots', f'{f}_{n}.jpg')} missing")
raise Exception(f"{os.path.join(output_directory, 'screenshots', f'{f}_{n}_{zoom}.jpg')} missing")
def merge_tiles(base_path, zoom, tile):
X = tile[0]
Y = tile[1]
positions = [(0, 0), (0, 1), (1, 0), (1, 1)]
# If the image already exists, open it so we can paste the higher quality data in it
if os.path.exists(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.jpg")):
dst = Image.open(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.jpg"))
dst = make_background_transparent(dst)
else:
dst = Image.new('RGB', (256, 256), (221, 221, 221))
dst = Image.new('RGB', (256, 256), (0, 0, 0, 0))
# Loop on all the 4 subtiles in the tile
positions = [(0, 0), (0, 1), (1, 0), (1, 1)]
for i in range(0, 4):
# Open the subtile, if it exists, and resize it down to 128x128
if os.path.exists(os.path.join(base_path, str(zoom), str(2*X + positions[i][0]), f"{2*Y + positions[i][1]}.jpg")):
im = Image.open(os.path.join(base_path, str(zoom), str(2*X + positions[i][0]), f"{2*Y + positions[i][1]}.jpg")).resize((128, 128))
else:
im = Image.new('RGB', (128, 128), (0, 0, 0, 0))
dst.paste(im, (positions[i][0] * 128, positions[i][1] * 128))
im = make_background_transparent(im)
dst.paste(im, (positions[i][0] * 128, positions[i][1] * 128))
# Create the output folder if it exists
if not os.path.exists(os.path.join(base_path, str(zoom - 1), str(X))):
try:
os.mkdir(os.path.join(base_path, str(zoom - 1), str(X)))
except FileExistsError:
# Ignore this error, it means one other thread has already created the folder
pass
except Exception as e:
raise e
dst.save(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.jpg"), quality=95)
def run(map_config):
# Save the image
dst.convert('RGB').save(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.jpg"), quality=95)
def make_background_transparent(im):
im.putalpha(255)
data = numpy.array(im)
red, green, blue, alpha = data.T
# If present, remove any "background" areas
background_areas = (red == 221) & (blue == 221) & (green == 221)
data[..., :][background_areas.T] = (0, 0, 0, 0) # make transparent
return Image.fromarray(data)
def run(map_config, port):
global tot_futs, fut_counter
with open('configs/screen_properties.yml', 'r') as sp:
@ -203,8 +225,8 @@ def run(map_config):
# Making PUT request
# If the number of rows or columns is odd, we need to take the picture at the CENTER of the tile!
lat, lng = num_to_deg(XY[0] + (n_width % 2) / 2, XY[1] + (n_height % 2) / 2, zoom)
data = json.dumps({'lat': lat, 'lng': lng, 'alt': 1350 + map_config['zoom_factor'] * (25000 - 1350)})
r = requests.put('http://localhost:8080', data = data)
data = json.dumps({'lat': lat, 'lng': lng, 'alt': 1350 + map_config['zoom_factor'] * (25000 - 1350), 'mode': 'map'})
r = requests.put(f'http://127.0.0.1:{port}', data = data)
geo_data = json.loads(r.text)
@ -233,7 +255,7 @@ def run(map_config):
sy = s_height / m_height
# Resize, rotate and save the screenshot
screenshot.resize((int(sx * screenshot.width), int(sy * screenshot.height))).rotate(math.degrees(geo_data['northRotation'])).save(os.path.join(output_directory, "screenshots", f"{f}_{n}.jpg"), quality=95)
screenshot.resize((int(sx * screenshot.width), int(sy * screenshot.height))).rotate(math.degrees(geo_data['northRotation'])).save(os.path.join(output_directory, "screenshots", f"{f}_{n}_{zoom}.jpg"), quality=95)
printProgressBar(n + 1, len(screenshots_XY))
n += 1