Add initial plotting
This commit is contained in:
parent
2db5d14202
commit
55295b84aa
10 changed files with 362 additions and 436 deletions
24
src/lib/mathutil.ts
Normal file
24
src/lib/mathutil.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
export function distHaversine(
|
||||
p1: { lat: number; lng: number },
|
||||
p2: { lat: number; lng: number },
|
||||
precision?: number
|
||||
): string {
|
||||
const R = 6371; // Earth's mean radius in km
|
||||
|
||||
const rad = (x: number): number => (x * Math.PI) / 180;
|
||||
|
||||
const dLat = rad(p2.lat - p1.lat);
|
||||
const dLong = rad(p2.lng - p1.lng);
|
||||
|
||||
const a =
|
||||
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
||||
Math.cos(rad(p1.lat)) *
|
||||
Math.cos(rad(p2.lat)) *
|
||||
Math.sin(dLong / 2) *
|
||||
Math.sin(dLong / 2);
|
||||
|
||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
const d = R * c;
|
||||
|
||||
return d.toFixed(precision ?? 3);
|
||||
}
|
||||
198
src/lib/prediction.ts
Normal file
198
src/lib/prediction.ts
Normal file
|
|
@ -0,0 +1,198 @@
|
|||
import { writable } from "svelte/store"
|
||||
import type { LatLngExpression } from "leaflet";
|
||||
import L from "leaflet";
|
||||
|
||||
interface TrajectoryPoint {
|
||||
altitude: number;
|
||||
datetime: string;
|
||||
latitude: number;
|
||||
longitude: number;
|
||||
}
|
||||
|
||||
interface PredictionStage {
|
||||
stage: string;
|
||||
trajectory: TrajectoryPoint[];
|
||||
}
|
||||
|
||||
interface ParsedPrediction {
|
||||
flight_path: [number, number, number][];
|
||||
launch: {
|
||||
latlng: LatLngExpression;
|
||||
datetime: Date;
|
||||
};
|
||||
burst: {
|
||||
latlng: LatLngExpression;
|
||||
datetime: Date;
|
||||
};
|
||||
landing: {
|
||||
latlng: LatLngExpression;
|
||||
datetime: Date;
|
||||
};
|
||||
profile: string;
|
||||
flight_time: number;
|
||||
}
|
||||
|
||||
|
||||
export const latestPrediction = writable({
|
||||
metadata: {
|
||||
complete_datetime: "",
|
||||
start_datetime: ""
|
||||
},
|
||||
prediction: [
|
||||
{
|
||||
stage: "",
|
||||
trajectory: [
|
||||
{
|
||||
altitude: 0.0,
|
||||
datetime: "",
|
||||
latitude: 0.0,
|
||||
longitude: 0.0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
export const latestPredictionParsed = writable({} as ParsedPrediction);
|
||||
|
||||
function getLatestDataset() {
|
||||
const now = new Date();
|
||||
const hours = now.getUTCHours();
|
||||
const minutes = now.getUTCMinutes();
|
||||
const seconds = now.getUTCSeconds();
|
||||
|
||||
// Round down to the nearest 6-hour interval
|
||||
const roundedHours = Math.floor(hours / 6) * 6;
|
||||
const roundedDate = new Date(now);
|
||||
roundedDate.setUTCHours(roundedHours, 0, 0, 0);
|
||||
|
||||
// Subtract 6 hours to account for the lag
|
||||
roundedDate.setUTCHours(roundedDate.getUTCHours() - 6);
|
||||
|
||||
return roundedDate.toISOString();
|
||||
}
|
||||
|
||||
function formatLaunchDateTime(dateObj: string | Date, timeStr: string): string {
|
||||
// Ensure date is a Date object
|
||||
const date = new Date(dateObj);
|
||||
|
||||
// Extract date components
|
||||
const year = date.getFullYear();
|
||||
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||
const day = String(date.getDate()).padStart(2, '0');
|
||||
|
||||
// Format time (ensure it has seconds)
|
||||
let formattedTime = timeStr;
|
||||
if (timeStr.split(':').length === 2) {
|
||||
formattedTime += ':00'; // Add seconds if missing
|
||||
}
|
||||
|
||||
// Combine into ISO string
|
||||
const isoString = new Date(`${year}-${month}-${day}T${formattedTime}Z`).toISOString();
|
||||
|
||||
return isoString;
|
||||
}
|
||||
|
||||
export const getForecast = async (flightParameters: Record<string, any>, startDate: string, startTime: string): Promise<void> => {
|
||||
const launch_datetime = formatLaunchDateTime(startDate, startTime);
|
||||
|
||||
// Create request object
|
||||
flightParameters.dataset = getLatestDataset();
|
||||
flightParameters.launch_datetime = launch_datetime;
|
||||
|
||||
console.log("Sending request:", flightParameters);
|
||||
|
||||
try {
|
||||
// Example POST request - replace with your actual API endpoint
|
||||
const response = await fetch('http://127.0.0.1:8000/api/predictions', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(flightParameters)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log("Forecast response:", data);
|
||||
|
||||
latestPrediction.set(data.result);
|
||||
latestPredictionParsed.set(parsePrediction(data.result.prediction));
|
||||
|
||||
alert("Forecast request successful!");
|
||||
// Handle the response data as needed
|
||||
} catch (error) {
|
||||
console.error("Error sending forecast request:", error);
|
||||
alert("Error getting forecast: " + error);
|
||||
}
|
||||
};
|
||||
|
||||
export function parsePrediction(prediction: PredictionStage[]): ParsedPrediction {
|
||||
const flight_path: [number, number, number][] = [];
|
||||
const launch: { latlng: LatLngExpression; datetime: Date } = {} as any;
|
||||
const burst: { latlng: LatLngExpression; datetime: Date } = {} as any;
|
||||
const landing: { latlng: LatLngExpression; datetime: Date } = {} as any;
|
||||
|
||||
const ascent = prediction[0].trajectory;
|
||||
const descent = prediction[1].trajectory;
|
||||
|
||||
// Add the ascent track to the flight path array.
|
||||
ascent.forEach((item) => {
|
||||
let lon = item.longitude;
|
||||
if (lon > 180.0) {
|
||||
lon -= 360.0;
|
||||
}
|
||||
|
||||
flight_path.push([item.latitude, lon, item.altitude]);
|
||||
});
|
||||
|
||||
// Add the descent track to the flight path array.
|
||||
descent.forEach((item) => {
|
||||
let lon = item.longitude;
|
||||
if (lon > 180.0) {
|
||||
lon -= 360.0;
|
||||
}
|
||||
|
||||
flight_path.push([item.latitude, lon, item.altitude]);
|
||||
});
|
||||
|
||||
// Populate the launch, burst, and landing points
|
||||
const launchObj = ascent[0];
|
||||
let lon = launchObj.longitude;
|
||||
if (lon > 180.0) {
|
||||
lon -= 360.0;
|
||||
}
|
||||
launch.latlng = L.latLng([launchObj.latitude, lon, launchObj.altitude]);
|
||||
launch.datetime = new Date(launchObj.datetime);
|
||||
|
||||
const burstObj = descent[0];
|
||||
lon = burstObj.longitude;
|
||||
if (lon > 180.0) {
|
||||
lon -= 360.0;
|
||||
}
|
||||
burst.latlng = L.latLng([burstObj.latitude, lon, burstObj.altitude]);
|
||||
burst.datetime = new Date(burstObj.datetime);
|
||||
|
||||
const landingObj = descent[descent.length - 1];
|
||||
lon = landingObj.longitude;
|
||||
if (lon > 180.0) {
|
||||
lon -= 360.0;
|
||||
}
|
||||
landing.latlng = L.latLng([landingObj.latitude, lon, landingObj.altitude]);
|
||||
landing.datetime = new Date(landingObj.datetime);
|
||||
|
||||
const profile = prediction[1].stage === "descent" ? "standard_profile" : "float_profile";
|
||||
const flight_time = (new Date(landing.datetime).getTime() - new Date(launch.datetime).getTime()) / 1000;
|
||||
|
||||
return {
|
||||
flight_path,
|
||||
launch,
|
||||
burst,
|
||||
landing,
|
||||
profile,
|
||||
flight_time,
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue