Chapter 20: Capstone Project — Full AMR Autonomy
Lesson 5: Final Demo + Research-Style Writeup
This lesson formalizes the final AMR capstone demonstration as a reproducible experiment. We define mission-level metrics, derive paired statistical comparisons, organize a research-style report, and provide multi-language evaluation code for Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica.
1. Why the Final Demo Must Be Measured
A capstone demo is not only a live navigation run; it is a quantitative claim about reliability, safety, efficiency, and map/estimation quality. Let \( \theta \) denote the full AMR stack configuration (sensor calibration, localization parameters, planner gains, safety thresholds), and let \( \mathcal{S} \) denote a scenario distribution (maps, starts/goals, obstacle scripts, and random seeds).
\[ \mathbf{z}_j(\theta) = \big(\text{trajectory}, \text{events}, \text{compute logs}, \text{energy}, \text{map}\big), \qquad \mathbf{m}_j = \mathbf{m}\!\left(\mathbf{z}_j(\theta)\right) \in \mathbb{R}^{q} \]
The final report should compare a baseline stack \( \theta_B \) and an improved stack \( \theta_P \) under paired trials (same scenario and same seed). For metric \( k \), define the paired difference \( d_j^{(k)} \):
\[ d_j^{(k)} = m_j^{(k)}(\theta_P) - m_j^{(k)}(\theta_B), \qquad \bar{d}^{(k)} = \frac{1}{N}\sum_{j=1}^{N} d_j^{(k)}. \]
This paired design reduces nuisance variation because both systems face the same realization of the environment.
2. Experimental Protocol for the Capstone Demo
A rigorous protocol for the final AMR demonstration is: freeze software versions, freeze calibration files, define a scenario matrix, pre-register metrics and failure criteria, run paired trials, then analyze logs offline. This is the same logic used in benchmarking and ablation studies.
flowchart TD
A["Freeze versions and calibration"] --> B["Define scenarios and random seeds"]
B --> C["Pre-register metrics and pass/fail criteria"]
C --> D["Run paired trials: baseline vs proposed"]
D --> E["Extract episode metrics from logs"]
E --> F["Compute CIs, paired deltas, ablation tables"]
F --> G["Write report and archive reproducibility bundle"]
For binary mission success \( Y_j \in \{0,1\} \), the sample success rate is \( \hat{p} = \frac{1}{N}\sum_{j=1}^{N}Y_j \). A robust finite-sample interval uses the Wilson form:
\[ \hat{p}_W = \frac{\hat{p} + \frac{z^2}{2N}}{1+\frac{z^2}{N}}, \qquad h_W = \frac{z}{1+\frac{z^2}{N}}\sqrt{\frac{\hat{p}(1-\hat{p})}{N}+\frac{z^2}{4N^2}}, \qquad \text{CI}_{1-\alpha} = [\hat{p}_W-h_W,\; \hat{p}_W+h_W] \]
where \( z = z_{1-\alpha/2} \) and \( 0 < \alpha < 1 \).
3. Core Metrics for Final Evaluation
Use a balanced metric set that reflects the full AMR autonomy stack:
- \( p_{\text{succ}} \): mission success rate
- \( T \): mission time (s)
- \( \eta \): path efficiency
- \( e_{xy}^{\mathrm{rms}} \): translational RMS error
- \( d_{\min} \): minimum obstacle clearance
- \( C \): collisions / collision-free rate
- \( \ell \): control/perception latency (mean or p95)
- \( E/L \): energy per traveled meter
- \( \mathrm{IoU}_{\mathrm{map}} \): map overlap quality
If a synchronized reference trajectory \( (x_r(t_n),y_r(t_n)) \) exists, then
\[ e_{xy}^{\mathrm{rms}} = \sqrt{\frac{1}{M}\sum_{n=1}^{M} \left((x(t_n)-x_r(t_n))^2 + (y(t_n)-y_r(t_n))^2\right)}. \]
Path efficiency is \( \eta = \frac{L^\star}{L} \), where \( L^\star \) is the reference feasible path length and \( L \) is the executed path length:
\[ \eta = \frac{L^\star}{L}, \qquad 0 < \eta \le 1. \]
Proof sketch. Since \( L^\star \) is chosen as a shortest feasible path length, every feasible executed path must satisfy \( L^\star \le L \). Divide by \( L > 0 \) to obtain \( \eta \le 1 \), and positivity follows because path lengths are positive for nontrivial missions. □
4. Paired Statistics and Confidence Intervals
For a continuous metric, the paired mean difference estimator is \( \bar{d} = \frac{1}{N}\sum_{j=1}^{N}(X_j-Y_j) \), where \( X_j \) and \( Y_j \) are proposed and baseline values in the same paired trial.
Proposition. If paired samples are iid and integrable, then \( \mathbb{E}[\bar{d}] = \mathbb{E}[X_1-Y_1] \).
Proof. By linearity of expectation, \( \mathbb{E}[\bar{d}] = \frac{1}{N}\sum_{j=1}^{N}\mathbb{E}[X_j-Y_j] \). Under identical distribution, every term equals \( \mathbb{E}[X_1-Y_1] \). □
A normal-approximation confidence interval is
\[ \bar{d} \pm z_{1-\alpha/2}\frac{s_d}{\sqrt{N}}, \qquad s_d^2 = \frac{1}{N-1}\sum_{j=1}^{N}(d_j-\bar{d})^2. \]
For non-Gaussian metrics (e.g., latencies with spikes), bootstrap percentile intervals are often more stable:
\[ \text{CI}_{1-\alpha}^{\text{boot}} = \left[Q_{\alpha/2}\!\left(\{\bar{m}^{\ast(b)}\}_{b=1}^{B}\right),\; Q_{1-\alpha/2}\!\left(\{\bar{m}^{\ast(b)}\}_{b=1}^{B}\right)\right]. \]
5. Composite Score for a Single Headline Result
To summarize many metrics in one value, normalize each feature and compute a weighted sum. Let \( f_{j,r} \) be feature \( r \) for trial \( j \), with pooled mean \( \mu_r \) and standard deviation \( \sigma_r \).
\[ z_{j,r} = \frac{f_{j,r}-\mu_r}{\sigma_r}, \qquad S_j = \sum_{r=1}^{R} w_r z_{j,r}, \qquad \sum_{r=1}^{R} w_r = 1,\; w_r \ge 0. \]
For lower-is-better metrics (time, latency, collisions, energy/meter), define the feature with a negative sign before z-normalization.
Affine invariance proof. If \( f' = af+b \) with \( a > 0 \), then \( \mu' = a\mu+b \) and \( \sigma' = a\sigma \), so \( \frac{f'-\mu'}{\sigma'} = \frac{f-\mu}{\sigma} \). Thus z-scores do not depend on metric units. □
6. Research-Style Writeup Structure
A compact but strong final report should include:
- Abstract (problem, method, quantitative result)
- System Setup (robot, sensors, compute, software versions)
- Methods (localization, mapping, navigation stack details)
- Experimental Design (scenarios, seeds, metrics, paired protocol)
- Results (tables, confidence intervals, ablation study)
- Failure Analysis (taxonomy of localization loss, deadlock, latency spikes)
- Reproducibility Package (code, configs, maps, logs, manifest)
flowchart TD
A["Logs + trajectories + events"] --> B["Episode metrics"]
B --> C["Paired statistics and CIs"]
C --> D["Tables and composite score"]
D --> E["Failure taxonomy"]
E --> F["Final report sections"]
F --> G["Archive code, params, logs, seeds"]
7. Python Implementation — Chapter20_Lesson5.py
Python is ideal for offline AMR evaluation pipelines using
numpy, pandas, and ROS/ROS2 log parsers. The
script below computes aggregate metrics, paired CIs, a bootstrap CI for
success rate, and a composite score.
\
# Chapter20_Lesson5.py
# AMR Capstone final demo evaluation + research-style summary (Python)
import math
import random
# Each run: [success, time_s, path_m, ref_m, rms_xy_m, clearance_m, collisions, latency_ms, energy_wh, map_iou]
baseline = [
[1,118.2,28.1,22.0,0.19,0.24,1,31.2,24.8,0.72],
[1,104.3,24.9,20.0,0.17,0.28,0,28.7,20.1,0.79],
[0,138.8,30.4,23.0,0.31,0.12,2,39.1,28.5,0.58],
[1,96.5,22.7,19.0,0.13,0.35,0,24.6,18.4,0.82],
[1,110.1,26.8,21.0,0.22,0.21,1,33.8,23.7,0.74],
]
proposed = [
[1,91.4,24.0,22.0,0.11,0.31,0,22.3,21.2,0.84],
[1,86.0,21.8,20.0,0.10,0.34,0,20.4,18.8,0.87],
[1,104.2,25.6,23.0,0.16,0.22,1,24.9,22.1,0.76],
[1,80.9,20.5,19.0,0.09,0.39,0,18.9,17.3,0.90],
[1,89.1,23.5,21.0,0.14,0.27,0,21.8,19.6,0.83],
]
def mean(xs):
return sum(xs) / len(xs)
def std(xs):
m = mean(xs)
return math.sqrt(sum((x - m) ** 2 for x in xs) / (len(xs) - 1))
def path_eff(run):
return run[3] / run[2]
def energy_per_m(run):
return run[8] / run[2]
def aggregate(runs):
return {
"success_rate": mean([r[0] for r in runs]),
"collision_free_rate": mean([1.0 if r[6] == 0 else 0.0 for r in runs]),
"time_s": mean([r[1] for r in runs]),
"path_eff": mean([path_eff(r) for r in runs]),
"rms_xy_m": mean([r[4] for r in runs]),
"clearance_m": mean([r[5] for r in runs]),
"latency_ms": mean([r[7] for r in runs]),
"energy_wh_per_m": mean([energy_per_m(r) for r in runs]),
"map_iou": mean([r[9] for r in runs]),
}
def paired_ci(prop_vals, base_vals):
d = [p - b for p, b in zip(prop_vals, base_vals)]
m = mean(d)
s = std(d)
z = 1.959963984540054
h = z * s / math.sqrt(len(d))
return (m, m - h, m + h)
def bootstrap_ci(vals, B=2000, seed=0):
rng = random.Random(seed)
boots = []
n = len(vals)
for _ in range(B):
sample = [vals[rng.randrange(n)] for _ in range(n)]
boots.append(mean(sample))
boots.sort()
return boots[int(0.025 * B)], boots[int(0.975 * B) - 1]
def zscore_features(run):
# higher-is-better transformed features
return [
run[0], # success
path_eff(run), # path efficiency
-run[1], # time
-run[4], # rms_xy
run[5], # clearance
-run[6], # collisions
-run[7], # latency
-energy_per_m(run), # energy per m
run[9], # map IoU
]
def composite_scores(base_runs, prop_runs):
all_runs = base_runs + prop_runs
F = [zscore_features(r) for r in all_runs]
cols = list(zip(*F))
mu = [mean(list(c)) for c in cols]
sd = [max(std(list(c)), 1e-12) for c in cols]
w = [0.25, 0.10, 0.12, 0.05, 0.10, 0.10, 0.08, 0.05, 0.15]
def score(run):
f = zscore_features(run)
return sum(wi * ((fi - mi) / si) for wi, fi, mi, si in zip(w, f, mu, sd))
return [score(r) for r in base_runs], [score(r) for r in prop_runs]
A = aggregate(baseline)
B = aggregate(proposed)
time_ci = paired_ci([r[1] for r in proposed], [r[1] for r in baseline])
iou_ci = paired_ci([r[9] for r in proposed], [r[9] for r in baseline])
succ_boot = bootstrap_ci([r[0] for r in proposed], seed=1)
b_scores, p_scores = composite_scores(baseline, proposed)
score_ci = paired_ci(p_scores, b_scores)
print("Baseline:", A)
print("Proposed:", B)
print("Paired delta mission time (s):", time_ci)
print("Paired delta map IoU:", iou_ci)
print("Bootstrap CI for proposed success rate:", succ_boot)
print("Paired delta composite score:", score_ci)
print("\nMarkdown row summary:")
for k in ["success_rate", "time_s", "path_eff", "rms_xy_m", "clearance_m", "latency_ms", "energy_wh_per_m", "map_iou"]:
print(f"{k}: baseline={A[k]:.4f}, proposed={B[k]:.4f}, delta={B[k]-A[k]:+.4f}")
8. C++ Implementation — Chapter20_Lesson5.cpp
This C++ version is suitable for integration in a runtime evaluator node
(e.g., ROS2 with rclcpp and CSV/ROS bag readers).
\
/* Chapter20_Lesson5.cpp
* AMR Capstone final demo evaluation + research-style summary (C++17)
*/
#include <iostream>
#include <vector>
#include <cmath>
#include <numeric>
#include <iomanip>
struct Run {
double success, time_s, path_m, ref_m, rms_xy, clearance, collisions, latency_ms, energy_wh, map_iou;
};
double mean(const std::vector<double>& x) {
return std::accumulate(x.begin(), x.end(), 0.0) / x.size();
}
double stdev(const std::vector<double>& x) {
double m = mean(x), s = 0.0;
for (double v : x) s += (v - m) * (v - m);
return std::sqrt(s / (x.size() - 1));
}
double pathEff(const Run& r) { return r.ref_m / r.path_m; }
double energyPerM(const Run& r) { return r.energy_wh / r.path_m; }
struct Agg { double succ, cfree, time, eff, rms, clr, lat, enpm, iou; };
Agg aggregate(const std::vector<Run>& runs) {
std::vector<double> succ, cfree, time, eff, rms, clr, lat, enpm, iou;
for (const auto& r : runs) {
succ.push_back(r.success);
cfree.push_back(r.collisions == 0 ? 1.0 : 0.0);
time.push_back(r.time_s); eff.push_back(pathEff(r)); rms.push_back(r.rms_xy);
clr.push_back(r.clearance); lat.push_back(r.latency_ms); enpm.push_back(energyPerM(r)); iou.push_back(r.map_iou);
}
return {mean(succ), mean(cfree), mean(time), mean(eff), mean(rms), mean(clr), mean(lat), mean(enpm), mean(iou)};
}
void pairedCI(const std::vector<double>& p, const std::vector<double>& b, double& m, double& lo, double& hi) {
std::vector<double> d(p.size());
for (size_t i = 0; i < p.size(); ++i) d[i] = p[i] - b[i];
m = mean(d);
double h = 1.959963984540054 * stdev(d) / std::sqrt((double)d.size());
lo = m - h; hi = m + h;
}
int main() {
std::vector<Run> baseline = {
{1,118.2,28.1,22.0,0.19,0.24,1,31.2,24.8,0.72},
{1,104.3,24.9,20.0,0.17,0.28,0,28.7,20.1,0.79},
{0,138.8,30.4,23.0,0.31,0.12,2,39.1,28.5,0.58},
{1,96.5,22.7,19.0,0.13,0.35,0,24.6,18.4,0.82},
{1,110.1,26.8,21.0,0.22,0.21,1,33.8,23.7,0.74}
};
std::vector<Run> proposed = {
{1,91.4,24.0,22.0,0.11,0.31,0,22.3,21.2,0.84},
{1,86.0,21.8,20.0,0.10,0.34,0,20.4,18.8,0.87},
{1,104.2,25.6,23.0,0.16,0.22,1,24.9,22.1,0.76},
{1,80.9,20.5,19.0,0.09,0.39,0,18.9,17.3,0.90},
{1,89.1,23.5,21.0,0.14,0.27,0,21.8,19.6,0.83}
};
Agg A = aggregate(baseline), B = aggregate(proposed);
std::vector<double> tB, tP, iB, iP;
for (size_t i = 0; i < baseline.size(); ++i) {
tB.push_back(baseline[i].time_s); tP.push_back(proposed[i].time_s);
iB.push_back(baseline[i].map_iou); iP.push_back(proposed[i].map_iou);
}
double md, lo, hi;
pairedCI(tP, tB, md, lo, hi);
std::cout << std::fixed << std::setprecision(4);
std::cout << "Baseline success=" << A.succ << ", proposed success=" << B.succ << "\n";
std::cout << "Baseline time=" << A.time << ", proposed time=" << B.time << "\n";
std::cout << "Baseline eff=" << A.eff << ", proposed eff=" << B.eff << "\n";
std::cout << "Baseline IoU=" << A.iou << ", proposed IoU=" << B.iou << "\n";
std::cout << "Paired delta time (proposed-baseline): " << md << " [" << lo << ", " << hi << "]\n";
pairedCI(iP, iB, md, lo, hi);
std::cout << "Paired delta IoU (proposed-baseline): " << md << " [" << lo << ", " << hi << "]\n";
return 0;
}
9. Java Implementation — Chapter20_Lesson5.java
Java is useful for offline analytics or dashboard backends; the same metric logic can be connected to CSV/JSON pipelines.
\
/* Chapter20_Lesson5.java
* AMR Capstone final demo evaluation + research-style summary (Java 17)
*/
import java.util.*;
public class Chapter20_Lesson5 {
static class Run {
double success, time, path, ref, rms, clr, col, lat, en, iou;
Run(double success, double time, double path, double ref, double rms, double clr, double col, double lat, double en, double iou) {
this.success = success; this.time = time; this.path = path; this.ref = ref; this.rms = rms;
this.clr = clr; this.col = col; this.lat = lat; this.en = en; this.iou = iou;
}
}
static double mean(double[] x) { double s = 0; for (double v : x) s += v; return s / x.length; }
static double stdev(double[] x) { double m = mean(x), s = 0; for (double v : x) s += (v - m)*(v - m); return Math.sqrt(s/(x.length-1)); }
static double eff(Run r) { return r.ref / r.path; }
static double enpm(Run r) { return r.en / r.path; }
static class Agg { double succ, cfree, time, eff, rms, clr, lat, enpm, iou; }
static Agg aggregate(List<Run> runs) {
int n = runs.size();
double[] succ = new double[n], cfree = new double[n], time = new double[n], ef = new double[n];
double[] rms = new double[n], clr = new double[n], lat = new double[n], enpm = new double[n], iou = new double[n];
for (int i = 0; i < n; i++) {
Run r = runs.get(i);
succ[i]=r.success; cfree[i]=(r.col==0?1:0); time[i]=r.time; ef[i]=eff(r); rms[i]=r.rms;
clr[i]=r.clr; lat[i]=r.lat; enpm[i]=enpm(r); iou[i]=r.iou;
}
Agg a = new Agg();
a.succ = mean(succ); a.cfree = mean(cfree); a.time = mean(time); a.eff = mean(ef);
a.rms = mean(rms); a.clr = mean(clr); a.lat = mean(lat); a.enpm = mean(enpm); a.iou = mean(iou);
return a;
}
static double[] pairedCI(double[] p, double[] b) {
double[] d = new double[p.length];
for (int i = 0; i < p.length; i++) d[i] = p[i] - b[i];
double m = mean(d);
double h = 1.959963984540054 * stdev(d) / Math.sqrt(d.length);
return new double[]{m, m-h, m+h};
}
public static void main(String[] args) {
List<Run> baseline = Arrays.asList(
new Run(1,118.2,28.1,22.0,0.19,0.24,1,31.2,24.8,0.72),
new Run(1,104.3,24.9,20.0,0.17,0.28,0,28.7,20.1,0.79),
new Run(0,138.8,30.4,23.0,0.31,0.12,2,39.1,28.5,0.58),
new Run(1,96.5,22.7,19.0,0.13,0.35,0,24.6,18.4,0.82),
new Run(1,110.1,26.8,21.0,0.22,0.21,1,33.8,23.7,0.74)
);
List<Run> proposed = Arrays.asList(
new Run(1,91.4,24.0,22.0,0.11,0.31,0,22.3,21.2,0.84),
new Run(1,86.0,21.8,20.0,0.10,0.34,0,20.4,18.8,0.87),
new Run(1,104.2,25.6,23.0,0.16,0.22,1,24.9,22.1,0.76),
new Run(1,80.9,20.5,19.0,0.09,0.39,0,18.9,17.3,0.90),
new Run(1,89.1,23.5,21.0,0.14,0.27,0,21.8,19.6,0.83)
);
Agg A = aggregate(baseline), B = aggregate(proposed);
double[] tB = baseline.stream().mapToDouble(r -> r.time).toArray();
double[] tP = proposed.stream().mapToDouble(r -> r.time).toArray();
double[] iB = baseline.stream().mapToDouble(r -> r.iou).toArray();
double[] iP = proposed.stream().mapToDouble(r -> r.iou).toArray();
double[] ciTime = pairedCI(tP, tB);
double[] ciIoU = pairedCI(iP, iB);
System.out.printf(Locale.US, "Baseline success=%.4f, proposed success=%.4f%n", A.succ, B.succ);
System.out.printf(Locale.US, "Baseline time=%.4f, proposed time=%.4f%n", A.time, B.time);
System.out.printf(Locale.US, "Baseline eff=%.4f, proposed eff=%.4f%n", A.eff, B.eff);
System.out.printf(Locale.US, "Baseline IoU=%.4f, proposed IoU=%.4f%n", A.iou, B.iou);
System.out.printf(Locale.US, "Paired delta time: %.4f [%.4f, %.4f]%n", ciTime[0], ciTime[1], ciTime[2]);
System.out.printf(Locale.US, "Paired delta IoU: %.4f [%.4f, %.4f]%n", ciIoU[0], ciIoU[1], ciIoU[2]);
}
}
10. MATLAB / Simulink Implementation — Chapter20_Lesson5.m
For Simulink-centric workflows, export telemetry after each run and use this MATLAB script for post-run capstone statistics.
\
% Chapter20_Lesson5.m
% AMR Capstone final demo evaluation + research-style summary (MATLAB / Simulink)
clear; clc;
% [success, time_s, path_m, ref_m, rms_xy_m, clearance_m, collisions, latency_ms, energy_wh, map_iou]
B = [
1 118.2 28.1 22.0 0.19 0.24 1 31.2 24.8 0.72;
1 104.3 24.9 20.0 0.17 0.28 0 28.7 20.1 0.79;
0 138.8 30.4 23.0 0.31 0.12 2 39.1 28.5 0.58;
1 96.5 22.7 19.0 0.13 0.35 0 24.6 18.4 0.82;
1 110.1 26.8 21.0 0.22 0.21 1 33.8 23.7 0.74
];
P = [
1 91.4 24.0 22.0 0.11 0.31 0 22.3 21.2 0.84;
1 86.0 21.8 20.0 0.10 0.34 0 20.4 18.8 0.87;
1 104.2 25.6 23.0 0.16 0.22 1 24.9 22.1 0.76;
1 80.9 20.5 19.0 0.09 0.39 0 18.9 17.3 0.90;
1 89.1 23.5 21.0 0.14 0.27 0 21.8 19.6 0.83
];
AB = aggregateMetrics(B);
AP = aggregateMetrics(P);
disp(AB); disp(AP);
ciTime = pairedCI(P(:,2) - B(:,2));
ciIoU = pairedCI(P(:,10) - B(:,10));
fprintf('Paired delta time: %.4f [%.4f, %.4f]\n', ciTime(1), ciTime(2), ciTime(3));
fprintf('Paired delta IoU : %.4f [%.4f, %.4f]\n', ciIoU(1), ciIoU(2), ciIoU(3));
% Simulink integration note:
% Export timeseries logs -> episode summary table -> run this script to compute final report metrics.
function A = aggregateMetrics(M)
eff = M(:,4) ./ M(:,3);
enpm = M(:,9) ./ M(:,3);
A = struct();
A.success_rate = mean(M(:,1));
A.collision_free_rate = mean(M(:,7) == 0);
A.time_s = mean(M(:,2));
A.path_eff = mean(eff);
A.rms_xy_m = mean(M(:,5));
A.clearance_m = mean(M(:,6));
A.latency_ms = mean(M(:,8));
A.energy_wh_per_m = mean(enpm);
A.map_iou = mean(M(:,10));
end
function ci = pairedCI(d)
m = mean(d);
s = std(d, 0);
h = 1.959963984540054 * s / sqrt(numel(d));
ci = [m, m - h, m + h];
end
11. Wolfram Mathematica Implementation — Chapter20_Lesson5.nb
Wolfram Language is convenient for notebook-based symbolic and numeric analysis of the final experiment summary.
\
(* Chapter20_Lesson5.nb
AMR Capstone final demo evaluation + research-style summary (Wolfram Language) *)
baseline = {
<|"succ" -> 1, "time" -> 118.2, "path" -> 28.1, "ref" -> 22.0, "rms" -> 0.19, "clr" -> 0.24, "col" -> 1, "lat" -> 31.2, "en" -> 24.8, "iou" -> 0.72|>,
<|"succ" -> 1, "time" -> 104.3, "path" -> 24.9, "ref" -> 20.0, "rms" -> 0.17, "clr" -> 0.28, "col" -> 0, "lat" -> 28.7, "en" -> 20.1, "iou" -> 0.79|>,
<|"succ" -> 0, "time" -> 138.8, "path" -> 30.4, "ref" -> 23.0, "rms" -> 0.31, "clr" -> 0.12, "col" -> 2, "lat" -> 39.1, "en" -> 28.5, "iou" -> 0.58|>,
<|"succ" -> 1, "time" -> 96.5, "path" -> 22.7, "ref" -> 19.0, "rms" -> 0.13, "clr" -> 0.35, "col" -> 0, "lat" -> 24.6, "en" -> 18.4, "iou" -> 0.82|>,
<|"succ" -> 1, "time" -> 110.1, "path" -> 26.8, "ref" -> 21.0, "rms" -> 0.22, "clr" -> 0.21, "col" -> 1, "lat" -> 33.8, "en" -> 23.7, "iou" -> 0.74|>
};
proposed = {
<|"succ" -> 1, "time" -> 91.4, "path" -> 24.0, "ref" -> 22.0, "rms" -> 0.11, "clr" -> 0.31, "col" -> 0, "lat" -> 22.3, "en" -> 21.2, "iou" -> 0.84|>,
<|"succ" -> 1, "time" -> 86.0, "path" -> 21.8, "ref" -> 20.0, "rms" -> 0.10, "clr" -> 0.34, "col" -> 0, "lat" -> 20.4, "en" -> 18.8, "iou" -> 0.87|>,
<|"succ" -> 1, "time" -> 104.2, "path" -> 25.6, "ref" -> 23.0, "rms" -> 0.16, "clr" -> 0.22, "col" -> 1, "lat" -> 24.9, "en" -> 22.1, "iou" -> 0.76|>,
<|"succ" -> 1, "time" -> 80.9, "path" -> 20.5, "ref" -> 19.0, "rms" -> 0.09, "clr" -> 0.39, "col" -> 0, "lat" -> 18.9, "en" -> 17.3, "iou" -> 0.90|>,
<|"succ" -> 1, "time" -> 89.1, "path" -> 23.5, "ref" -> 21.0, "rms" -> 0.14, "clr" -> 0.27, "col" -> 0, "lat" -> 21.8, "en" -> 19.6, "iou" -> 0.83|>
};
pathEff[e_] := e["ref"]/e["path"];
enPerM[e_] := e["en"]/e["path"];
aggregate[eps_] := <|
"successRate" -> Mean[eps[[All, "succ"]]],
"collisionFreeRate" -> Mean[Boole[eps[[All, "col"]] == 0]],
"timeS" -> Mean[eps[[All, "time"]]],
"pathEff" -> Mean[pathEff /@ eps],
"rmsXY" -> Mean[eps[[All, "rms"]]],
"clearance" -> Mean[eps[[All, "clr"]]],
"latencyMs" -> Mean[eps[[All, "lat"]]],
"energyPerM" -> Mean[enPerM /@ eps],
"mapIoU" -> Mean[eps[[All, "iou"]]]
|>;
pairedCI[d_List] := Module[{m = Mean[d], s = StandardDeviation[d], h},
h = 1.959963984540054 s/Sqrt[Length[d]];
<|"mean" -> m, "lo" -> m - h, "hi" -> m + h|>
];
Print["Baseline: ", aggregate[baseline]];
Print["Proposed: ", aggregate[proposed]];
Print["Paired delta time: ", pairedCI[proposed[[All, "time"]] - baseline[[All, "time"]]]];
Print["Paired delta IoU: ", pairedCI[proposed[[All, "iou"]] - baseline[[All, "iou"]]]];
12. Problems and Solutions
Problem 1 (Paired mission-time CI): Suppose \( N=25 \) paired trials yield \( \bar{d}=-8.4 \) s and \( s_d=6.0 \) s for mission time. Compute the 95% normal-approximation CI.
Solution:
\[ \bar{d} \pm 1.96\frac{s_d}{\sqrt{N}} = -8.4 \pm 1.96\frac{6}{5} = -8.4 \pm 2.352 \]
\[ \text{CI}_{0.95} = [-10.752,\; -6.048]\;\text{s}. \]
Problem 2 (Wilson center): In \( N=40 \) runs, the robot succeeds 34 times. With \( z=1.96 \), compute the Wilson center \( \hat{p}_W \).
Solution: Here \( \hat{p}=34/40=0.85 \), \( z^2 \approx 3.8416 \).
\[ \hat{p}_W = \frac{0.85 + \frac{3.8416}{80}}{1 + \frac{3.8416}{40}} = \frac{0.89802}{1.09604} \approx 0.8193. \]
Problem 3 (Path efficiency): If the reference path length is \( L^\star = 18.5 \) m and the executed path length is \( L = 22.2 \) m, compute \( \eta \) and interpret the result.
Solution:
\[ \eta = \frac{18.5}{22.2} \approx 0.8333. \]
The robot traveled about 20% longer than the reference path; this may be acceptable if it improved safety or robustness.
Problem 4 (Composite score contribution): A trial has z-features \( z_{\text{succ}}=0.8 \), \( z_{\text{eff}}=0.4 \), \( z_{\text{time}}=0.6 \), \( z_{\text{iou}}=1.1 \), with weights \( 0.25, 0.10, 0.12, 0.15 \) respectively. Compute the partial score.
Solution:
\[ S_{\text{partial}} = 0.25(0.8)+0.10(0.4)+0.12(0.6)+0.15(1.1) = 0.20+0.04+0.072+0.165 = 0.477. \]
13. Summary
The capstone final demo becomes academically valid when it is repeatable, metric-driven, and statistically analyzed. This lesson provided the mathematical and implementation tools needed to produce a strong final demonstration and a research-style writeup suitable for course assessment or a project portfolio.
14. References
- Thrun, S., Burgard, W., & Fox, D. (2005). Probabilistic Robotics. MIT Press.
- Grisetti, G., Kümmerle, R., Stachniss, C., & Burgard, W. (2010). A tutorial on graph-based SLAM. IEEE ITS Magazine, 2(4), 31–43.
- Fox, D., Burgard, W., & Thrun, S. (1997). The dynamic window approach to collision avoidance. IEEE Robotics & Automation Magazine, 4(1), 23–33.
- Macenski, S., Singh, S., Martin, F., & Gines, J. (2020). The Nav2 project. IROS, 10295–10300.
- Geiger, A., Lenz, P., & Urtasun, R. (2012). KITTI benchmark suite. CVPR, 3354–3361.
- Sturm, J., Engelhard, N., Endres, F., Burgard, W., & Cremers, D. (2012). RGB-D SLAM benchmark. IROS, 573–580.
- Berrar, D. (2019). Confidence intervals for performance estimates. Encyclopedia of Bioinformatics and Computational Biology, 403–412.
- Efron, B., & Tibshirani, R. (1993). An Introduction to the Bootstrap. Chapman & Hall.