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:

  1. Abstract (problem, method, quantitative result)
  2. System Setup (robot, sensors, compute, software versions)
  3. Methods (localization, mapping, navigation stack details)
  4. Experimental Design (scenarios, seeds, metrics, paired protocol)
  5. Results (tables, confidence intervals, ablation study)
  6. Failure Analysis (taxonomy of localization loss, deadlock, latency spikes)
  7. 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

  1. Thrun, S., Burgard, W., & Fox, D. (2005). Probabilistic Robotics. MIT Press.
  2. Grisetti, G., Kümmerle, R., Stachniss, C., & Burgard, W. (2010). A tutorial on graph-based SLAM. IEEE ITS Magazine, 2(4), 31–43.
  3. Fox, D., Burgard, W., & Thrun, S. (1997). The dynamic window approach to collision avoidance. IEEE Robotics & Automation Magazine, 4(1), 23–33.
  4. Macenski, S., Singh, S., Martin, F., & Gines, J. (2020). The Nav2 project. IROS, 10295–10300.
  5. Geiger, A., Lenz, P., & Urtasun, R. (2012). KITTI benchmark suite. CVPR, 3354–3361.
  6. Sturm, J., Engelhard, N., Endres, F., Burgard, W., & Cremers, D. (2012). RGB-D SLAM benchmark. IROS, 573–580.
  7. Berrar, D. (2019). Confidence intervals for performance estimates. Encyclopedia of Bioinformatics and Computational Biology, 403–412.
  8. Efron, B., & Tibshirani, R. (1993). An Introduction to the Bootstrap. Chapman & Hall.