Particle filter, resampling step implementation
Your question is about the resampling step, and let's focus on that. 

Resampling is used in particle filtering to counteract "sample impoverishment" that is the fact that some particles may have very low weights. This is a waste of resources as you want to describe your probability distribution ate best. You should note that it should not interfere (a priori) with the measurement of prediction steps.

The optimal situation is to have all particles having roughly uniform weights and that's the goal set by most resampling algorithms. I propose you use this function which uses something similar to histogram equalization for a ratio resampleof particles (a nd-array were the last line represents the weights):

def resampling(particles, resample):
    """
    Resample weighted particles.

    The particles are grouped in N_pop batches to represent multiple velocities.
    The probability is given for all particles but corresponds to the proba-
    bility of one batch.

    Input
    -----
    N particles as a particles.shape array

    Output
    ------
    N particles as a particles.shape array

    Parameters
    ----------
    resample : gives the ratio of particles that get resampled at every frame (between 0 and 1)

    """
    particles_out = particles.copy()
    N = particles.shape[1]  # number of particles


    # resample a percentage of the particles (the total number keeps to N)
    if resample &gt; 0:
        # draw resample (in %) random addresses of particles that we will reassign
        N_resample = int(N*resample)
        address_resample = np.random.permutation(np.arange(N))[0:N_resample]

        # draw from this subset some addresses uniformly over their pdf using histogram equalization
        proba_resample = particles_out[-1, address_resample]
        proba_resample /= proba_resample.sum()
        address = np.interp(np.linspace(0, 1, N_resample, endpoint=False)+1/2./N_resample,#np.random.rand(N_resample),
                            np.concatenate(([0.], np.cumsum(proba_resample))),
                            np.arange(N_resample+1))
        address = [int(k) for k in address]

        # reassign these particles and set their weight to a uniform value
        particles_out[:, address_resample] = particles_out[:, address_resample[address]]
        subset_weight = proba_resample[address].sum() # should be \approx N_resample / N, that is, resample
        particles_out[4, address_resample] = subset_weight / N_resample #1/N_resample #particles_out[4, address_resample].sum()

        # ultimately, normalize weights
        particles_out[4, :] /= particles_out[4, :].sum()

    return particles_out