Skip to content

Commit

Permalink
[TUTO][DOC] Finished the first draft of the PF tutorial documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
LAGNEAU Romain committed Sep 2, 2024
1 parent 4f11cb9 commit af996bb
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 120 deletions.
Binary file modified doc/image/tutorial/misc/img-tutorial-pf-run.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 43 additions & 47 deletions doc/tutorial/misc/tutorial-pf.dox
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ The Particle Filters (PF) are a set of Monte Carlo algorithms that
permit to approximate solutions for filtering problems even when
the state-space and/or measurement space are non-linear.

In this tutorial, we will use a PF to filter the 3D position of a simulated object, which revolves in a plane parallel
In this tutorial, we will use a PF on the same use-case than presented in \ref tutorial-ukf . The PF is used to
filter the 3D position of a simulated object, which revolves in a plane parallel
to the ground around a static point, which is the origin of the world frame \f$ {F}_W \f$. The coordinate frame
attached to the object is denoted \f$ {F}_O \f$. The object is observed by a static camera whose coordinate
frame is denoted \f$ {F}_C \f$. The object is supposed plane and having four markers sticked on its surface.
Expand All @@ -35,7 +36,7 @@ radius of the revolution around the origin of the world frame.
The maths beyond the Particle Filter are explained in the documentation of the vpParticleFilter class.
We will recall briefly the important steps of the PF.

Be \f$ \textbf{x}_i \in \textit{S} \f$ a particle representing the internal state of the PF, with \f$ i \in {0 \dots N - 1} \f$
Be \f$ \textbf{x}_i \in \textit{S} \f$ a particle representing the internal state of the PF, with \f$ i \in \{0 \dots N - 1\} \f$
and \f$ \textit{S} \f$ the state space.
To each particle is associated a weight \f$ w_i \f$ that represents its likelihood knowing the measurements and is used
to compute the filtered state \f$ \textbf{x}_{filtered} \in \textit{S} \f$.
Expand Down Expand Up @@ -247,7 +248,7 @@ It takes as input the camera parameters <code>cam</code>, the homogeneous matrix
expresses the rotation between the object frame and world frame <code>wRo</code> and the homogeneous coordinates of the
markers expressed in the object frame <code>markers</code> to be able to convert the 3D position of the object in the
world frame \f$ {}^W \textbf{X} \f$ into 3D positions of the markers in the camera frame \f$ {}^C \textbf{X}^i \f$, where
\f$ i \f$ denotes the i\f$^th\f$ marker sticked on the object. The standard deviation of the noise <code>noise_stdev</code>
\f$ i \f$ denotes the i\f$^{th}\f$ marker sticked on the object. The standard deviation of the noise <code>noise_stdev</code>
and the seed value <code>seed</code> are here to initialized the Gaussian noise generator used to simulate noisy measurements.
Additionally, the likelihood standard deviation \f$\sigma_l\f$ is given for the computation of the likelihood of a PF
particle knowing the measurements.
Expand Down Expand Up @@ -285,7 +286,7 @@ Here is the corresponding code:

The method <code>computePose</code> compute the 3D pose of an object from the 3D coordinates along with their projection
in the image. Here, we use it to convert the noisy measurements in a noisy 3D pose, in order to
compare the 3D position estimated by the UKF with regard to the 3D position we would have if we computed the pose directly
compare the 3D position estimated by the PF and by the UKF with regard to the 3D position we would have if we computed the pose directly
from the noisy measurements.

\snippet tutorial-pf.cpp Pose_for_display
Expand Down Expand Up @@ -315,58 +316,55 @@ generate camera parameters for a simulated camera as follow:

\snippet tutorial-pf.cpp Camera_for_measurements

\subsubsection tuto-pf-tutorial-explained-initukf Details on the initialization of the UKF
\subsubsection tuto-pf-tutorial-explained-initpf Details on the initialization of the PF

To initialize the UKF, we need an object that will be able to compute the sigma points and their associated weights. To
do so, we must create an instance of a class inheriting from the class vpUKSigmaDrawerAbstract. In our case, we decided
to use the method proposed by E. A. Wan and R. van der Merwe in \cite Merwe00 and implemented in the vpUKSigmaDrawerMerwe class:
To create the particle filter, we need:
- the number of particles \f$ N \f$ we want to use,
- the standard deviations of each of the components of the state \f$ \sigma_j , j \in \{0 \dots dim(\textit{S}) - 1\} \f$,
- optionnally, the seed to use to create the random noise generators affected to each state components,
- optionnally, the number of threads to use if OpenMP is available.

\snippet tutorial-pf.cpp Sigma_points_drawer
These parameters can be set using the Command Line Interface (CLI) thanks to the following structure:

The first parameter is the dimension of the state of the UKF. The second parameter is \f$ \alpha \f$: the greater it is
the further of the mean the sigma points are; it is a real and its value must be between 0 and 1. The third parameter is
\f$ \beta \f$: it is a real whose value is set to two for Gaussian problems. Finally, the last parameter is \f$ \kappa \f$:
it is a real whose value must be set to \f$ 3 - n \f$ for most problems.
\snippet tutorial-pf.cpp CLI

The UKF needs the covariance matrix of the measurements \f$ \textbf{R} \f$ that represents the uncertainty of the
measurements:
They are thereafter used in the following section of code of the main function:

\snippet tutorial-pf.cpp Covariance_measurements
\snippet tutorial-pf.cpp Constants_for_the_PF

The UKF needs the covariance matrix of the process \f$ \textbf{Q} \f$ that represents the uncertainty induced during the
prediction step:
Then, to initialize the filters, we need:
- a guess of the initial state \f$ \textbf{x}(t = 0) \f$,
- a process function \f$ f \f$,
- a likelihood function \f$ l \f$,
- a function that returns true if the filter is degenerated and sampling is needed,
- a function that performs the resampling,
- optionnally, a function to perform the weighted mean \f$ wm \f$ if the addition operation cannot be readily performed
in the state space \f$ \textit{S} \f$,
- optionnally, a function to perform the addition operation in the state space \f$ \textit{S} \f$.

\snippet tutorial-pf.cpp Covariance_process
The section of code corresponding to the declaration of these functions is the following:

The UKF needs an estimate of the intial state \f$ \textbf{x}_0 \f$ and of its covariance \f$ \textbf{P}_0 \f$:
\snippet tutorial-pf.cpp Init_functions_pf

\snippet tutorial-pf.cpp Initial_estimates
When both the constants and the functions have been declared, it is possible to create the PF
using the following code:

Next, we initialize the process function and the measurement function:
\snippet tutorial-pf.cpp Init_PF

\snippet tutorial-pf.cpp Init_functions
\subsubsection tuto-pf-tutorial-explained-initukf Initialization of the UKF, used for comparison purpose

Finally, we create the UKF and initialize its state:
We refer the user to \ref tuto-ukf-tutorial-explained-initukf for more detailed explanations on the initialization
of the UKF, as this tutorial uses the same use-case. The code corresponding to the creation and initialization
of the UKF is the following:

\snippet tutorial-pf.cpp Init_UKF

If the internal state cannot use the standard addition and subtraction, it would be necessary to write other methods:
- a method permitting to add two state vectors (see vpUnscentedKalman::setStateAddFunction),
- a method permitting to subtract two state vectors (see vpUnscentedKalman::setStateResidualFunction),
- and a method permitting to compute the mean of several state vectors (see vpUnscentedKalman::setStateMeanFunction).

If some commands are known to have an effect on the internal state, it would be necessary to write other methods:
- a method for the effects of the commands on the state, without knowing the state (see vpUnscentedKalman::setCommandOnlyFunction),
- and/or a method for the effects of the commands on the state, knowing the state (see vpUnscentedKalman::setCommandStateFunction).

If the measurement space cannot use the standard addition and subtraction, it would be necessary to write other methods:
- a method permitting to subtract two measurement vectors (see vpUnscentedKalman::setMeasurementResidualFunction),
- and a method permitting to compute the mean of several measurement vectors (see vpUnscentedKalman::setMeasurementMeanFunction).

\subsubsection tuto-pf-tutorial-explained-initgui Details on the initialization of the Graphical User Interface

If ViSP has been compiled with any of the third-party graphical libraries, we first begin by initializing the
plot that will display the object x and y coordinates expressed in the world frame:
plot that will display the object x and y coordinates expressed in the world frame. Then, we initialize a plot that will
display the error norm between either one of the filtered positions or the noisy position and the Ground Truth position.
The corresponding code is the following:

\snippet tutorial-pf.cpp Init_plot

Expand All @@ -378,7 +376,7 @@ Then, we initialize the simple renderer that displays what the camera sees:

For the initialization of the loop, we initialize an instance of the vpObjectSimulator class that
simulates the moving object. Then, we initialize the current ground-truth 3D position of the object expressed in the
world frame, which is the frame in which the internal state of the UKF is expressed, as a null homogeneous coordinates
world frame, which is the frame in which the internal states of both the PF and the UKF are expressed, as a null homogeneous coordinates
vector.

\snippet tutorial-pf.cpp Init_simu
Expand All @@ -398,9 +396,13 @@ some noise to the projections using the following line:

\snippet tutorial-pf.cpp Update_measurement

Then, we use the Unscented Kalman Filter to filter the noisy measurements:
Then, we use the Particle Filter to filter the noisy measurements:

\snippet tutorial-pf.cpp PF_filtering

\snippet tutorial-pf.cpp Perform_filtering
Then, we use the Unscented Kalman Filter to filter the noisy measurements to compare the results:

\snippet tutorial-pf.cpp UKF_filtering

Finally, we update the plot and renderer:

Expand All @@ -419,11 +421,5 @@ Finally, we update the renderer that displays the projection in the image of the

\snippet tutorial-pf.cpp Update_renderer

\subsubsection tuto-pf-tutorial-explained-cleaning Details on the cleaning at the end of the program

Finally, we clean the allocated memory for the renderer:

\snippet tutorial-pf.cpp Delete_renderer

The program stops once the `Return` key is pressed.
*/
2 changes: 1 addition & 1 deletion doc/tutorial/misc/tutorial-ukf.dox
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ It takes as input the camera parameters <code>cam</code>, the homogeneous matrix
expresses the rotation between the object frame and world frame <code>wRo</code> and the homogeneous coordinates of the
markers expressed in the object frame <code>markers</code> to be able to convert the 3D position of the object in the
world frame \f$ {}^W \textbf{X} \f$ into 3D positions of the markers in the camera frame \f$ {}^C \textbf{X}^i \f$, where
\f$ i \f$ denotes the i\f$^th\f$ marker sticked on the object. The standard deviation of the noise <code>noise_stdev</code>
\f$ i \f$ denotes the i\f$^{th}\f$ marker sticked on the object. The standard deviation of the noise <code>noise_stdev</code>
and the seed value <code>seed</code> are here to initialized the Gaussian noise generator used to simulate noisy measurements.

The method <code>state_to_measurement</code> is used to convert the internal state of the UKF into the measurement space
Expand Down
Loading

0 comments on commit af996bb

Please sign in to comment.