Skip to content

Commit

Permalink
fix v2 collection
Browse files Browse the repository at this point in the history
  • Loading branch information
misko committed Jan 11, 2024
1 parent cb60ece commit c5ae9ae
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 113 deletions.
228 changes: 124 additions & 104 deletions spf/grbl_sdr_collect_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
from dataclasses import dataclass
from datetime import datetime

import matplotlib.pyplot as plt
import numpy as np
import yaml
from grbl.grbl_interactive import get_default_gm, stop_grbl
Expand All @@ -20,6 +19,7 @@
ReceiverConfig,
get_avg_phase,
get_pplus,
plot_recv_signal,
setup_rxtx,
setup_rxtx_and_phase_calibration,
shutdown_radios,
Expand Down Expand Up @@ -180,11 +180,22 @@ def grbl_thread_runner(gm, planner):
default=None,
required=False,
)
parser.add_argument("--plot", action="store_true")
parser.add_argument(
"-p",
"--plot",
type=int,
help="Plot an output",
default=None,
required=False,
)
args = parser.parse_args()

run_started_at = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
output_files_prefix = f"wallarrayv2_{run_started_at}"
# read YAML
with open(args.yaml_config, "r") as stream:
yaml_config = yaml.safe_load(stream)

output_files_prefix = f"wallarrayv2_{run_started_at}_nRX{len(yaml_config['receivers'])}_{yaml_config['planner']}"

# setup logging
logging.basicConfig(
Expand All @@ -196,17 +207,13 @@ def grbl_thread_runner(gm, planner):
level=getattr(logging, args.logging_level.upper(), None),
)

# read YAML
with open(args.yaml_config, "r") as stream:
yaml_config = yaml.safe_load(stream)

with open(f"{output_files_prefix}.yaml", "w") as outfile:
yaml.dump(yaml_config, outfile, default_flow_style=False)

# record matrix
column_names = v2_column_names(nthetas=yaml_config["n-thetas"])
record_matrix = np.memmap(
yaml_config["output-file"].replace("__DATE__", run_started_at),
f"{output_files_prefix}.npy",
dtype="float32",
mode="w+",
shape=(
Expand All @@ -231,67 +238,71 @@ def grbl_thread_runner(gm, planner):
receiver_pplus = []
pplus_rx, pplus_tx = (None, None)
for receiver in yaml_config["receivers"]:
rx_config = ReceiverConfig(
lo=receiver["f-carrier"],
rf_bandwidth=receiver["bandwidth"],
sample_rate=receiver["f-sampling"],
gains=[receiver["rx-gain"], receiver["rx-gain"]],
gain_control_mode=receiver["rx-gain-mode"],
if run_collection:
rx_config = ReceiverConfig(
lo=receiver["f-carrier"],
rf_bandwidth=receiver["bandwidth"],
sample_rate=receiver["f-sampling"],
gains=[receiver["rx-gain"], receiver["rx-gain"]],
gain_control_mode=receiver["rx-gain-mode"],
enabled_channels=[0, 1],
buffer_size=receiver["buffer-size"],
intermediate=receiver["f-intermediate"],
uri="ip:%s" % receiver["receiver-ip"],
rx_spacing=receiver["antenna-spacing-m"],
rx_theta_in_pis=receiver["theta-in-pis"],
motor_channel=receiver["motor_channel"],
rx_buffers=receiver["rx-buffers"],
)
tx_config = EmitterConfig(
lo=receiver["f-carrier"],
rf_bandwidth=receiver["bandwidth"],
sample_rate=receiver["f-sampling"],
intermediate=receiver["f-intermediate"],
gains=[-30, -80],
enabled_channels=[0],
cyclic=True,
uri="ip:%s" % receiver["emitter-ip"],
)
pplus_rx, pplus_tx = setup_rxtx_and_phase_calibration(
rx_config=rx_config,
tx_config=tx_config,
n_calibration_frames=yaml_config["calibration-frames"],
# leave_tx_on=False,
# using_tx_already_on=None,
)
logging.debug("RX online!")
receiver_pplus.append(pplus_rx)

if run_collection:
# setup the emitter
target_yaml_config = yaml_config["emitter"]
target_rx_config = ReceiverConfig(
lo=target_yaml_config["f-carrier"],
rf_bandwidth=target_yaml_config["bandwidth"],
sample_rate=target_yaml_config["f-sampling"],
gains=[target_yaml_config["rx-gain"], target_yaml_config["rx-gain"]],
gain_control_mode=target_yaml_config["rx-gain-mode"],
enabled_channels=[0, 1],
buffer_size=receiver["buffer-size"],
intermediate=receiver["f-intermediate"],
uri="ip:%s" % receiver["receiver-ip"],
rx_spacing=receiver["antenna-spacing-m"],
rx_theta_in_pis=receiver["theta-in-pis"],
motor_channel=receiver["motor_channel"],
rx_buffers=receiver["rx-buffers"],
buffer_size=target_yaml_config["buffer-size"],
intermediate=target_yaml_config["f-intermediate"],
uri="ip:%s" % target_yaml_config["receiver-ip"],
)
tx_config = EmitterConfig(
lo=receiver["f-carrier"],
rf_bandwidth=receiver["bandwidth"],
sample_rate=receiver["f-sampling"],
intermediate=receiver["f-intermediate"],
gains=[-30, -80],
target_tx_config = EmitterConfig(
lo=target_yaml_config["f-carrier"],
rf_bandwidth=target_yaml_config["bandwidth"],
sample_rate=target_yaml_config["f-sampling"],
intermediate=target_yaml_config["f-intermediate"],
gains=[target_yaml_config["tx-gain"], -80],
enabled_channels=[0],
cyclic=True,
uri="ip:%s" % receiver["emitter-ip"],
)
pplus_rx, pplus_tx = setup_rxtx_and_phase_calibration(
rx_config=rx_config,
tx_config=tx_config,
n_calibration_frames=800,
# leave_tx_on=False,
# using_tx_already_on=None,
uri="ip:%s" % target_yaml_config["emitter-ip"],
motor_channel=target_yaml_config["motor_channel"],
)
logging.debug("RX online!")
receiver_pplus.append(pplus_rx)

# setup the emitter
target_yaml_config = yaml_config["emitter"]
target_rx_config = ReceiverConfig(
lo=target_yaml_config["f-carrier"],
rf_bandwidth=target_yaml_config["bandwidth"],
sample_rate=target_yaml_config["f-sampling"],
gains=[target_yaml_config["rx-gain"], target_yaml_config["rx-gain"]],
gain_control_mode=target_yaml_config["rx-gain-mode"],
enabled_channels=[0, 1],
buffer_size=target_yaml_config["buffer-size"],
intermediate=target_yaml_config["f-intermediate"],
uri="ip:%s" % target_yaml_config["receiver-ip"],
)
target_tx_config = EmitterConfig(
lo=target_yaml_config["f-carrier"],
rf_bandwidth=target_yaml_config["bandwidth"],
sample_rate=target_yaml_config["f-sampling"],
intermediate=target_yaml_config["f-intermediate"],
gains=[target_yaml_config["tx-gain"], -80],
enabled_channels=[0],
cyclic=True,
uri="ip:%s" % target_yaml_config["emitter-ip"],
motor_channel=target_yaml_config["motor_channel"],
)

setup_rxtx(rx_config=target_rx_config, tx_config=target_tx_config)
setup_rxtx(
rx_config=target_rx_config, tx_config=target_tx_config, leave_tx_on=True
)

# threadA semaphore to produce fresh data
# threadB semaphore to produce fresh data
Expand All @@ -301,51 +312,60 @@ def grbl_thread_runner(gm, planner):
# setup GRBL
gm = None
gm_thread = None
if args.grbl_serial is not None:
gm = get_default_gm(args.grbl_serial)
gm_thread = threading.Thread(
target=grbl_thread_runner, args=(gm, yaml_config["planner"])
)
gm_thread.start()
if run_collection:
if args.grbl_serial is not None:
gm = get_default_gm(args.grbl_serial)
gm_thread = threading.Thread(
target=grbl_thread_runner, args=(gm, yaml_config["planner"])
)
gm_thread.start()

# setup read threads

time_offset = time.time()
read_threads = []
for pplus_rx in receiver_pplus:
read_thread = ThreadedRX(pplus_rx, time_offset, nthetas=yaml_config["n-thetas"])
read_thread.start_read_thread()
read_threads.append(read_thread)

record_index = 0
for record_index in tqdm(range(yaml_config["n-records-per-receiver"])):
if not run_collection:
logging.info("Breaking man loop early")
break
for read_thread_idx, read_thread in enumerate(read_threads):
while run_collection and not read_thread.ready_lock.acquire(timeout=0.5):
pass
###
# copy the data out

rx_pos = np.array([0, 0])
tx_pos = np.array([0, 0])
if gm is not None:
tx_pos = gm.controller.position["xy"][target_tx_config.motor_channel]
rx_pos = gm.controller.position["xy"][
read_thread.pplus.rx_config.motor_channel
]

record_matrix[read_thread_idx, record_index] = prepare_record_entry(
ds=read_thread.data, rx_pos=rx_pos, tx_pos=tx_pos
time_offset = time.time()
if run_collection:
for pplus_rx in receiver_pplus:
read_thread = ThreadedRX(
pplus_rx, time_offset, nthetas=yaml_config["n-thetas"]
)
if args.plot and record_index % 100 == 0 and read_thread_idx == 0:
plt.cla()
plt.plot(read_thread.data.beam_sds)
plt.draw()
plt.pause(0.01)
###
read_thread.read_lock.release()
read_thread.start_read_thread()
read_threads.append(read_thread)
if (
pplus_rx is not None
and args.plot is not None
and args.plot == (len(read_threads) - 1)
):
plot_recv_signal(pplus_rx)

if run_collection:
record_index = 0
for record_index in tqdm(range(yaml_config["n-records-per-receiver"])):
if not run_collection:
logging.info("Breaking man loop early")
break
for read_thread_idx, read_thread in enumerate(read_threads):
while run_collection and not read_thread.ready_lock.acquire(
timeout=0.5
):
pass
###
# copy the data out

rx_pos = np.array([0, 0])
tx_pos = np.array([0, 0])
if gm is not None:
tx_pos = gm.controller.position["xy"][
target_tx_config.motor_channel
]
rx_pos = gm.controller.position["xy"][
read_thread.pplus.rx_config.motor_channel
]

record_matrix[read_thread_idx, record_index] = prepare_record_entry(
ds=read_thread.data, rx_pos=rx_pos, tx_pos=tx_pos
)
###
read_thread.read_lock.release()
shutdown()
logging.info("Shuttingdown: sending false to threads")
for read_thread in read_threads:
Expand Down
34 changes: 25 additions & 9 deletions spf/sdrpluto/sdr_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import logging
import sys
import time
from datetime import datetime
from math import gcd
from typing import Optional

Expand Down Expand Up @@ -188,7 +189,18 @@ def check_for_freq_peak(self):
return False


class ReceiverConfig:
class Config:
def __repr__(self):
return "<{klass} @{id:x} {attrs}>".format(
klass=self.__class__.__name__,
id=id(self) & 0xFFFFFF,
attrs="\n".join(
"{}={!r}".format(k, v) for k, v in sorted(self.__dict__.items())
),
)


class ReceiverConfig(Config):
def __init__(
self,
lo: int,
Expand Down Expand Up @@ -242,7 +254,7 @@ def __init__(
self.rx_pos = None


class EmitterConfig:
class EmitterConfig(Config):
def __init__(
self,
lo: int,
Expand Down Expand Up @@ -289,7 +301,7 @@ def args_to_tx_config(args):
lo=args.fc,
rf_bandwidth=int(3 * args.fi),
sample_rate=int(args.fs),
gains=[-30, -80],
gains=[args.tx_gain, -80],
enabled_channels=[0],
cyclic=True,
intermediate=args.fi,
Expand Down Expand Up @@ -326,7 +338,6 @@ def setup_rxtx(rx_config, tx_config, leave_tx_on=False):
pplus_rx = get_pplus(rx_config=rx_config)
logging.debug(f"{tx_config.uri} RX (TX) are different")
pplus_tx = get_pplus(tx_config=tx_config)

pplus_rx.setup_rx()
pplus_tx.setup_tx()
time.sleep(0.1)
Expand All @@ -341,6 +352,9 @@ def setup_rxtx(rx_config, tx_config, leave_tx_on=False):

# test to see what frequency we are seeing
if pplus_rx.check_for_freq_peak():
logging.info(
f"RXTX came online with configs\nRX_config:{pplus_rx.rx_config}\nTX_config:{pplus_tx.tx_config}"
)
if not leave_tx_on:
pplus_tx.close_tx()
return pplus_rx, pplus_tx
Expand Down Expand Up @@ -401,6 +415,8 @@ def setup_rxtx_and_phase_calibration(
phase_calibrations = np.zeros(n_calibration_frames)
phase_calibrations_cm = np.zeros(n_calibration_frames)
for idx in range(n_calibration_frames):
if not run_radios:
break
signal_matrix = np.vstack(pplus_rx.sdr.rx())
phase_calibrations[idx] = (
(np.angle(signal_matrix[0]) - np.angle(signal_matrix[1])) % (2 * np.pi)
Expand Down Expand Up @@ -462,12 +478,12 @@ def plot_recv_signal(pplus_rx):

rx_n = pplus_rx.sdr.rx_buffer_size
t = np.arange(rx_n)
while True:
while run_radios:
signal_matrix = np.vstack(pplus_rx.sdr.rx())
signal_matrix[1] *= np.exp(1j * pplus_rx.phase_calibration)
assert pplus_rx.rx_config.rx_pos is not None
beam_thetas, beam_sds, _ = beamformer(
pplus_rx.rx_config.rx_pos, signal_matrix, args.fc
pplus_rx.rx_config.rx_pos, signal_matrix, pplus_rx.rx_config.lo
)

freq = np.fft.fftfreq(t.shape[-1], d=1.0 / pplus_rx.sdr.sample_rate)
Expand Down Expand Up @@ -591,10 +607,11 @@ def plot_recv_signal(pplus_rx):

# calibrate the receiver
# setup logging
# start_logging_at = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
run_started_at = datetime.now().strftime("%Y_%m_%d_%H_%M_%S")
output_files_prefix = f"wallarrayv2_{run_started_at}"
logging.basicConfig(
handlers=[
# logging.FileHandler(f"{start_logging_at}.log"),
logging.FileHandler(f"{output_files_prefix}.log"),
logging.StreamHandler(),
],
format="%(asctime)s:%(levelname)s:%(message)s",
Expand All @@ -620,7 +637,6 @@ def plot_recv_signal(pplus_rx):
plot_recv_signal(pplus_rx)

elif args.mode == "rx":
# sdr_rx = adi.ad9361(uri=receiver_uri)
pplus_rx = get_pplus(rx_config=args_to_rx_config(args))
pplus_rx.setup_rx()
pplus_rx.phase_calibration = args.cal0
Expand Down
Loading

0 comments on commit c5ae9ae

Please sign in to comment.