Skip to content

Commit 008c6d7

Browse files
committed
resolve merge
2 parents efbc1a8 + 5f459bc commit 008c6d7

5 files changed

Lines changed: 139 additions & 26 deletions

File tree

data_collection/rpi5_inference/inference_config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ dry-run: False
5757

5858
data-version: 4
5959

60-
seconds-per-sample: 0.5
60+
seconds-per-sample: 0.1
6161

6262

6363
collector:

spf/data_collector.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
from typing import Any, Dict, Optional
1111

1212
import numpy as np
13-
from attr import dataclass
13+
#from attr import dataclass
14+
from dataclasses import dataclass, asdict
15+
1416
from tqdm import tqdm
1517

1618
from spf.dataset.v4_data import v4rx_2xf64_keys, v4rx_f64_keys, v4rx_new_dataset
@@ -216,7 +218,7 @@ def get_rx(self, max_retries=15) -> Dict[str, Any]:
216218
tries = 0
217219
while tries < max_retries:
218220
try:
219-
signal_matrix = self.pplus.sdr.rx()
221+
signal_matrix = self.pplus.sdr.rx() # complex128 for pluto, eventhough its 12bit TODO
220222
rssis = self.pplus.rssis()
221223
gains = self.pplus.gains()
222224
return {"signal_matrix": signal_matrix, "rssis": rssis, "gains": gains}
@@ -420,7 +422,7 @@ def write_to_record_matrix(self, thread_idx, record_idx, read_thread: ThreadedRX
420422
def run_inner_collector_thread(self):
421423
futures = []
422424
with ThreadPoolExecutorWithQueueSizeLimit(
423-
max_workers=6, maxsize=12
425+
max_workers=1, maxsize=1
424426
) as executor:
425427
for record_index in tqdm(range(self.yaml_config["n-records-per-receiver"])):
426428
for read_thread_idx, read_thread in enumerate(self.read_threads):
@@ -474,12 +476,13 @@ def close(self):
474476

475477
# V4 data format
476478
class DroneDataCollectorRaw(DataCollector):
477-
def __init__(self, *args, **kwargs):
479+
def __init__(self, realtime_v5inf, *args, **kwargs):
478480
super(DroneDataCollectorRaw, self).__init__(
479481
*args,
480482
thread_class=ThreadedRXRawV4,
481483
**kwargs,
482484
)
485+
self.realtime_v5inf=realtime_v5inf
483486

484487
def setup_record_matrix(self):
485488
if self.data_filename is not None:
@@ -511,12 +514,20 @@ def write_to_record_matrix(self, thread_idx, record_idx, data):
511514
data.gps_lat = current_pos_heading_and_time["gps"][1]
512515
data.gps_timestamp = current_pos_heading_and_time["gps_time"]
513516

517+
if self.realtime_v5inf is not None:
518+
print("WRITTING!!")
519+
data_dict=asdict(data)
520+
data_dict['signal_matrix']=data_dict['signal_matrix'].reshape(1,1,*data_dict['signal_matrix'].shape)
521+
print("KEYS IN DICT",data_dict.keys())
522+
print("SIG",data_dict['signal_matrix'].shape)
523+
self.realtime_v5inf.write_to_idx(record_idx, thread_idx, data_dict)
514524
if self.data_filename is not None:
515525
z = self.zarr[f"receivers/r{thread_idx}"]
516526
z.signal_matrix[record_idx] = data.signal_matrix
517527
for k in v4rx_f64_keys + v4rx_2xf64_keys:
518528
z[k][record_idx] = getattr(data, k) # getattr(data, k)
519529

530+
520531
def close(self):
521532
self.zarr.store.close()
522533
self.zarr = None

spf/dataset/segmentation.py

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,17 @@ def segment_session(
591591
else:
592592
# If no signal windows were identified, use placeholder values
593593
segmentation_results["weighted_windows_stats"] = np.array([-1, -1, -1])
594+
else:
595+
segmentation_results['all_windows_stats']=get_all_windows_stats(v,**kwrgs)[1]
596+
597+
# Transpose the window statistics for easier processing
598+
# all_windows_stats shape is (3, N_windows) where:
599+
# - Row 0: Trimmed circular mean of phase difference
600+
# - Row 1: Trimmed standard deviation of phase difference
601+
# - Row 2: Median absolute signal amplitude
602+
segmentation_results["all_windows_stats"] = (
603+
segmentation_results["all_windows_stats"].astype(np.float16).T
604+
)
594605

595606
# add a singleton in front of each of these
596607
segmentation_results = {
@@ -600,6 +611,32 @@ def segment_session(
600611

601612
return segmentation_results
602613

614+
def get_all_windows_stats(
615+
v,
616+
window_size,
617+
stride,
618+
trim,
619+
mean_diff_threshold,
620+
max_stddev_threshold,
621+
drop_less_than_size,
622+
min_abs_signal,
623+
steering_vectors=None, # not used but passed in
624+
):
625+
# Verify the signal matrix has the expected shape (2 antennas)
626+
assert v.ndim == 2 and v.shape[0] == 2
627+
628+
# Calculate phase differences between the two antenna elements
629+
# This gives us the phase shift that can be used to determine angle of arrival
630+
pd = get_phase_diff(v).astype(np.float32)
631+
632+
# Calculate statistics for each window:
633+
# - Trimmed circular mean of phase differences
634+
# - Trimmed standard deviation of phase differences
635+
# - Median absolute signal amplitude
636+
step_idxs, step_stats = windowed_trimmed_circular_mean_and_stddev(
637+
v, pd, window_size=window_size, stride=stride, trim=trim
638+
)
639+
return step_idxs, step_stats
603640

604641
def simple_segment(
605642
v,
@@ -658,9 +695,10 @@ def simple_segment(
658695
# - Trimmed circular mean of phase differences
659696
# - Trimmed standard deviation of phase differences
660697
# - Median absolute signal amplitude
661-
window_idxs_and_stats = windowed_trimmed_circular_mean_and_stddev(
662-
v, pd, window_size=window_size, stride=stride, trim=trim
663-
)
698+
# window_idxs_and_stats = windowed_trimmed_circular_mean_and_stddev(
699+
# v, pd, window_size=window_size, stride=stride, trim=trim
700+
# )
701+
window_idxs_and_stats = get_all_windows_stats(v=v,window_size=window_size,stride=stride,trim=trim)
664702
# window_idxs_and_stats has two components:
665703
# [0] = list of window indices (start_idx, end_idx)
666704
# [1] = array of statistics (trimmed_mean, trimmed_stddev, abs_signal_median)

spf/dataset/spf_dataset.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,6 @@ def __init__(
456456
skip_fields: List[
457457
str
458458
] = [], # Data fields to exclude during loading to save memory
459-
n_parallel: int = 20, # Number of parallel processes for segmentation
460459
empirical_data_fn: (
461460
str | None
462461
) = None, # Path to empirical distribution data file for phase-to-angle mapping
@@ -477,7 +476,6 @@ def __init__(
477476
):
478477
# Store configuration parameters
479478
self.yaml_fn = yaml_fn
480-
self.n_parallel = n_parallel
481479
self.nthetas = nthetas # Number of angles to discretize space for beamforming
482480
self.target_ntheta = self.nthetas if target_ntheta is None else target_ntheta
483481

@@ -645,14 +643,14 @@ def check_for_new_data(self):
645643

646644
def write_to_idx(self, idx, ridx, raw):
647645
# this is the heavy lifting of processing, do it on this process
648-
rendered_data = self.render_session(idx, ridx, raw)
646+
rendered_data = self.render_session(ridx, raw)
649647

650648
self.incoming_queue.put((idx, ridx, rendered_data))
651649

652650
# with self.condition:
653651
# self.condition.notify_all()
654652

655-
def render_session(self, idx, ridx, data):
653+
def render_session(self, ridx, data):
656654
snapshot_idxs = [0] # which snapshots to get
657655

658656
data["rx_wavelength_spacing"] = torch.tensor(self.rx_wavelength_spacing)
@@ -677,26 +675,29 @@ def render_session(self, idx, ridx, data):
677675

678676
if "signal_matrix" not in self.skip_fields:
679677
# WARNGING this does not respect flipping!
678+
# signal matrix ~ 1,1,2,524288
680679
abs_signal = data["signal_matrix"].abs().to(torch.float32)
681680
assert data["signal_matrix"].shape[0] == 1
682681
pd = torch_get_phase_diff(data["signal_matrix"][0]).to(torch.float32)
683682
data["abs_signal_and_phase_diff"] = torch.concatenate(
684683
[abs_signal, pd[None, :, None]], dim=2
685684
)
686685

687-
data["rx_pos_mm"] = torch.vstack(
688-
[
689-
data["rx_pos_x_mm"],
690-
data["rx_pos_y_mm"],
691-
]
692-
).T
686+
# data["rx_pos_mm"] = torch.vstack(
687+
# [
688+
# data["rx_pos_x_mm"], # size = [1]
689+
# data["rx_pos_y_mm"], # size = [1]
690+
# ]
691+
# ).T # torch.Size([1, 2])
693692

694-
data["tx_pos_mm"] = torch.vstack(
695-
[
696-
data["tx_pos_x_mm"],
697-
data["tx_pos_y_mm"],
698-
]
699-
).T
693+
# data["tx_pos_mm"] = torch.vstack(
694+
# [
695+
# data["tx_pos_x_mm"], # size = [1]
696+
# data["tx_pos_y_mm"], # size = [1]
697+
# ]
698+
# ).T # torch.Size([1, 2])
699+
700+
data["rx_pos_mm"] = data["tx_pos_mm"] = torch.ones(1, 2) * torch.nan
700701

701702
data["rx_pos_xy"] = (
702703
data["rx_pos_mm"][snapshot_idxs].unsqueeze(0) / self.distance_normalization
@@ -705,9 +706,13 @@ def render_session(self, idx, ridx, data):
705706
data["tx_pos_xy"] = (
706707
data["tx_pos_mm"][snapshot_idxs].unsqueeze(0) / self.distance_normalization
707708
)
708-
breakpoint()
709+
710+
signal_matrix = data["signal_matrix"][0][0]
711+
if isinstance(signal_matrix, torch.Tensor):
712+
signal_matrix = signal_matrix.numpy()
713+
709714
segmentation = segment_session(
710-
data["signal_matrix"][0][0].numpy(),
715+
signal_matrix,
711716
gpu=self.gpu,
712717
skip_beamformer=False,
713718
skip_detrend=self.skip_detrend,

spf/mavlink_radio_collection.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
from pymavlink import mavutil
1111

1212
from spf.data_collector import DroneDataCollectorRaw
13+
from spf.dataset.spf_dataset import v5inferencedataset,training_only_keys
14+
from spf.dataset.spf_nn_dataset_wrapper import v5spfdataset_nn_wrapper
1315
from spf.distance_finder.distance_finder_controller import DistanceFinderController
1416
from spf.gps.boundaries import boundaries # crissy_boundary_convex
1517
from spf.gps.boundaries import find_closest_boundary
@@ -18,6 +20,7 @@
1820
drone_get_planner,
1921
get_ardupilot_serial,
2022
)
23+
from spf.scripts.train_utils import load_config_from_fn
2124
from spf.utils import (
2225
DataVersionNotImplemented,
2326
filenames_from_time_in_seconds,
@@ -126,6 +129,23 @@ def parse_args():
126129
type=str,
127130
default=None,
128131
)
132+
parser.add_argument(
133+
"--checkpoint",
134+
type=str,
135+
default=None,
136+
)
137+
parser.add_argument(
138+
"--checkpoint-config",
139+
type=str,
140+
default=None,
141+
)
142+
143+
parser.add_argument(
144+
"--nthetas",
145+
type=int,
146+
help="nthetas",
147+
default=None,
148+
)
129149
parser.add_argument(
130150
"--ultrasonic",
131151
action=argparse.BooleanOptionalAction,
@@ -136,6 +156,11 @@ def parse_args():
136156
action=argparse.BooleanOptionalAction,
137157
default=False,
138158
)
159+
parser.add_argument(
160+
"--realtime",
161+
action=argparse.BooleanOptionalAction,
162+
default=False,
163+
)
139164

140165
parser.add_argument(
141166
"--inference", action=argparse.BooleanOptionalAction, default=False
@@ -234,8 +259,42 @@ def parse_args():
234259
if args.inference:
235260
pass
236261

262+
263+
if args.checkpoint:
264+
# load model config and use that theta
265+
config = load_config_from_fn(args.checkpoint_config)
266+
assert args.nthetas is None, "nthetas cannot be set when loading checkpoint"
267+
args.nthetas = config['global']['nthetas']
268+
elif args.nthetas is None:
269+
logging.warning("Setting nthetas to 65 as default")
270+
args.nthetas=65
271+
272+
if args.realtime:
273+
v5inf = v5inferencedataset(
274+
yaml_fn=temp_filenames["yaml"],
275+
nthetas=args.nthetas,
276+
gpu=False,
277+
paired=True,
278+
model_config_fn="",
279+
skip_fields=["signal_matrix"] + training_only_keys,
280+
vehicle_type="rover",
281+
skip_segmentation=True,
282+
skip_detrend=False,
283+
)
284+
nn_ds = v5spfdataset_nn_wrapper(
285+
v5inf,
286+
args.checkpoint_config,
287+
args.checkpoint,
288+
inference_cache=None,
289+
device="cpu",
290+
v4=False,
291+
absolute=True,
292+
)
293+
294+
237295
if yaml_config["data-version"] == 4:
238296
data_collector = DroneDataCollectorRaw(
297+
realtime_v5inf=v5inf if args.realtime else None,
239298
data_filename=temp_filenames["data"] if args.write_to_disk else None,
240299
yaml_config=yaml_config,
241300
position_controller=drone,

0 commit comments

Comments
 (0)