47 Commits

Author SHA1 Message Date
bdc31ccad5 plot script fixes 2026-03-04 23:06:06 -08:00
d5c7f4f11f finalized plotting utility 2026-03-04 22:32:39 -08:00
110ff87c57 type error fix 2026-03-04 21:27:51 -08:00
51e7533369 added radio plotting tools 2026-03-04 21:22:33 -08:00
3fd4462f11 plotting update 2026-03-04 18:42:17 -08:00
12b6e79f1e fixed GPS log out path 2026-03-04 18:21:39 -08:00
e801018d9c radio experiment TDM working 2026-03-04 17:26:50 -08:00
d5307f63e9 seems to line up well again, constrainMotion updates 2026-03-03 20:14:55 -08:00
ac52e0414d scenario update, quadprog issue 2026-03-03 19:32:13 -08:00
f140b55a63 obstacle respected now 2026-03-03 18:53:19 -08:00
6b5d33962b obstacles in but ignored 2026-03-03 16:42:15 -08:00
8ebeda3bf0 scenario - obstacle - one around, one over 2026-03-03 16:22:13 -08:00
fe7b1b2ed3 per-UAV parameters 2026-03-03 16:18:07 -08:00
252423eb29 moved reader out of miSim, went to event-based guidance 2026-03-03 15:53:22 -08:00
351a9bd16f removed prompt to continue 2026-03-03 15:22:10 -08:00
2b853466f2 results compare favorably 2026-03-02 19:06:45 -08:00
d49bf61d1d scenario edits 2026-03-02 18:18:40 -08:00
032f50774f improved globe plotting 2026-03-02 16:15:03 -08:00
e40d2e4614 moved origin to get more space from geofence 2026-03-02 12:15:01 -08:00
387d6aea56 scenario csv on both platforms 2026-02-28 19:36:58 -08:00
0bf293c95e added slack in collision avoidance constraint 2026-02-27 16:06:10 -08:00
db6df5f263 csv parse update 2026-02-25 11:44:59 -08:00
d89fa38ba1 testing fixes 2026-02-25 11:02:56 -08:00
c2fa2b524a added constraint violation recovery mechanism 2026-02-24 19:30:14 -08:00
bb97502be5 codegen fixes, bug fixes, gets running on testbed environment 2026-02-24 19:05:54 -08:00
fb9feac23d gps log plotting 2026-02-16 11:19:10 -08:00
fd6ebf538c aerpaw gps csv reader 2026-02-15 21:50:13 -08:00
a328eae126 gps logging updates 2026-02-15 17:29:14 -08:00
c060dfad06 respect geofence, move from socket to async/await 2026-02-13 18:55:07 -08:00
05bf99f061 more config cleanup 2026-02-13 18:16:27 -08:00
77ac58a8a2 config cleanup 2026-02-13 18:06:06 -08:00
525d213e6a project cleanup 2026-02-07 14:36:53 -08:00
f434e1a685 logging consistency 2026-02-02 12:16:13 -08:00
330c1e5d54 message type updates 2026-02-01 16:02:18 -08:00
f6e1f13bb5 removed potentially faulty environment detection in favor of explicit setting 2026-02-01 11:34:35 -08:00
79b03345ba refactor experiment config 2026-02-01 11:08:04 -08:00
a965dff4ca added parallel message receiving for previously implemented messaging where necessary 2026-01-30 18:28:19 -08:00
448db1e0e3 added RTL and LAND capabilities 2026-01-30 18:16:33 -08:00
dd82cb3956 kinda working 2026-01-30 15:56:00 -08:00
6b8e26eb69 added real autopilot connection info 2026-01-29 22:07:53 -08:00
654de7c2a1 allowed connection to real autopilot 2026-01-29 21:11:45 -08:00
338bb6c340 added aerpawlib capabilities to uav script 2026-01-29 20:56:54 -08:00
6604928f8f reorganized and added aerpawlib submodule 2026-01-29 20:08:51 -08:00
aed1924297 sending starting positions to agents (not verified on AERPAW yet) 2026-01-29 16:42:19 -08:00
fe106f31cd cleanup demo 2026-01-28 23:20:11 -08:00
8c5c315380 basic implementation of client/server for AERPAW, whole lot of mess included 2026-01-28 22:29:17 -08:00
b444e44d33 experiment setup 2026-01-28 15:47:09 -08:00
10 changed files with 17 additions and 175 deletions

3
.gitmodules vendored
View File

@@ -0,0 +1,3 @@
[submodule "aerpaw/aerpawlib"]
path = aerpaw/aerpawlib
url = https://github.com/morzack/aerpawlib-vehicle-control.git

1
aerpaw/aerpawlib Submodule

Submodule aerpaw/aerpawlib added at 705fc699ef

View File

@@ -267,10 +267,6 @@ class CSwSNRRX(gr.top_block):
'/root/Quality', num_uavs, slot_duration, guard_interval) '/root/Quality', num_uavs, slot_duration, guard_interval)
self.blocks_file_sink_0 = TdmTaggedFileSink( self.blocks_file_sink_0 = TdmTaggedFileSink(
'/root/Power', num_uavs, slot_duration, guard_interval) '/root/Power', num_uavs, slot_duration, guard_interval)
self.blocks_file_sink_noisefloor = TdmTaggedFileSink(
'/root/NoiseFloor', num_uavs, slot_duration, guard_interval)
self._freqoffset_file = open('/root/FreqOffset', 'w')
self._freqoffset_file.write('tx_uav_id,value\n')
self.blocks_divide_xx_0 = blocks.divide_ff(1) self.blocks_divide_xx_0 = blocks.divide_ff(1)
self.blocks_complex_to_real_0_0 = blocks.complex_to_real(1) self.blocks_complex_to_real_0_0 = blocks.complex_to_real(1)
self.blocks_complex_to_real_0 = blocks.complex_to_real(1) self.blocks_complex_to_real_0 = blocks.complex_to_real(1)
@@ -314,7 +310,6 @@ class CSwSNRRX(gr.top_block):
self.connect((self.blocks_nlog10_ff_0_0, 0), (self.blocks_add_const_vxx_0, 0)) self.connect((self.blocks_nlog10_ff_0_0, 0), (self.blocks_add_const_vxx_0, 0))
self.connect((self.blocks_nlog10_ff_0_0, 0), (self.blocks_sub_xx_0, 0)) self.connect((self.blocks_nlog10_ff_0_0, 0), (self.blocks_sub_xx_0, 0))
self.connect((self.blocks_nlog10_ff_0_0_0, 0), (self.blocks_sub_xx_0, 1)) self.connect((self.blocks_nlog10_ff_0_0_0, 0), (self.blocks_sub_xx_0, 1))
self.connect((self.blocks_nlog10_ff_0_0_0, 0), (self.blocks_file_sink_noisefloor, 0))
self.connect((self.blocks_stream_to_vector_0_0, 0), (self.epy_block_0, 0)) self.connect((self.blocks_stream_to_vector_0_0, 0), (self.epy_block_0, 0))
self.connect((self.blocks_sub_xx_0, 0), (self.blocks_file_sink_0_0_0, 0)) self.connect((self.blocks_sub_xx_0, 0), (self.blocks_file_sink_0_0_0, 0))
self.connect((self.blocks_vector_to_stream_0_0, 0), (self.blocks_keep_m_in_n_0, 0)) self.connect((self.blocks_vector_to_stream_0_0, 0), (self.blocks_keep_m_in_n_0, 0))
@@ -326,26 +321,6 @@ class CSwSNRRX(gr.top_block):
self.connect((self.freq_xlating_fft_filter_ccc_0_0, 0), (self.blocks_stream_to_vector_0_0, 0)) self.connect((self.freq_xlating_fft_filter_ccc_0_0, 0), (self.blocks_stream_to_vector_0_0, 0))
self.connect((self.uhd_usrp_source_0, 0), (self.blocks_multiply_xx_0, 0)) self.connect((self.uhd_usrp_source_0, 0), (self.blocks_multiply_xx_0, 0))
##################################################
# Frequency offset polling thread
##################################################
def _freq_offset_probe():
frame_dur = slot_duration * num_uavs
while True:
val = self.digital_fll_band_edge_cc_0_0.get_frequency()
freq_hz = val * samp_rate / (2 * math.pi)
now = time.time()
slot_time = now % frame_dur
current_slot = int(slot_time / slot_duration)
time_into_slot = slot_time - current_slot * slot_duration
tx_id = -1 if time_into_slot < guard_interval else current_slot
self._freqoffset_file.write(f'{tx_id},{freq_hz}\n')
self._freqoffset_file.flush()
time.sleep(0.01)
_freq_offset_thread = threading.Thread(target=_freq_offset_probe)
_freq_offset_thread.daemon = True
_freq_offset_thread.start()
def get_args(self): def get_args(self):
return self.args return self.args

View File

@@ -24,25 +24,16 @@ function [f, R] = plotRadioLogs(resultsPath)
R{ii}(bad, :) = []; R{ii}(bad, :) = [];
end end
% Compute path loss from Power (post-processing)
% Power = 20*log10(peak_mag) - rxGain; path loss = txGain - rxGain - Power
txGain_dB = 76; % from startchannelsounderTXGRC.sh GAIN_TX
rxGain_dB = 30; % from startchannelsounderRXGRC.sh GAIN_RX
for ii = 1:numel(R)
R{ii}.PathLoss = txGain_dB - rxGain_dB - R{ii}.Power;
R{ii}.FreqOffset = R{ii}.FreqOffset / 1e6; % Hz to MHz
end
% Build legend labels and color map for up to 4 UAVs % Build legend labels and color map for up to 4 UAVs
nUAV = numel(R); nUAV = numel(R);
colors = lines(nUAV * nUAV); colors = lines(nUAV * nUAV);
styles = ["-o", "-s", "-^", "-d", "-v", "-p", "-h", "-<", "->", "-+", "-x", "-*"]; styles = ["-o", "-s", "-^", "-d", "-v", "-p", "-h", "-<", "->", "-+", "-x", "-*"];
metricNames = ["SNR", "Power", "Quality", "PathLoss", "NoiseFloor", "FreqOffset"]; metricNames = ["SNR", "Power", "Quality"];
yLabels = ["SNR (dB)", "Power (dB)", "Quality", "Path Loss (dB)", "Noise Floor (dB)", "Freq Offset (MHz)"]; yLabels = ["SNR (dB)", "Power (dB)", "Quality"];
f = figure; f = figure;
tl = tiledlayout(numel(metricNames), 1, 'TileSpacing', 'compact', 'Padding', 'compact'); tl = tiledlayout(3, 1, 'TileSpacing', 'compact', 'Padding', 'compact');
for mi = 1:numel(metricNames) for mi = 1:numel(metricNames)
ax = nexttile(tl); ax = nexttile(tl);

View File

@@ -4,19 +4,19 @@ function R = readRadioLogs(logPath)
end end
arguments (Output) arguments (Output)
R (:, 8) table; R (:, 6) table;
end end
% Extract receiving UAV ID from directory name (e.g. "uav0_..." 0) % Extract receiving UAV ID from directory name (e.g. "uav0_..." 0)
[~, dirName] = fileparts(logPath); [~, dirName] = fileparts(logPath);
rxID = int32(sscanf(dirName, 'uav%d')); rxID = int32(sscanf(dirName, 'uav%d'));
metrics = ["quality", "snr", "power", "noisefloor", "freqoffset"]; metrics = ["quality", "snr", "power"];
logs = dir(logPath); logs = dir(logPath);
logs = logs(endsWith({logs(:).name}, metrics + "_log.txt")); logs = logs(endsWith({logs(:).name}, metrics + "_log.txt"));
R = table(datetime.empty(0,1), zeros(0,1,'int32'), zeros(0,1,'int32'), zeros(0,1), zeros(0,1), zeros(0,1), zeros(0,1), zeros(0,1), ... R = table(datetime.empty(0,1), zeros(0,1,'int32'), zeros(0,1,'int32'), zeros(0,1), zeros(0,1), zeros(0,1), ...
'VariableNames', ["Timestamp", "TxUAVID", "RxUAVID", "SNR", "Power", "Quality", "NoiseFloor", "FreqOffset"]); 'VariableNames', ["Timestamp", "TxUAVID", "RxUAVID", "SNR", "Power", "Quality"]);
for ii = 1:numel(logs) for ii = 1:numel(logs)
filepath = fullfile(logs(ii).folder, logs(ii).name); filepath = fullfile(logs(ii).folder, logs(ii).name);
@@ -43,15 +43,13 @@ function R = readRadioLogs(logPath)
val = data{3}; val = data{3};
n = numel(ts); n = numel(ts);
t = table(ts, txId, repmat(rxID, n, 1), NaN(n,1), NaN(n,1), NaN(n,1), NaN(n,1), NaN(n,1), ... t = table(ts, txId, repmat(rxID, n, 1), NaN(n,1), NaN(n,1), NaN(n,1), ...
'VariableNames', ["Timestamp", "TxUAVID", "RxUAVID", "SNR", "Power", "Quality", "NoiseFloor", "FreqOffset"]); 'VariableNames', ["Timestamp", "TxUAVID", "RxUAVID", "SNR", "Power", "Quality"]);
switch metric switch metric
case "snr", t.SNR = val; case "snr", t.SNR = val;
case "power", t.Power = val; case "power", t.Power = val;
case "quality", t.Quality = val; case "quality", t.Quality = val;
case "noisefloor", t.NoiseFloor = val;
case "freqoffset", t.FreqOffset = val;
end end
R = [R; t]; %#ok<AGROW> R = [R; t]; %#ok<AGROW>

View File

@@ -1,5 +1,5 @@
%% Plot AERPAW logs (trajectory, radio) %% Plot AERPAW logs (trajectory, radio)
resultsPath = fullfile(matlab.project.rootProject().RootFolder, "sandbox", "t2"); % Define path to results copied from AERPAW platform resultsPath = fullfile(matlab.project.rootProject().RootFolder, "sandbox", "t1"); % Define path to results copied from AERPAW platform
% Plot GPS logged data and scenario information (domain, objective, obstacles) % Plot GPS logged data and scenario information (domain, objective, obstacles)
seaToGroundLevel = 110; % measured approximately from USGS national map viewer seaToGroundLevel = 110; % measured approximately from USGS national map viewer

View File

@@ -1,43 +0,0 @@
#!/bin/bash
#RX
cd $PROFILE_DIR"/ProfileScripts/Radio/Helpers"
screen -S rxGRC -dm \
bash -c "stdbuf -oL -eL ./startchannelsounderRXGRC.sh \
2>&1 | ts $TS_FORMAT \
| tee $RESULTS_DIR/$LOG_PREFIX\_radio_channelsounderrxgrc_log.txt"
screen -S power -dm \
bash -c "stdbuf -oL -eL tail -F /root/Power\
2>&1 | ts $TS_FORMAT \
| tee $RESULTS_DIR/$LOG_PREFIX\_power_log.txt"
screen -S quality -dm \
bash -c "stdbuf -oL -eL tail -F /root/Quality\
2>&1 | ts $TS_FORMAT \
| tee $RESULTS_DIR/$LOG_PREFIX\_quality_log.txt"
screen -S snr -dm \
bash -c "stdbuf -oL -eL tail -F /root/SNR\
2>&1 | ts $TS_FORMAT \
| tee $RESULTS_DIR/$LOG_PREFIX\_snr_log.txt"
screen -S noisefloor -dm \
bash -c "stdbuf -oL -eL tail -F /root/NoiseFloor\
2>&1 | ts $TS_FORMAT \
| tee $RESULTS_DIR/$LOG_PREFIX\_noisefloor_log.txt"
screen -S freqoffset -dm \
bash -c "stdbuf -oL -eL tail -F /root/FreqOffset\
2>&1 | ts $TS_FORMAT \
| tee $RESULTS_DIR/$LOG_PREFIX\_freqoffset_log.txt"
#TX
screen -S txGRC -dm \
bash -c "stdbuf -oL -eL ./startchannelsounderTXGRC.sh \
2>&1 | ts $TS_FORMAT \
| tee $RESULTS_DIR/$LOG_PREFIX\_radio_channelsoundertxgrc_log.txt"
cd -

View File

@@ -1,30 +0,0 @@
#!/bin/bash
### Sample GPS logger portion
# use vehicle type generic to skip the arming requirement
export VEHICLE_TYPE="${VEHICLE_TYPE:-generic}"
# GPS Logger sample application (this does not move the vehicle)
#cd $PROFILE_DIR"/ProfileScripts/Vehicle/Helpers"
#
#screen -S vehicle -dm \
# bash -c "stdbuf -oL -eL ./gpsLoggerHelper.sh \
# 2> >(ts $TS_FORMAT >> $RESULTS_DIR/${LOG_PREFIX}_vehicle_log_err.txt) \
# | ts $TS_FORMAT \
# | tee $RESULTS_DIR/$LOG_PREFIX\_vehicle_log.txt"
#
#cd -
### Actual control portion (custom)
export VEHICLE_TYPE="${VEHICLE_TYPE:-drone}" # out of rover, drone, generic
cd /root/miSim/aerpaw
# Use screen/ts/tee aerpawism from sample script
screen -S vehicle -dm \
bash -c "stdbuf -oL -eL ./run_uav.sh testbed /root/miSim/aerpaw/config/client1.yaml \
| ts $TS_FORMAT \
| tee $RESULTS_DIR/$LOG_PREFIX\_vehicle_log.txt"
cd -

View File

@@ -1,53 +0,0 @@
#!/bin/bash
/root/stopexperiment.sh
source /root/.ap-set-experiment-env.sh
source /root/.bashrc
# set path to client config YAML
export AERPAW_CLIENT_CONFIG=/root/miSim/aerpaw/config/client1.yaml
export AERPAW_REPO=${AERPAW_REPO:-/root/AERPAW-Dev}
export AERPAW_PYTHON=${AERPAW_PYTHON:-python3}
export PYTHONPATH=/usr/local/lib/python3/dist-packages/
export EXP_NUMBER=${EXP_NUMBER:-1}
if [ "$AP_EXPENV_THIS_CONTAINER_NODE_VEHICLE" == "vehicle_uav" ]; then
export VEHICLE_TYPE=drone
elif [ "$AP_EXPENV_THIS_CONTAINER_NODE_VEHICLE" == "vehicle_ugv" ]; then
export VEHICLE_TYPE=rover
else
export VEHICLE_TYPE=none
fi
if [ "$AP_EXPENV_SESSION_ENV" == "Virtual" ]; then
export LAUNCH_MODE=EMULATION
elif [ "$AP_EXPENV_SESSION_ENV" == "Testbed" ]; then
export LAUNCH_MODE=TESTBED
else
export LAUNCH_MODE=none
fi
# prepare results directory
export UAV_ID=$(python3 -c "import yaml; print(yaml.safe_load(open('$AERPAW_CLIENT_CONFIG'))['uav_id'])")
export RESULTS_DIR_TIMESTAMP=$(date +%Y-%m-%d_%H_%M_%S)
export RESULTS_DIR="/root/Results/uav${UAV_ID}_${RESULTS_DIR_TIMESTAMP}"
mkdir -p "$RESULTS_DIR"
export TS_FORMAT="${TS_FORMAT:-'[%Y-%m-%d %H:%M:%.S]'}"
export LOG_PREFIX="$(date +%Y-%m-%d_%H_%M_%S)"
export TX_FREQ=3.32e9
export RX_FREQ=3.32e9
export PROFILE_DIR=$AERPAW_REPO"/AHN/E-VM/Profile_software"
cd $PROFILE_DIR"/ProfileScripts"
./Radio/startRadio.sh
#./Traffic/startTraffic.sh
./Vehicle/startVehicle.sh
schedule_stop.sh 30

BIN
t1.zip Normal file

Binary file not shown.