This is one of the only practical techniques to handing non-Gaussian noise and non-linear observation and motion models. We don't need to to have any analytical expressions for and !

This is an approximation of Bayes Filter. Reminder

The method shown here is sometimes called the bootstrap algorithm, condensation algorithm, or survival-of-the-fittest algorithm

How it Works

  1. Draw M samples from the joint density comprising the prior and motion noise
where $m$ is the unique *particle index*. In practice we just draw samples from the two factors separately

2. Generate a prediction of the posterior by sending the samples through the motion model

these new *predicted particles* together approximate the posterior density, $p(\mathbf{x}_{k}|\check{\mathbf{x}}_{0},\mathbf{v}_{1:k},\mathbf{y}_{1:k-1})$

3. Correct the posterior PDF by incorporating (our measurements). This is done in two steps: 1. Assign a scalar weight to each predicted particle based on the divergence between the desired posterior and the predicted posterior for each particle.

	This is done in practice normally by simulating a **expected sensor reading** using the non-linear observation model.
	and then set $p(\mathbf{y}_{k}|\check{\mathbf{x}}_{k,m})=p(\mathbf{y}_{k}|\check{\mathbf{y}}_{k,m})$
2. Resample the posterior based on the weight assigned to each predicted posterior particle:
	**There are a number of ways to do this resampling**

here can be fed back into step 2!!! bad representation, but I'm trying to say that the samples you redrew here are fed inot the motion model again. (the noise is also resampled)

  1. Repeat steps 1-3 until we want to stop. ie. maybe when

Methods of Resampling

Resampling the posterior density according to the weights we get is pretty important, and there are a number of ways to do it.

Madow Resampling

Assuming we have samples, each assigned an unnormalized weight . From the weights, we create bins with boundary according to

This defines boundaries of M bins between 0 and 1.

def madow_systematic_resampling(weights, M):
    """
    Madow's systematic resampling for particle filters.
    
    Parameters:
    -----------
    weights : array-like, shape (M,)
        Unnormalized or normalized weights for M particles
    M : int
        Number of particles
    
    Returns:
    --------
    indices : array, shape (M,)
        Indices of resampled particles
    """
    # Normalize weights
    weights = np.asarray(weights)
    w_normalized = weights / np.sum(weights)
    
    # Compute cumulative sum to create bin boundaries β_m
    beta = np.cumsum(w_normalized)
    
    # Sample random starting point ρ from uniform [0, 1)
    rho = np.random.uniform(0, 1)
    
    # Initialize indices array
    indices = np.zeros(M, dtype=int)
    
    # Systematic sampling: step forward by 1/M at each iteration
    for i in range(M):
        # Current position (wraps around using modulo)
        u = (rho + i / M) % 1.0
        
        # Find which bin u falls into
        # This is the index where β_{m-1} < u ≤ β_m
        indices[i] = np.searchsorted(beta, u)
    
    return indices

This guarantees that any bin with width greater than will have a sample in it.