Chapter 10: Advanced Perception for Manipulation

Lesson 5: Active Perception for Better Manipulation

This lesson develops a rigorous Bayesian and information-theoretic view of active perception for robotic manipulation. We formalize how to choose sensor motions and exploratory actions that maximize information about task-relevant latent variables (e.g., object pose, contact state), and show how this coupling improves grasping and manipulation performance. We derive core objective functions (entropy, mutual information, Fisher information), connect them to next-best-view (NBV) planning and tactile exploration, and implement simple active perception loops in Python, C++, Java, MATLAB/Simulink, and Wolfram Mathematica.

1. What Is Active Perception in Manipulation?

In previous lessons of this chapter, perception has mostly been passive: given sensor data, we estimate 3D pose, track objects, segment the scene, and infer affordances. In active perception, the robot deliberately chooses actions (camera motions, arm motions, tactile probes) to obtain more informative observations that improve the downstream manipulation policy (grasping, placing, inserting).

Let \( x \) denote a latent state describing the scene that is relevant for manipulation, for example \( x = (T_o, \mathbf{c}) \) combining object pose \( T_o \in SE(3) \) and contact parameters \( \mathbf{c} \). Let \( a_t \) denote a sensing action at time \( t \) (e.g. moving the wrist camera), and \( z_t \) the resulting observation (image patch, depth, tactile reading). A belief at time \( t \) is a distribution \( b_t(x) = p(x \mid z_{0:t}, a_{0:t-1}) \).

An active perception policy seeks to choose actions that optimize a utility function of the future belief, typically related to information or task success:

\[ a_t^\star \in \arg\max_a \mathbb{E}\!\left[ U\!\big(b_{t+1}^z, a\big) \;\middle|\; b_t, a \right], \]

where \( b_{t+1}^z \) is the posterior belief after executing \( a \) and observing \( z \). Typical choices are:

  • Information objective: \( U(b_{t+1}^z, a) = H(b_t) - H(b_{t+1}^z) \) (expected entropy reduction).
  • Task objective: probability of success of the downstream manipulation plan under \( b_{t+1}^z \).

The overall manipulation policy then interleaves sensing and acting: repeatedly decrease uncertainty to a threshold, then commit to a grasp or insertion motion planned in the belief space (using tools from previous chapters).

flowchart TD
  S["Start manipulation task"] --> G["Set goal (e.g., stable grasp)"]
  G --> B["Initialize belief over scene state"]
  B --> A1["Choose informative sensing action"]
  A1 --> EXEC["Execute sensing motion"]
  EXEC --> Z["Acquire measurement"]
  Z --> UPD["Update belief via Bayes rule"]
  UPD --> C1["Check confidence for manipulation"]
  C1 -->|"enough confidence"| PLAN["Plan and execute manipulation"]
  C1 -->|"not enough"| A1
        

2. Bayesian Formulation of Active Perception

We reuse the belief-space concepts from Chapter 6 (planning under uncertainty). Assume the scene state \( x \) is static during sensing (no moving objects). The belief update is purely observational:

\[ b_{t+1}(x) = p(x \mid z_{t+1}, a_t, b_t) = \eta \, p(z_{t+1} \mid x, a_t) \, b_t(x), \quad \eta^{-1} = \sum_{x'} p(z_{t+1} \mid x', a_t) \, b_t(x'). \]

Here \( p(z \mid x,a) \) is the observation model of the perception system, and \( \eta \) normalizes the posterior. For continuous \( x \), the summation is replaced by an integral. The expected posterior under action \( a \) is obtained by marginalizing over possible future observations:

\[ \mathbb{E}_{z \mid a,b_t}\!\big[f(b_{t+1}^z)\big] = \sum_z \left( \sum_x p(z \mid x,a) b_t(x) \right) f\!\big(b_{t+1}^z\big), \]

where the inner sum is the predictive likelihood \( p(z \mid a, b_t) = \sum_x p(z \mid x,a) b_t(x) \). This expectation is in general intractable, and many practical active perception algorithms rely on approximations:

  • Discrete state and observation spaces.
  • Particle approximations of \( b_t \).
  • Local Gaussian approximations (extended Kalman filter view).

In a purely myopic setting (one-step lookahead), \( a_t^\star \) is chosen by evaluating this expectation for each candidate action instead of solving a full POMDP over a long horizon.

3. Information-Theoretic Objectives

A standard way to formalize informativeness is via entropy and mutual information. For a discrete belief \( b(x) \), the entropy is

\[ H(b) = -\sum_x b(x) \log b(x). \]

For an action \( a \), the expected posterior entropy is

\[ \mathbb{E}_{z \mid a,b}\big[ H(b^{z}) \big] = -\sum_z p(z \mid a,b) \sum_x b^{z}(x) \log b^{z}(x), \]

where \( b^{z} \) is the posterior belief given that observation \( z \) occurs. The expected information gain (mutual information between \( X \) and \( Z \) given action \( a \)) is

\[ I(X;Z \mid a) = H(b) - \mathbb{E}_{z \mid a,b}\big[H(b^{z})\big]. \]

Equivalently, this can be written as

\[ I(X;Z \mid a) = \sum_{x,z} p(x,z \mid a) \log \frac{ p(z \mid x,a) }{ p(z \mid a) }, \quad p(x,z \mid a) = p(z \mid x,a) b(x). \]

An information-greedy sensing policy chooses \( a_t \) as

\[ a_t^\star \in \arg\max_a I_t(X;Z \mid a). \]

This does not yet reason about motion cost or manipulation cost. A more refined criterion is to trade off information gain against sensing effort, e.g.

\[ a_t^\star \in \arg\max_a \left[ I_t(X;Z \mid a) - \lambda c(a) \right], \]

where \( c(a) \) is a geometric cost (e.g., camera motion time) and \( \lambda > 0 \) controls the trade-off.

4. Next-Best-View (NBV) for Pose Estimation

Consider estimating an object pose \( \theta \in \mathbb{R}^n \) (e.g. a 6-DOF pose parameterization). A camera attached to the manipulator can be moved to one of a finite set of viewpoints \( v \in \mathcal{V} \). Each viewpoint yields an observation \( z \) whose distribution depends on \( \theta \) and \( v \): \( p(z \mid \theta, v) \).

Given a prior belief \( b(\theta) \) and a candidate viewpoint \( v \), the expected information gain can be approximated discretely:

\[ I(\Theta;Z \mid v) = H(b) - \sum_z \left( \sum_{\theta} p(z \mid \theta,v)\, b(\theta) \right) H\!\big(b^{z,v}\big), \]

where the posterior over \( \theta \) for a specific \( z \) and \( v \) is

\[ b^{z,v}(\theta) = \frac{ p(z \mid \theta, v)\, b(\theta) }{ \sum_{\theta'} p(z \mid \theta',v)\, b(\theta') }. \]

The standard NBV problem selects \( v^\star \in \arg\max_{v \in \mathcal{V}} I(\Theta;Z \mid v) \). In practice, the sums are replaced by integrals or Monte Carlo approximations over pose samples from \( b(\theta) \).

For a locally Gaussian pose belief, we can derive a more compact expression. Suppose

\[ \theta \sim \mathcal{N}(\mu,\Sigma), \quad z = h(\theta, v) + \varepsilon, \quad \varepsilon \sim \mathcal{N}(0,R), \]

and linearize the image measurement model around \( \mu \): \( h(\theta, v) \approx h(\mu,v) + H_v (\theta - \mu) \). The posterior over \( \theta \) remains Gaussian with covariance

\[ \Sigma'(v) = \left( \Sigma^{-1} + H_v^{\top} R^{-1} H_v \right)^{-1}. \]

Using the entropy of a Gaussian, \( H(\mathcal{N}(\mu,\Sigma)) = \tfrac{1}{2} \log\!\big((2\pi e)^n \det \Sigma\big) \), the information gain from viewpoint \( v \) is

\[ \Delta H(v) = \tfrac{1}{2} \log \frac{\det \Sigma}{\det \Sigma'(v)} = \tfrac{1}{2} \log \det\!\Big( I + \Sigma H_v^{\top} R^{-1} H_v \Big). \]

Thus NBV becomes \( v^\star = \arg\max_v \Delta H(v) \), which is equivalent to maximizing a function of the Fisher information matrix \( H_v^{\top} R^{-1} H_v \). This is a classical result that connects active perception to optimal experiment design.

flowchart TD
  B["Belief over object pose"] --> CANDS["Enumerate candidate viewpoints"]
  CANDS --> LOOP["For each view: approximate expected entropy of posterior"]
  LOOP --> SEL["Select view with maximum info gain"]
  SEL --> MOVE["Move camera / wrist to chosen viewpoint"]
  MOVE --> OBS["Acquire image and update belief"]
        

5. Active Tactile and Multi-Modal Perception

Active perception is not limited to vision. Tactile and force sensing can be used to refine contact locations, surface normals, and friction parameters crucial for stable grasps. Consider a simple one-dimensional example: a planar object boundary located at an unknown position \( s^\star \in [0,1] \), with a prior \( p(s^\star) \). A probing action selects a position \( s \in [0,1] \) at which the fingertip moves into contact; the binary observation \( z \in \{0,1\} \) indicates whether contact occurs.

In an idealized noise-free case, the tactile observation is

\[ z = \mathbf{1}\{s < s^\star\}, \]

i.e. a step function that reveals whether the boundary is to the right or left of \( s \). If the prior is uniform on \( [0,1] \), the entropy-minimizing probing policy is a binary search: always place the next probe at the current posterior median. After \( k \) noiseless probes, the posterior support interval length is \( 2^{-k} \), and entropy decreases linearly in \( k \).

With noise, the observation model becomes probabilistic, e.g.

\[ p(z=1 \mid s^\star,s) = \sigma\!\big(\alpha (s^\star - s)\big), \quad \sigma(u) = \frac{1}{1+e^{-u}}, \]

and posterior updates must account for this uncertainty. The same information gain criteria as in vision can be applied, and the optimal probing sequence can deviate from exact binary search.

In multi-modal active perception (vision + touch), the joint observation model factorizes as

\[ p(z^{\text{vis}}, z^{\text{tac}} \mid x,a) = p(z^{\text{vis}} \mid x,a^{\text{vis}}) \, p(z^{\text{tac}} \mid x,a^{\text{tac}}), \]

and the posterior over \( x \) combines evidence multiplicatively. An action \( a \) now has visual and tactile components, and NBV planning must be extended to decide whether to move the camera, execute an exploratory touch, or do both.

6. Coupling Active Perception with Manipulation Planning

So far, active perception has been discussed as an independent sensing module. However, the ultimate objective is successful manipulation. A simple but powerful abstraction is to split actions into:

  • Sensing actions \( a_t^{\text{sens}} \): do not directly change the object, but move sensors (camera, wrist).
  • Manipulation actions \( a_t^{\text{man}} \): change the object (grasping, pushing, lifting).

Given a belief \( b_t \), a planned manipulation sequence \( \pi^{\text{man}} \) (e.g. a grasp from Chapter 7 and a collision-free path from Chapters 2–4) has an expected success probability

\[ P_{\text{succ}}(b_t, \pi^{\text{man}}) = \sum_x b_t(x) \mathbf{1}\{\text{plan succeeds in state } x\}. \]

Active perception aims to bring this probability above a threshold \( \rho \) before committing to execution, while minimizing sensing cost:

\[ \min_{a_0^{\text{sens}},\dots,a_{T-1}^{\text{sens}}} \sum_{t=0}^{T-1} c\big(a_t^{\text{sens}}\big) \quad \text{s.t.} \quad P_{\text{succ}}\!\big(b_T, \pi^{\text{man}}\big) \ge \rho. \]

In practice, this constraint is approximated using confidence bounds on pose and contact estimates. For example, the robot may execute sensing actions until the covariance of the estimated pose is below a given threshold in the directions most critical for the grasp wrench space (Chapter 7).

7. Python Lab — Myopic Active View Selection in 1D

We implement a toy example of active perception for a 1D "pose" \( \theta \in [-\pi, \pi] \). The robot can choose a view angle \( a \), and receives a binary observation \( z \in \{0,1\} \) saying whether a particular feature is "visible". The measurement model is

\[ p(z=1 \mid \theta,a) = \sigma\!\big(\kappa \cos(\theta - a)\big), \quad \sigma(u)=\frac{1}{1+e^{-u}}, \]

so views that align the feature with the camera optical axis tend to yield more informative readings. We discretize \( \theta \), maintain a discrete belief, and choose the view with maximal expected entropy reduction.


import numpy as np

# Discretized state space for 1D "pose"
n_theta = 360
theta_grid = np.linspace(-np.pi, np.pi, n_theta, endpoint=False)

def softplus(x):
    return np.log1p(np.exp(x))

def logistic(u):
    return 1.0 / (1.0 + np.exp(-u))

def measurement_likelihood(z, theta, a, kappa=4.0):
    """
    Binary measurement model p(z | theta, a).
    z in {0,1}, theta and a are scalars.
    """
    p1 = logistic(kappa * np.cos(theta - a))
    return p1 if z == 1 else (1.0 - p1)

def normalize(b):
    s = np.sum(b)
    if s == 0.0:
        return np.ones_like(b) / float(b.size)
    return b / s

def entropy(b):
    # Natural-log entropy; ignore zero entries
    mask = b > 0.0
    return -np.sum(b[mask] * np.log(b[mask]))

def expected_entropy_after_action(b, a, kappa=4.0):
    """
    Compute E_z[ H(b') ] under action a (myopic).
    z is binary {0,1}.
    """
    # Predictive likelihood of z
    p_z = []
    posteriors = []
    for z in [0, 1]:
        # Unnormalized posterior
        like = np.array([
            measurement_likelihood(z, th, a, kappa) for th in theta_grid
        ])
        b_unnorm = like * b
        pz = np.sum(b_unnorm)
        p_z.append(pz)
        posteriors.append(normalize(b_unnorm) if pz > 0 else b.copy())
    p_z = np.array(p_z)
    # Expected posterior entropy
    H = 0.0
    for z in [0, 1]:
        if p_z[z] > 0.0:
            H += p_z[z] * entropy(posteriors[z])
    return H

def choose_action(b, candidate_views, kappa=4.0):
    H_prior = entropy(b)
    best_a = None
    best_ig = -np.inf
    for a in candidate_views:
        H_post = expected_entropy_after_action(b, a, kappa)
        ig = H_prior - H_post
        if ig > best_ig:
            best_ig = ig
            best_a = a
    return best_a, best_ig

def update_belief(b, a, z, kappa=4.0):
    like = np.array([
        measurement_likelihood(z, th, a, kappa) for th in theta_grid
    ])
    return normalize(like * b)

# Example loop: start uniform, run a few active sensing steps
b = np.ones(n_theta) / float(n_theta)
candidate_views = np.linspace(-np.pi, np.pi, 12, endpoint=False)

# Ground-truth theta for simulation
theta_true = 0.7

rng = np.random.default_rng(0)

for t in range(6):
    a_star, ig = choose_action(b, candidate_views)
    # Simulate measurement from true state
    p1 = measurement_likelihood(1, theta_true, a_star)
    z = 1 if rng.random() < p1 else 0
    b = update_belief(b, a_star, z)
    print(f"Step {t}: a = {a_star:.2f}, z = {z}, IG = {ig:.3f}, H = {entropy(b):.3f}")
      

This code illustrates the core algorithmic pattern of NBV for simple state spaces: discretize, evaluate expected posterior entropy for each candidate action, choose the best, update the belief. Extending this to 6-DOF pose uses the same logic but more sophisticated sampling and rendering-based likelihood models.

8. C++ Snippet — View Selection with Eigen

The following C++ snippet demonstrates a similar myopic view-selection loop using Eigen for vector operations. We assume a discretized 1D state as before, and a binary observation model.


#include <iostream>
#include <vector>
#include <cmath>
#include <random>
#include <limits>
#include <Eigen/Dense>

using Eigen::VectorXd;

double logistic(double u) {
    return 1.0 / (1.0 + std::exp(-u));
}

double measurement_likelihood(int z, double theta, double a, double kappa = 4.0) {
    double p1 = logistic(kappa * std::cos(theta - a));
    return (z == 1) ? p1 : (1.0 - p1);
}

VectorXd normalize(const VectorXd &b) {
    double s = b.sum();
    if (s <= 0.0) {
        return VectorXd::Ones(b.size()) / static_cast<double>(b.size());
    }
    return b / s;
}

double entropy(const VectorXd &b) {
    double H = 0.0;
    for (int i = 0; i < b.size(); ++i) {
        double bi = b(i);
        if (bi > 0.0) {
            H -= bi * std::log(bi);
        }
    }
    return H;
}

double expected_entropy_after_action(const VectorXd &theta_grid,
                                     const VectorXd &b,
                                     double a,
                                     double kappa = 4.0) {
    const int n = theta_grid.size();
    double H_exp = 0.0;
    for (int z = 0; z <= 1; ++z) {
        VectorXd like(n);
        for (int i = 0; i < n; ++i) {
            like(i) = measurement_likelihood(z, theta_grid(i), a, kappa);
        }
        VectorXd b_unnorm = like.cwiseProduct(b);
        double pz = b_unnorm.sum();
        if (pz > 0.0) {
            VectorXd b_post = b_unnorm / pz;
            H_exp += pz * entropy(b_post);
        }
    }
    return H_exp;
}

int main() {
    const int n_theta = 360;
    VectorXd theta_grid(n_theta);
    for (int i = 0; i < n_theta; ++i) {
        theta_grid(i) = -M_PI + 2.0 * M_PI * static_cast<double>(i) / n_theta;
    }

    VectorXd b = VectorXd::Ones(n_theta) / static_cast<double>(n_theta);

    // Candidate views
    const int n_views = 12;
    std::vector<double> views(n_views);
    for (int i = 0; i < n_views; ++i) {
        views[i] = -M_PI + 2.0 * M_PI * static_cast<double>(i) / n_views;
    }

    // Ground truth
    double theta_true = 0.7;

    std::mt19937 gen(0);
    std::uniform_real_distribution<double> unif(0.0, 1.0);

    for (int t = 0; t < 6; ++t) {
        double H_prior = entropy(b);
        double best_a = views[0];
        double best_ig = -std::numeric_limits<double>::infinity();

        for (double a : views) {
            double H_post = expected_entropy_after_action(theta_grid, b, a);
            double ig = H_prior - H_post;
            if (ig > best_ig) {
                best_ig = ig;
                best_a = a;
            }
        }

        // Simulate measurement
        double p1 = measurement_likelihood(1, theta_true, best_a);
        int z = (unif(gen) < p1) ? 1 : 0;

        // Update belief
        VectorXd like(n_theta);
        for (int i = 0; i < n_theta; ++i) {
            like(i) = measurement_likelihood(z, theta_grid(i), best_a);
        }
        b = normalize(like.cwiseProduct(b));

        std::cout << "Step " << t
                  << " a=" << best_a
                  << " z=" << z
                  << " IG=" << best_ig
                  << " H=" << entropy(b)
                  << std::endl;
    }

    return 0;
}
      

This C++ implementation mirrors the Python logic, and can be integrated into a larger manipulation stack using standard robotics middleware (e.g. wrapped as a service in a ROS-based system).

9. Java Snippet — Generic Active Sensing Loop

The Java snippet below shows a generic structure for an active sensing loop. For simplicity, we keep the measurement model abstract via an interface; in a real system, this would call a vision or tactile estimator implemented in C++ or Python through JNI or a network API.


public class ActiveSensing1D {

    public interface MeasurementModel {
        double likelihood(int z, double theta, double a);
    }

    private final double[] thetaGrid;
    private double[] belief;
    private final double[] candidateViews;
    private final MeasurementModel model;

    public ActiveSensing1D(double[] thetaGrid,
                           double[] candidateViews,
                           MeasurementModel model) {
        this.thetaGrid = thetaGrid;
        this.candidateViews = candidateViews;
        this.model = model;
        this.belief = new double[thetaGrid.length];
        double init = 1.0 / thetaGrid.length;
        for (int i = 0; i < belief.length; ++i) {
            belief[i] = init;
        }
    }

    private void normalize() {
        double sum = 0.0;
        for (double v : belief) {
            sum += v;
        }
        if (sum <= 0.0) {
            double init = 1.0 / belief.length;
            for (int i = 0; i < belief.length; ++i) {
                belief[i] = init;
            }
            return;
        }
        for (int i = 0; i < belief.length; ++i) {
            belief[i] /= sum;
        }
    }

    private double entropy() {
        double H = 0.0;
        for (double b : belief) {
            if (b > 0.0) {
                H -= b * Math.log(b);
            }
        }
        return H;
    }

    private double expectedEntropyAfterAction(double a) {
        double Hexp = 0.0;
        int[] zs = {0, 1};
        for (int z : zs) {
            double[] post = new double[thetaGrid.length];
            double pz = 0.0;
            for (int i = 0; i < thetaGrid.length; ++i) {
                double like = model.likelihood(z, thetaGrid[i], a);
                post[i] = like * belief[i];
                pz += post[i];
            }
            if (pz > 0.0) {
                for (int i = 0; i < post.length; ++i) {
                    post[i] /= pz;
                }
                double Hz = 0.0;
                for (double b : post) {
                    if (b > 0.0) {
                        Hz -= b * Math.log(b);
                    }
                }
                Hexp += pz * Hz;
            }
        }
        return Hexp;
    }

    public double chooseAction() {
        double Hprior = entropy();
        double bestA = candidateViews[0];
        double bestIG = Double.NEGATIVE_INFINITY;
        for (double a : candidateViews) {
            double Hpost = expectedEntropyAfterAction(a);
            double ig = Hprior - Hpost;
            if (ig > bestIG) {
                bestIG = ig;
                bestA = a;
            }
        }
        return bestA;
    }

    public void update(double a, int z) {
        for (int i = 0; i < thetaGrid.length; ++i) {
            double like = model.likelihood(z, thetaGrid[i], a);
            belief[i] *= like;
        }
        normalize();
    }

    public double[] getBelief() {
        return belief.clone();
    }
}
      

This code encapsulates the essence of active perception: a belief over state, an information-based action selector, and a Bayesian update given new observations.

10. MATLAB/Simulink Implementation Sketch

In MATLAB, we can implement NBV-style active perception using vectors and matrices, and embed the logic into a Simulink model via a MATLAB Function block. Below is a script that performs one active step of 1D-view selection as in the previous examples.


function active_perception_demo()
    nTheta = 360;
    thetaGrid = linspace(-pi, pi, nTheta);
    b = ones(1, nTheta) / nTheta;

    nViews = 12;
    candidateViews = linspace(-pi, pi, nViews);

    thetaTrue = 0.7;
    kappa = 4.0;

    for t = 1:6
        [aStar, ig] = choose_action(thetaGrid, b, candidateViews, kappa);
        % Simulate measurement
        p1 = measurement_likelihood(1, thetaTrue, aStar, kappa);
        z = rand() < p1;
        b = update_belief(thetaGrid, b, aStar, z, kappa);
        H = entropy_belief(b);
        fprintf('Step %d: a=%.2f, z=%d, IG=%.3f, H=%.3f\n', t, aStar, z, ig, H);
    end
end

function p = measurement_likelihood(z, theta, a, kappa)
    p1 = 1.0 ./ (1.0 + exp(-kappa .* cos(theta - a)));
    if z == 1
        p = p1;
    else
        p = 1.0 - p1;
    end
end

function H = entropy_belief(b)
    idx = b > 0;
    H = -sum(b(idx) .* log(b(idx)));
end

function [aStar, bestIG] = choose_action(thetaGrid, b, candidateViews, kappa)
    Hprior = entropy_belief(b);
    aStar = candidateViews(1);
    bestIG = -inf;
    for a = candidateViews
        Hpost = expected_entropy_after_action(thetaGrid, b, a, kappa);
        ig = Hprior - Hpost;
        if ig > bestIG
            bestIG = ig;
            aStar = a;
        end
    end
end

function Hexp = expected_entropy_after_action(thetaGrid, b, a, kappa)
    Hexp = 0.0;
    for z = 0:1
        like = measurement_likelihood(z, thetaGrid, a, kappa);
        bUnnorm = like .* b;
        pz = sum(bUnnorm);
        if pz > 0
            bPost = bUnnorm / pz;
            Hz = entropy_belief(bPost);
            Hexp = Hexp + pz * Hz;
        end
    end
end

function bNext = update_belief(thetaGrid, b, a, z, kappa)
    like = measurement_likelihood(z, thetaGrid, a, kappa);
    bUnnorm = like .* b;
    s = sum(bUnnorm);
    if s <= 0
        bNext = ones(size(b)) / numel(b);
    else
        bNext = bUnnorm / s;
    end
end
      

To integrate this into Simulink, one can:

  1. Create a MATLAB Function block implementing a single update step.
  2. Feed in the current belief, chosen action, and measured \( z \) from sensor blocks (e.g., a camera processing pipeline block).
  3. Output the updated belief and the recommended next sensing action as signals for the manipulator motion planner.

11. Wolfram Mathematica Implementation Sketch

Mathematica is well-suited for prototyping information-theoretic active perception, thanks to symbolic and numerical capabilities. The following snippet implements a single NBV step for a discrete 1D state.


nTheta = 360;
thetaGrid = Subdivide[-Pi, Pi, nTheta - 1];
belief = ConstantArray[1.0/nTheta, nTheta];

logistic[u_] := 1.0/(1.0 + Exp[-u]);

measurementLikelihood[z_, theta_, a_, kappa_: 4.0] :=
  Module[{p1},
    p1 = logistic[kappa*Cos[theta - a]];
    If[z == 1, p1, 1.0 - p1]
  ];

entropyBelief[b_List] :=
  Module[{mask},
    mask = Select[b, # > 0.0 &];
    -Total[mask*Log[mask]]
  ];

expectedEntropyAfterAction[b_List, a_, kappa_: 4.0] :=
  Module[{Hexp = 0.0, zVals = {0, 1}, n = Length[thetaGrid]},
    Do[
      Module[{like, bUnnorm, pz, bPost, Hz},
        like = Table[measurementLikelihood[z, thetaGrid[[i]], a, kappa], {i, n}];
        bUnnorm = like*b;
        pz = Total[bUnnorm];
        If[pz > 0.0,
          bPost = bUnnorm/pz;
          Hz = entropyBelief[bPost];
          Hexp = Hexp + pz*Hz;
        ];
      ],
      {z, zVals}
    ];
    Hexp
  ];

chooseAction[b_List, candidateViews_List, kappa_: 4.0] :=
  Module[{Hprior, bestA, bestIG, Hpost, ig},
    Hprior = entropyBelief[b];
    bestA = First[candidateViews];
    bestIG = -Infinity;
    Do[
      Hpost = expectedEntropyAfterAction[b, a, kappa];
      ig = Hprior - Hpost;
      If[ig > bestIG,
        bestIG = ig;
        bestA = a;
      ],
      {a, candidateViews}
    ];
    {bestA, bestIG}
  ];

updateBelief[b_List, a_, z_, kappa_: 4.0] :=
  Module[{like, bUnnorm, s},
    like = measurementLikelihood[z, #, a, kappa] & /@ thetaGrid;
    bUnnorm = like*b;
    s = Total[bUnnorm];
    If[s <= 0.0,
      ConstantArray[1.0/Length[b], Length[b]],
      bUnnorm/s
    ]
  ];

(* Example usage *)
nViews = 12;
candidateViews = Subdivide[-Pi, Pi, nViews - 1];
thetaTrue = 0.7;

b = belief;
Do[
  {aStar, ig} = chooseAction[b, candidateViews];
  p1 = measurementLikelihood[1, thetaTrue, aStar];
  z = If[RandomReal[] < p1, 1, 0];
  b = updateBelief[b, aStar, z];
  Print["Step ", t, " a=", aStar, " z=", z, " IG=", ig, " H=", entropyBelief[b]];
  ,
  {t, 0, 5}
];
      

Mathematica can also be used to symbolically derive gradients of information measures with respect to action parameters, which is useful for continuous sensor motion optimization.

12. Problems and Solutions

Problem 1 (Bayes Update for Static Scene): Consider a static scene state \( x \) and an observation model \( p(z \mid x,a) \). Assuming a prior \( b(x) \) and an executed sensing action \( a \) with observation \( z \), derive the expression for the posterior belief \( b'(x) = p(x \mid z,a) \).

Solution: By Bayes rule,

\[ b'(x) = p(x \mid z,a) = \frac{ p(z \mid x,a)\, b(x) }{ \sum_{x'} p(z \mid x',a) b(x') }. \]

The denominator is the marginal likelihood \( p(z \mid a) \). This is exactly the update used in the active perception loops above.

Problem 2 (Expected Entropy for a Binary State): Let \( X \in \{x_1,x_2\} \) with prior probabilities \( b_1, b_2 = 1-b_1 \). For an action \( a \), suppose the observation \( Z \in \{0,1\} \) has likelihoods \( p(z=1 \mid x_i,a) = \alpha_i \). Derive a closed-form expression for the expected posterior entropy \( \mathbb{E}[H(b')] \) as a function of \( b_1 \), \( \alpha_1 \), and \( \alpha_2 \).

Solution: First compute \( p(z=1 \mid a) = \alpha_1 b_1 + \alpha_2 (1-b_1) \) and \( p(z=0 \mid a) = 1 - p(z=1 \mid a) \). The posterior for \( z=1 \) is

\[ b_1^{(1)} = \frac{\alpha_1 b_1}{\alpha_1 b_1 + \alpha_2 (1-b_1)}, \quad b_2^{(1)} = 1 - b_1^{(1)}, \]

giving entropy

\[ H_1 = - b_1^{(1)} \log b_1^{(1)} - (1-b_1^{(1)}) \log (1-b_1^{(1)}). \]

Similarly for \( z=0 \),

\[ b_1^{(0)} = \frac{(1-\alpha_1) b_1}{(1-\alpha_1) b_1 + (1-\alpha_2)(1-b_1)}, \quad H_0 = - b_1^{(0)} \log b_1^{(0)} - (1-b_1^{(0)}) \log (1-b_1^{(0)}). \]

Therefore the expected posterior entropy is

\[ \mathbb{E}[H(b')] = p(z=1 \mid a) H_1 + p(z=0 \mid a) H_0. \]

Comparing this quantity for two candidate actions \( a_1, a_2 \) indicates which action yields larger expected entropy reduction.

Problem 3 (Gaussian NBV Derivation): Starting from the linear-Gaussian model \( \theta \sim \mathcal{N}(\mu,\Sigma) \), \( z = H_v \theta + \varepsilon \), \( \varepsilon \sim \mathcal{N}(0,R) \), derive the posterior covariance \( \Sigma'(v) \) and show that the entropy reduction is \( \Delta H(v) = \tfrac{1}{2}\log\det(I + \Sigma H_v^\top R^{-1} H_v) \).

Solution: The standard linear-Gaussian conditioning formula gives the posterior covariance

\[ \Sigma'(v) = \Sigma - \Sigma H_v^{\top} (H_v \Sigma H_v^{\top} + R)^{-1} H_v \Sigma. \]

Using the matrix inversion lemma, one can show this is equivalent to

\[ \Sigma'(v) = \big( \Sigma^{-1} + H_v^\top R^{-1} H_v \big)^{-1}. \]

The entropy of a Gaussian in \( \mathbb{R}^n \) is \( H = \tfrac{1}{2}\log\big((2\pi e)^n \det \Sigma\big) \), hence

\[ \Delta H(v) = \tfrac{1}{2} \log \frac{\det \Sigma}{\det \Sigma'(v)} = \tfrac{1}{2} \log \det\!\Big( I + \Sigma H_v^\top R^{-1} H_v \Big), \]

where the last equality uses \( \det \Sigma'(v) = \det(\Sigma^{-1} + H_v^\top R^{-1} H_v)^{-1} = \det(\Sigma) / \det(I + \Sigma H_v^\top R^{-1} H_v) \). This shows that NBV corresponds to choosing the view with maximal log-det of the Fisher-information-augmented covariance.

Problem 4 (Active Perception as Myopic POMDP): Consider a POMDP with state space \( \mathcal{X} \), action space \( \mathcal{A} = \mathcal{A}^{\text{sens}} \cup \mathcal{A}^{\text{man}} \), and observation model \( p(z \mid x,a) \) (for any action, sensing or manipulation). Show that a myopic information-gain policy for sensing actions can be obtained by defining the instantaneous reward

\[ R(b_t, a_t, z_{t+1}) = H(b_t) - H(b_{t+1}^z), \]

and maximizing expected one-step reward over \( a_t^{\text{sens}} \).

Solution: In belief-state POMDP form, the reward is a function of the belief before and after the action-observation pair. The expected one-step reward for a sensing action \( a_t^{\text{sens}} \) is

\[ \mathbb{E}\big[R(b_t,a_t,z_{t+1})\big] = \mathbb{E}_{z \mid a_t,b_t} \big[ H(b_t) - H(b_{t+1}^z) \big] = H(b_t) - \mathbb{E}_{z \mid a_t,b_t} \big[ H(b_{t+1}^z) \big], \]

which is precisely the mutual information \( I_t(X;Z \mid a_t) \). Therefore, maximizing expected one-step reward over sensing actions is equivalent to the information gain policy from earlier sections.

Problem 5 (Binary Search as Optimal Tactile Policy): For the noiseless 1D tactile example \( z = \mathbf{1}\{s < s^\star\} \) with \( s^\star \) uniformly distributed on \( [0,1] \), prove that placing the probe at the posterior median at each step minimizes the expected posterior entropy.

Solution (sketch): Under a uniform prior on \( [0,1] \), entropy is a monotone function of the support length (since the density is constant). A probe at position \( s \) partitions the support into two intervals \( [0,s] \) and \( [s,1] \) with probabilities \( s \) and \( 1-s \). The expected posterior entropy is then proportional to

\[ \mathbb{E}[H(b')] \propto s \log s + (1-s) \log(1-s), \]

which is minimized when \( s = \tfrac{1}{2} \), by symmetry or direct differentiation. After one probe, the posterior remains uniform on either \( [0,\tfrac{1}{2}] \) or \( [\tfrac{1}{2},1] \). By induction, choosing the median at each step always halves the support, achieving the smallest possible expected entropy over all policies that use the same number of measurements.

13. Summary

In this lesson we formalized active perception as a Bayesian decision problem over beliefs, with actions chosen to maximize information gain or task success. We introduced entropy and mutual information as objective functions, derived NBV criteria for discrete and Gaussian beliefs, and extended the framework to tactile and multi-modal sensing. We also showed how active perception couples to manipulation through confidence-constrained optimization, and implemented myopic active sensing loops in Python, C++, Java, MATLAB/Simulink, and Mathematica. These tools enable robots to not only interpret sensory data, but to seek data that is maximally useful for robust manipulation.

14. References

  1. Bajcsy, R. (1988). Active perception. Proceedings of the IEEE, 76(8), 966–1005.
  2. Aloimonos, J., Weiss, I., & Bandyopadhyay, A. (1988). Active vision. International Journal of Computer Vision, 1(4), 333–356.
  3. Denzler, J., & Brown, C. M. (2002). Information theoretic sensor data selection for active object recognition and state estimation. IEEE Transactions on Pattern Analysis and Machine Intelligence, 24(2), 145–157.
  4. Pito, R. (1999). A solution to the next best view problem for automated surface acquisition. IEEE Transactions on Pattern Analysis and Machine Intelligence, 21(10), 1016–1030.
  5. Sim, R., & Roy, N. (2005). Global A-optimal robot exploration in SLAM. IEEE International Conference on Robotics and Automation.
  6. Kragic, D., & Christensen, H. I. (2002). Survey on visual servoing for manipulation. Computational Vision and Active Perception Laboratory Technical Reports.
  7. Bohg, J., Morales, A., Asfour, T., & Kragic, D. (2014). Data-driven grasp synthesis: A survey. IEEE Transactions on Robotics, 30(2), 289–309. (See especially discussion of active perception for grasping.)
  8. Hollinger, G. A., & Sukhatme, G. S. (2014). Sampling-based robotic information gathering algorithms. International Journal of Robotics Research, 33(9), 1271–1287.
  9. Krause, A., Singh, A., & Guestrin, C. (2008). Near-optimal sensor placements in Gaussian processes: Theory, efficient algorithms and empirical studies. Journal of Machine Learning Research, 9, 235–284.
  10. Javdani, S., Karaman, S., Bagnell, J. A., & Srinivasa, S. S. (2013). Near optimal Bayesian active learning for decision making. IEEE International Conference on Robotics and Automation.