FERS 0.1.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
simulationProgressStore.ts
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-only
2// Copyright (c) 2025-present FERS Contributors (see AUTHORS.md).
3
4import { create } from 'zustand';
5
6export type SimulationProgressState = {
7 message: string;
8 current: number;
9 total: number;
10 details?: SimulationProgressDetail[];
11};
12
13export type SimulationProgressDetail = {
14 id: string;
15 message: string;
16 current: number;
17 total: number;
18};
19
20export type SimulationRunStatus = 'idle' | 'running' | 'completed' | 'failed';
21
22export type SimulationOutputMode = 'pulsed' | 'cw' | 'fmcw' | 'sfcw';
23
24export type SimulationOutputChunkMetadata = {
25 chunk_index: number;
26 i_dataset: string;
27 q_dataset: string;
28 start_time: number;
29 sample_count: number;
30 sample_start: number;
31 sample_end_exclusive: number;
32};
33
34export type SimulationOutputStreamingSegmentMetadata = {
35 start_time: number;
36 end_time: number;
37 sample_count: number;
38 sample_start: number;
39 sample_end_exclusive: number;
40 first_chirp_start_time?: number;
41 emitted_chirp_count?: number;
42 first_triangle_start_time?: number;
43 emitted_triangle_count?: number;
44 first_sfcw_step_start_time?: number;
45 emitted_sfcw_step_count?: number;
46};
47
48export type SimulationOutputFmcwMetadata = {
49 waveform_shape?: 'linear' | 'triangle' | 'file';
50 chirp_bandwidth: number;
51 chirp_duration: number;
52 chirp_rate: number;
53 start_frequency_offset: number;
54 chirp_period?: number;
55 chirp_rate_signed?: number;
56 chirp_direction?: 'up' | 'down';
57 chirp_count?: number;
58 triangle_period?: number;
59 triangle_count?: number;
60 sampled_duration?: number;
61 sampled_count?: number;
62};
63
64export type SimulationOutputFmcwSourceSegmentMetadata = {
65 start_time: number;
66 end_time: number;
67 first_chirp_start_time?: number;
68 emitted_chirp_count?: number;
69 first_triangle_start_time?: number;
70 emitted_triangle_count?: number;
71};
72
73export type SimulationOutputFmcwSourceMetadata =
74 SimulationOutputFmcwMetadata & {
75 transmitter_id: number;
76 transmitter_name: string;
77 waveform_id: number;
78 waveform_name: string;
79 carrier_frequency: number;
80 segments: SimulationOutputFmcwSourceSegmentMetadata[];
81 };
82
83export type SimulationOutputSfcwMetadata = {
84 carrier_frequency: number;
85 start_frequency_offset: number;
86 step_size: number;
87 step_count: number;
88 dwell_time: number;
89 step_period: number;
90 sweep_count?: number;
91 first_frequency: number;
92 last_frequency: number;
93 frequency_span: number;
94 effective_bandwidth: number;
95 range_resolution: number;
96 unambiguous_range: number;
97};
98
99export type SimulationOutputSfcwSourceSegmentMetadata = {
100 start_time: number;
101 end_time: number;
102 first_step_start_time?: number;
103 emitted_step_count?: number;
104};
105
106export type SimulationOutputSfcwSourceMetadata =
107 SimulationOutputSfcwMetadata & {
108 transmitter_id: number;
109 transmitter_name: string;
110 waveform_id: number;
111 waveform_name: string;
112 segments: SimulationOutputSfcwSourceSegmentMetadata[];
113 };
114
115export type SimulationOutputVita49Timestamp = {
116 integer_seconds: number;
117 fractional_picoseconds: number;
118};
119
120export type SimulationOutputVita49StreamMetadata = {
121 receiver_id: number;
122 receiver_name: string;
123 stream_id: number;
124 mode?: string;
125 sample_rate: number;
126 reference_frequency: number;
127 packets_emitted: number;
128 samples_emitted: number;
129 packets_dropped: number;
130 samples_dropped: number;
131 over_range_count: number;
132 late_data_packet_count: number;
133 late_context_packet_count: number;
134 context_packet_count: number;
135 first_sample_time: number | null;
136 end_sample_time: number | null;
137 first_timestamp: SimulationOutputVita49Timestamp | null;
138 end_timestamp: SimulationOutputVita49Timestamp | null;
139};
140
141export type SimulationOutputVita49Metadata = {
142 endpoint: string;
143 endpoint_host: string;
144 endpoint_port: number;
145 epoch_unix_nanoseconds: string | null;
146 class_id: string;
147 adc_fullscale: number;
148 max_udp_payload: number;
149 queue_depth: number;
150 streams: SimulationOutputVita49StreamMetadata[];
151};
152
153export type SimulationOutputFileMetadata = {
154 receiver_id: number;
155 receiver_name: string;
156 mode: SimulationOutputMode;
157 path: string;
158 sampling_rate: number;
159 total_samples: number;
160 sample_start: number;
161 sample_end_exclusive: number;
162 pulse_count: number;
163 min_pulse_length_samples: number;
164 max_pulse_length_samples: number;
165 uniform_pulse_length: boolean;
166 chunks: SimulationOutputChunkMetadata[];
167 streaming_segments: SimulationOutputStreamingSegmentMetadata[];
168 fmcw?: SimulationOutputFmcwMetadata;
169 fmcw_sources: SimulationOutputFmcwSourceMetadata[];
170 sfcw?: SimulationOutputSfcwMetadata;
171 sfcw_sources: SimulationOutputSfcwSourceMetadata[];
172 fmcw_dechirp_mode?: 'none' | 'physical' | 'ideal';
173 fmcw_dechirp_reference_source?:
174 | 'none'
175 | 'attached'
176 | 'transmitter'
177 | 'custom';
178 fmcw_dechirp_reference_transmitter_id?: number;
179 fmcw_dechirp_reference_transmitter_name?: string;
180 fmcw_dechirp_reference_waveform_id?: number;
181 fmcw_dechirp_reference_waveform_name?: string;
182 fmcw_dechirp_reference_waveform?: SimulationOutputFmcwMetadata;
183};
184
185export type SimulationOutputMetadata = {
186 schema_version: number;
187 simulation_name: string;
188 output_directory: string;
189 start_time: number;
190 end_time: number;
191 sampling_rate: number | null;
192 sampling_rates?: number[];
193 oversample_ratio: number;
194 files: SimulationOutputFileMetadata[];
195 vita49?: SimulationOutputVita49Metadata;
196};
197
198export type RawSimulationOutputFileMetadata = Omit<
199 SimulationOutputFileMetadata,
200 'sampling_rate' | 'streaming_segments' | 'fmcw_sources' | 'sfcw_sources'
201> & {
202 sampling_rate?: number;
203 streaming_segments?: SimulationOutputStreamingSegmentMetadata[];
204 cw_segments?: SimulationOutputStreamingSegmentMetadata[];
205 fmcw_sources?: SimulationOutputFmcwSourceMetadata[];
206 sfcw_sources?: SimulationOutputSfcwSourceMetadata[];
207};
208
209export type RawSimulationOutputMetadata = Omit<
210 SimulationOutputMetadata,
211 'files'
212> & {
213 files: RawSimulationOutputFileMetadata[];
214};
215
216export const normalizeSimulationOutputMetadata = (
217 metadata: RawSimulationOutputMetadata
218): SimulationOutputMetadata => ({
219 ...metadata,
220 files: metadata.files.map((file) => {
221 const {
222 cw_segments,
223 streaming_segments,
224 fmcw_sources,
225 sfcw_sources,
226 sampling_rate,
227 ...normalizedFile
228 } = file;
229 return {
230 ...normalizedFile,
231 sampling_rate:
232 sampling_rate ??
233 metadata.sampling_rate ??
234 metadata.sampling_rates?.[0] ??
235 0,
236 streaming_segments: streaming_segments ?? cw_segments ?? [],
237 fmcw_sources: fmcw_sources ?? [],
238 sfcw_sources: sfcw_sources ?? [],
239 };
240 }),
241});
242
243type SimulationProgressStore = {
244 isSimulating: boolean;
245 isGeneratingKml: boolean;
246 simulationProgress: Record<string, SimulationProgressState>;
247 simulationRunStatus: SimulationRunStatus;
248 simulationRunError: string | null;
249 simulationOutputMetadata: SimulationOutputMetadata | null;
250
251 setIsSimulating: (isSimulating: boolean) => void;
252 setIsGeneratingKml: (isGeneratingKml: boolean) => void;
253 startSimulationRun: () => void;
254 setSimulationProgressSnapshot: (
255 progress: Record<string, SimulationProgressState>
256 ) => void;
257 setSimulationOutputMetadata: (
258 metadata: SimulationOutputMetadata | null
259 ) => void;
260 completeSimulationRun: () => void;
261 failSimulationRun: (errorMessage: string) => void;
262 clearSimulationProgress: () => void;
263};
264
265export const useSimulationProgressStore = create<SimulationProgressStore>()(
266 (set) => ({
267 isSimulating: false,
268 isGeneratingKml: false,
269 simulationProgress: {},
270 simulationRunStatus: 'idle',
271 simulationRunError: null,
272 simulationOutputMetadata: null,
273
274 setIsSimulating: (isSimulating) => set({ isSimulating }),
275 setIsGeneratingKml: (isGeneratingKml) => set({ isGeneratingKml }),
276 startSimulationRun: () =>
277 set({
278 isSimulating: true,
279 simulationProgress: {},
280 simulationRunStatus: 'running',
281 simulationRunError: null,
282 simulationOutputMetadata: null,
283 }),
284 setSimulationProgressSnapshot: (progress) =>
285 set({ simulationProgress: progress }),
286 setSimulationOutputMetadata: (metadata) =>
287 set({ simulationOutputMetadata: metadata }),
288 completeSimulationRun: () =>
289 set({
290 isSimulating: false,
291 simulationRunStatus: 'completed',
292 simulationRunError: null,
293 }),
294 failSimulationRun: (errorMessage) =>
295 set({
296 isSimulating: false,
297 simulationRunStatus: 'failed',
298 simulationRunError: errorMessage,
299 }),
300 clearSimulationProgress: () =>
301 set({
302 simulationProgress: {},
303 simulationRunStatus: 'idle',
304 simulationRunError: null,
305 simulationOutputMetadata: null,
306 }),
307 })
308);