Chapter 7: Sensors in Robotics
Lesson 6: Practical Sensor Selection
This lesson builds a rigorous, quantitative framework for choosing sensors for a robot task. We translate task requirements into measurable sensor specifications, derive constraints from noise, resolution, and sampling theory, and formalize trade-offs via multi-criteria optimization. The goal is to make sensor choice a defensible engineering decision rather than intuition.
1. From task to specifications
A robotic task induces a required information set about the robot and its environment. Let \( \mathbf{x}(t) \in \mathbb{R}^n \) be the task-relevant state (e.g., pose, velocity, contact wrench). A sensor provides measurements \( \mathbf{y}(t) \in \mathbb{R}^m \) modeled as
\[ \mathbf{y}(t)=\mathbf{h}(\mathbf{x}(t))+\mathbf{v}(t), \]
where \( \mathbf{h} \) is the sensing map and \( \mathbf{v}(t) \) is measurement noise (Lesson 5). Selecting a sensor means ensuring that \( \mathbf{x} \) can be recovered with adequate accuracy and timeliness.
We convert a task into numerical specifications by defining an error tolerance \( \varepsilon_{\max} \) and a latency bound \( T_{\max} \). For an estimator \( \hat{\mathbf{x}} \) based on sensor data:
\[ \mathbb{E}\big[\lVert \hat{\mathbf{x}}(t)-\mathbf{x}(t)\rVert^2\big] \le \varepsilon_{\max}^2, \qquad \text{and} \qquad \Delta t_{\text{sense}} \le T_{\max}. \]
Sensor specs (range, resolution, sampling rate, noise density, drift, etc.) are then chosen to satisfy these inequalities.
flowchart TD
A["Task description"] --> B["State variables needed x(t)"]
B --> C["Accuracy bound eps_max, latency bound T_max"]
C --> D["Translate to specs: range, res, fs, noise, drift"]
D --> E["Generate candidate sensors"]
E --> F["Check hard constraints"]
F -->|pass| G["Rank by objective score / Pareto"]
F -->|fail| H["Reject or redesign task"]
G --> I["Prototype + validate"]
2. Hard constraints: range, bandwidth, and aliasing
Some requirements are non-negotiable. Suppose the robot must measure a scalar signal \( x(t) \) whose frequency content is concentrated below a bandwidth \( B \) Hz (from task dynamics). If sampled at rate \( f_s \), Nyquist requires
\[ f_s \ge 2B. \]
Proof sketch: Let the continuous-time Fourier transform be \( X(f) \) with support in \( |f| \le B \). Sampling multiplies \( x(t) \) by a Dirac comb, yielding spectral replicas spaced by \( f_s \). If \( f_s < 2B \), replicas overlap, making distinct frequencies indistinguishable, so perfect reconstruction is impossible. Therefore any feasible sensor must satisfy \( f_s \ge 2B \).
Range constraint: If a sensor saturates outside \( [x_{\min},x_{\max}] \), then task feasibility requires
\[ \min_t x(t)\ge x_{\min}, \qquad \max_t x(t)\le x_{\max}. \]
Given a predicted task envelope \( x(t)\in[\underline{x},\overline{x}] \), a necessary condition is \( [\underline{x},\overline{x}] \subseteq [x_{\min},x_{\max}] \).
Dynamic range: A sensor with quantization step \( \Delta \) and range \( R=x_{\max}-x_{\min} \) has \( N=R/\Delta \) bins and effective bit depth \( b=\log_2 N \). If the task needs minimum distinguishable change \( \delta_x \), then \( \Delta \le \delta_x \).
3. Accuracy constraints from noise and resolution
In Lesson 5, we modeled noise as zero-mean with covariance \( \mathbf{R}=\mathbb{E}[\mathbf{v}\mathbf{v}^\top] \). For local linearization around an operating point:
\[ \mathbf{y}\approx \mathbf{h}(\mathbf{x}_0)+\mathbf{H}(\mathbf{x}-\mathbf{x}_0)+\mathbf{v}, \quad \mathbf{H}=\frac{\partial \mathbf{h}}{\partial \mathbf{x}}\bigg|_{\mathbf{x}_0}. \]
If \( \mathbf{H} \) has full column rank, a least-squares estimate is \( \hat{\mathbf{x}}=\mathbf{x}_0+(\mathbf{H}^\top\mathbf{H})^{-1}\mathbf{H}^\top(\mathbf{y}-\mathbf{h}(\mathbf{x}_0)) \), giving estimation covariance:
\[ \mathbf{P} =\mathbb{E}\big[(\hat{\mathbf{x}}-\mathbf{x})(\hat{\mathbf{x}}-\mathbf{x})^\top\big] =(\mathbf{H}^\top\mathbf{H})^{-1}\mathbf{H}^\top\mathbf{R}\mathbf{H}(\mathbf{H}^\top\mathbf{H})^{-1}. \]
A sensor is acceptable only if the induced \( \mathbf{P} \) meets \( \operatorname{tr}(\mathbf{P}) \le \varepsilon_{\max}^2 \).
Quantization noise: If quantization error is uniform on \( [-\Delta/2,\Delta/2] \), then
\[ \sigma_q^2 = \frac{\Delta^2}{12}. \]
Thus total noise variance for a scalar measurement becomes \( \sigma_{\text{tot}}^2 = \sigma_v^2 + \Delta^2/12 \). If a task uses a derived quantity \( z=g(y) \) with scalar Jacobian \( g'(y_0) \), error propagation yields
\[ \sigma_z^2 \approx \big(g'(y_0)\big)^2 \sigma_{\text{tot}}^2. \]
This formula lets you predict whether resolution upgrades are worth the cost.
4. Multi-criteria decision: constrained optimization
After filtering with hard constraints, we rank feasible sensors by optimizing a weighted objective. Let each candidate sensor \( s \) have attributes: accuracy \( a(s) \), latency \( \ell(s) \), power \( p(s) \), mass \( m(s) \), cost \( c(s) \). We normalize each attribute to \( \tilde{a},\tilde{\ell},\dots \in [0,1] \).
\[ \min_{s \in \mathcal{S}} J(s) = w_a \tilde{a}(s) + w_\ell \tilde{\ell}(s) + w_p \tilde{p}(s) + w_m \tilde{m}(s) + w_c \tilde{c}(s), \quad \text{s.t. hard constraints hold}. \]
The weights \( w_i \ge 0 \) satisfy \( \sum_i w_i = 1 \) and encode task priorities. Varying weights traces a Pareto set, revealing trade-offs.
Dominance: Sensor \( s_1 \) dominates \( s_2 \) if all attributes are no worse and at least one is better. Dominated sensors can be discarded:
\[ s_1 \prec s_2 \ \Longleftrightarrow\ \tilde{q}_i(s_1)\le \tilde{q}_i(s_2)\ \forall i \ \text{and}\ \exists j:\tilde{q}_j(s_1)<\tilde{q}_j(s_2). \]
This is the basis for Pareto-optimal selection without introducing advanced estimation topics.
5. Practical selection examples (within Chapter 7 scope)
We now apply the framework to sensor types introduced in Lessons 1–4.
5.1 Wheel odometry encoder choice
A wheel encoder with \( N \) counts/rev on wheel radius \( r \) produces distance quantization \( \Delta d = 2\pi r/N \). If maximum acceptable distance error per sample is \( \delta_d \), the constraint is \( 2\pi r/N \le \delta_d \Rightarrow N \ge 2\pi r/\delta_d \).
5.2 IMU sampling and noise
For angular velocity \( \omega(t) \) with bandwidth \( B_\omega \), need \( f_s \ge 2B_\omega \). If gyro noise density is \( n_g \) (rad/s/√Hz), then for bandwidth \( B_\omega \),
\[ \sigma_\omega^2 \approx n_g^2 B_\omega. \]
This must be compatible with the task tolerance via Section 3.
5.3 Range sensor for obstacle distance
If a range sensor has standard deviation that grows with distance \( \sigma_r(d)=\alpha d+\beta \) (datasheet fit), and the robot must keep distance error under \( \delta_r \) up to maximum operating distance \( d_{\max} \), then
\[ \alpha d_{\max}+\beta \le \delta_r. \]
If violated, you must change sensor class (e.g., ultrasonic to LiDAR) or reduce \( d_{\max} \).
6. Code labs: ranking candidate sensors
We implement a simple constrained, weighted-ranking selector. Candidates are evaluated with hard constraints (sampling, range, resolution), then scored by a weighted objective.
6.1 Python (NumPy)
import numpy as np
# Candidate sensors described by specs
# Each row: [range_min, range_max, fs, Delta, sigma_v, cost]
S = np.array([
[0.0, 5.0, 200.0, 0.01, 0.02, 50.0], # sensor A
[0.1, 10.0, 60.0, 0.05, 0.05, 20.0], # sensor B
[0.0, 8.0, 120.0, 0.02, 0.03, 35.0], # sensor C
])
# Task requirements
x_min_req, x_max_req = 0.0, 6.0
B = 40.0 # required bandwidth (Hz)
delta_x = 0.03 # required resolution
eps_max = 0.05 # max std dev allowed
def feasible(sensor):
rmin, rmax, fs, Delta, sigma_v, cost = sensor
# hard constraints
if not (rmin <= x_min_req and rmax >= x_max_req):
return False
if fs < 2*B:
return False
if Delta > delta_x:
return False
sigma_tot = np.sqrt(sigma_v**2 + Delta**2/12)
if sigma_tot > eps_max:
return False
return True
feasible_idx = [i for i,s in enumerate(S) if feasible(s)]
Sf = S[feasible_idx]
# Normalize attributes for scoring (lower is better)
# Attributes: sigma_tot, latency=1/fs, cost
sigma_tot = np.sqrt(Sf[:,4]**2 + Sf[:,3]**2/12)
latency = 1.0/Sf[:,2]
cost = Sf[:,5]
def normalize(v):
return (v - v.min())/(v.max()-v.min() + 1e-12)
A = np.stack([normalize(sigma_tot), normalize(latency), normalize(cost)], axis=1)
w = np.array([0.5, 0.3, 0.2]) # weights sum to 1
scores = A @ w
best_local = np.argmin(scores)
best_global = feasible_idx[best_local]
print("Feasible sensors:", feasible_idx)
print("Scores:", scores)
print("Best sensor index:", best_global)
6.2 C++ (Eigen)
#include <iostream>
#include <vector>
#include <cmath>
#include <Eigen/Dense>
struct Sensor {
double rmin, rmax, fs, Delta, sigma_v, cost;
};
int main() {
std::vector<Sensor> S = {
{0.0, 5.0, 200.0, 0.01, 0.02, 50.0},
{0.1, 10.0, 60.0, 0.05, 0.05, 20.0},
{0.0, 8.0, 120.0, 0.02, 0.03, 35.0}
};
double x_min_req = 0.0, x_max_req = 6.0;
double B = 40.0, delta_x = 0.03, eps_max = 0.05;
std::vector<int> feasible_idx;
std::vector<double> sigma_tot, latency, cost;
for (int i=0; i<(int)S.size(); ++i) {
auto s = S[i];
bool ok = (s.rmin <= x_min_req && s.rmax >= x_max_req);
ok = ok && (s.fs >= 2*B);
ok = ok && (s.Delta <= delta_x);
double stot = std::sqrt(s.sigma_v*s.sigma_v + s.Delta*s.Delta/12.0);
ok = ok && (stot <= eps_max);
if (ok) {
feasible_idx.push_back(i);
sigma_tot.push_back(stot);
latency.push_back(1.0/s.fs);
cost.push_back(s.cost);
}
}
if (feasible_idx.empty()) {
std::cout << "No feasible sensors\n";
return 0;
}
auto normalize = [](const std::vector<double>& v){
double mn = *std::min_element(v.begin(), v.end());
double mx = *std::max_element(v.begin(), v.end());
Eigen::VectorXd out(v.size());
for (int i=0;i<(int)v.size();++i)
out(i) = (v[i]-mn)/(mx-mn + 1e-12);
return out;
};
Eigen::VectorXd a1 = normalize(sigma_tot);
Eigen::VectorXd a2 = normalize(latency);
Eigen::VectorXd a3 = normalize(cost);
Eigen::MatrixXd A(a1.size(),3);
A.col(0)=a1; A.col(1)=a2; A.col(2)=a3;
Eigen::Vector3d w(0.5, 0.3, 0.2);
Eigen::VectorXd scores = A*w;
Eigen::Index best_local;
scores.minCoeff(&best_local);
int best_global = feasible_idx[(int)best_local];
std::cout << "Best sensor index: " << best_global << "\n";
return 0;
}
6.3 Java
import java.util.*;
import static java.lang.Math.*;
class Sensor {
double rmin, rmax, fs, Delta, sigmaV, cost;
Sensor(double rmin,double rmax,double fs,double Delta,double sigmaV,double cost){
this.rmin=rmin; this.rmax=rmax; this.fs=fs; this.Delta=Delta; this.sigmaV=sigmaV; this.cost=cost;
}
}
public class SensorSelection {
static double[] normalize(double[] v){
double mn=Arrays.stream(v).min().getAsDouble();
double mx=Arrays.stream(v).max().getAsDouble();
double[] out=new double[v.length];
for(int i=0;i<v.length;i++) out[i]=(v[i]-mn)/(mx-mn+1e-12);
return out;
}
public static void main(String[] args){
List<Sensor> S=List.of(
new Sensor(0.0,5.0,200.0,0.01,0.02,50.0),
new Sensor(0.1,10.0,60.0,0.05,0.05,20.0),
new Sensor(0.0,8.0,120.0,0.02,0.03,35.0)
);
double xMinReq=0.0, xMaxReq=6.0, B=40.0, deltaX=0.03, epsMax=0.05;
List<Integer> feasibleIdx=new ArrayList<>();
List<Double> sigmaTot=new ArrayList<>();
List<Double> latency=new ArrayList<>();
List<Double> cost=new ArrayList<>();
for(int i=0;i<S.size();i++){
Sensor s=S.get(i);
boolean ok = (s.rmin <= xMinReq && s.rmax >= xMaxReq);
ok = ok && (s.fs >= 2*B);
ok = ok && (s.Delta <= deltaX);
double stot = sqrt(s.sigmaV*s.sigmaV + s.Delta*s.Delta/12.0);
ok = ok && (stot <= epsMax);
if(ok){
feasibleIdx.add(i);
sigmaTot.add(stot);
latency.add(1.0/s.fs);
cost.add(s.cost);
}
}
if(feasibleIdx.isEmpty()){
System.out.println("No feasible sensors");
return;
}
double[] a1=sigmaTot.stream().mapToDouble(d->d).toArray();
double[] a2=latency.stream().mapToDouble(d->d).toArray();
double[] a3=cost.stream().mapToDouble(d->d).toArray();
a1=normalize(a1); a2=normalize(a2); a3=normalize(a3);
double[] w={0.5,0.3,0.2};
double bestScore=Double.POSITIVE_INFINITY;
int bestGlobal=-1;
for(int k=0;k<feasibleIdx.size();k++){
double score=w[0]*a1[k]+w[1]*a2[k]+w[2]*a3[k];
if(score<bestScore){
bestScore=score;
bestGlobal=feasibleIdx.get(k);
}
}
System.out.println("Best sensor index: "+bestGlobal);
}
}
6.4 MATLAB / Simulink
% Candidate sensors: [rmin rmax fs Delta sigma_v cost]
S = [ ...
0.0 5.0 200.0 0.01 0.02 50.0;
0.1 10.0 60.0 0.05 0.05 20.0;
0.0 8.0 120.0 0.02 0.03 35.0 ];
x_min_req = 0.0; x_max_req = 6.0;
B = 40.0; delta_x = 0.03; eps_max = 0.05;
feasible = true(size(S,1),1);
for i=1:size(S,1)
rmin=S(i,1); rmax=S(i,2); fs=S(i,3);
Delta=S(i,4); sigma_v=S(i,5);
stot = sqrt(sigma_v^2 + Delta^2/12);
feasible(i) = (rmin<=x_min_req) && (rmax>=x_max_req) ...
&& (fs>=2*B) && (Delta<=delta_x) && (stot<=eps_max);
end
Sf = S(feasible,:);
if isempty(Sf)
disp('No feasible sensors'); return;
end
sigma_tot = sqrt(Sf(:,5).^2 + Sf(:,4).^2/12);
latency = 1./Sf(:,3);
cost = Sf(:,6);
normalize = @(v) (v-min(v))./(max(v)-min(v)+1e-12);
A = [normalize(sigma_tot), normalize(latency), normalize(cost)];
w = [0.5 0.3 0.2]; % weights
scores = A*w';
[~,best_local] = min(scores);
best_global = find(feasible);
best_global = best_global(best_local);
disp('Best sensor index:'); disp(best_global);
% Simulink note:
% Create a subsystem "Candidate Sensor" with blocks:
% Gain for H, Band-Limited White Noise for v(t), and Zero-Order Hold for sampling.
% Use MATLAB Function block to compute feasible() and scores online.
7. Problems and Solutions
Problem 1 (Sampling feasibility): A robot must measure a vibration signal with bandwidth \( B=75 \) Hz. Two sensors have maximum rates \( f_{s,1}=120 \) Hz and \( f_{s,2}=200 \) Hz. Which sensors can be used without aliasing?
Solution: Nyquist requires \( f_s\ge 2B=150 \) Hz. Sensor 1 fails (\(120<150\)), Sensor 2 passes.
Problem 2 (Encoder resolution): A wheel has radius \( r=0.08 \) m. The task requires distance resolution better than \( \delta_d=1 \) mm per sample. Find the minimum counts/revolution \( N \).
Solution: \( \Delta d=2\pi r/N \le 0.001 \) gives
\[ N \ge \frac{2\pi(0.08)}{0.001} \approx 502.65. \]
So choose \( N\ge 503 \) counts/rev (practically, 512 or 1024).
Problem 3 (Total noise bound): A range sensor has intrinsic noise \( \sigma_v=0.03 \) m and quantization step \( \Delta=0.04 \) m. The task requires \( \sigma_{\text{tot}}\le 0.05 \) m. Is the sensor feasible?
Solution: \( \sigma_q^2=\Delta^2/12=0.0016/12\approx 1.333\cdot 10^{-4} \), so \( \sigma_q\approx 0.01155 \) m. Thus
\[ \sigma_{\text{tot}}=\sqrt{0.03^2+0.01155^2} \approx \sqrt{0.0009+0.000133} \approx 0.0321\ \text{m}. \]
Since \( 0.0321<0.05 \), it passes.
Problem 4 (Dominance pruning): Three feasible sensors have normalized attributes \( \tilde{q}(s_1)=(0.2,0.6,0.5) \), \( \tilde{q}(s_2)=(0.3,0.5,0.6) \), \( \tilde{q}(s_3)=(0.2,0.4,0.5) \), where components are (accuracy, latency, cost) and lower is better. Which sensors are dominated?
Solution: Compare \( s_3 \) to \( s_1 \): accuracy equal (0.2), latency better (0.4<0.6), cost equal (0.5). So \( s_3 \prec s_1 \) and \( s_1 \) is dominated. Neither \( s_2 \) nor \( s_3 \) dominates the other.
Problem 5 (Weight sensitivity): Two feasible sensors have normalized attributes: \( \tilde{q}(A)=(0.1,0.8,0.6) \), \( \tilde{q}(B)=(0.3,0.3,0.2) \). Find all weights \( w_a,w_\ell,w_c \ge 0 \), \( w_a+w_\ell+w_c=1 \) for which A is preferred.
Solution: Prefer A when \( J(A)\le J(B) \):
\[ 0.1w_a+0.8w_\ell+0.6w_c \le 0.3w_a+0.3w_\ell+0.2w_c. \]
Rearranging: \( -0.2w_a+0.5w_\ell+0.4w_c \le 0 \), or \( 0.5w_\ell+0.4w_c \le 0.2w_a \). Since \( w_a=1-w_\ell-w_c \), substitute:
\[ 0.5w_\ell+0.4w_c \le 0.2(1-w_\ell-w_c) \Rightarrow 0.7w_\ell+0.6w_c \le 0.2. \]
Any weights in the simplex satisfying \( 0.7w_\ell+0.6w_c \le 0.2 \) make A preferred (meaning accuracy must be strongly prioritized).
8. Summary
Practical sensor selection is a pipeline: (i) derive task bounds on accuracy and timeliness; (ii) enforce hard constraints from range, Nyquist sampling, and resolution; (iii) predict performance via noise+quantization propagation; and (iv) rank feasible candidates through multi-criteria optimization or Pareto dominance. This makes sensor choice traceable and justifiable in robot design.
9. References
- Shannon, C.E. (1949). Communication in the presence of noise. Proceedings of the IRE, 37(1), 10–21.
- Whittaker, E.T. (1915). On the functions which are represented by the expansions of interpolation theory. Proceedings of the Royal Society of Edinburgh, 35, 181–194.
- Nyquist, H. (1928). Certain topics in telegraph transmission theory. Transactions of the AIEE, 47, 617–644.
- Kay, S.M. (1993). Fundamentals of statistical signal processing: estimation theory (selected chapters). Journal-level foundational contributions.
- Zadeh, L.A. (1963). Optimality and non-scalar-valued performance criteria. IEEE Transactions on Automatic Control, 8(1), 59–60.
- Deb, K. (2001). Multi-objective optimization using evolutionary algorithms (theoretical foundations). IEEE Transactions on Evolutionary Computation, 6(2), 182–197.
- Cramér, H. (1946). Mathematical methods of statistics (Cramér–Rao bound foundations). Annals of Mathematical Statistics, 17(2), 199–204.