LoSlamParams.H

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/slam/LoSlamParams.H
00003    \brief A helper class to hold the different SLAM parameters.
00004 
00005    This file defines a helper class that holds the different SLAM
00006    parameters together in one place that can be used by the different
00007    bits and pieces that implement Robolocust's SLAM subsystem.
00008 */
00009 
00010 // //////////////////////////////////////////////////////////////////// //
00011 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00012 // by the University of Southern California (USC) and the iLab at USC.  //
00013 // See http://iLab.usc.edu for information about this project.          //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00016 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00017 // in Visual Environments, and Applications'' by Christof Koch and      //
00018 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00019 // pending; application number 09/912,225 filed July 23, 2001; see      //
00020 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00021 // //////////////////////////////////////////////////////////////////// //
00022 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00023 //                                                                      //
00024 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00025 // redistribute it and/or modify it under the terms of the GNU General  //
00026 // Public License as published by the Free Software Foundation; either  //
00027 // version 2 of the License, or (at your option) any later version.     //
00028 //                                                                      //
00029 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00030 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00031 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00032 // PURPOSE.  See the GNU General Public License for more details.       //
00033 //                                                                      //
00034 // You should have received a copy of the GNU General Public License    //
00035 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00036 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00037 // Boston, MA 02111-1307 USA.                                           //
00038 // //////////////////////////////////////////////////////////////////// //
00039 //
00040 // Primary maintainer for this file: mviswana usc edu
00041 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/slam/LoSlamParams.H $
00042 // $Id: LoSlamParams.H 13575 2010-06-17 01:42:18Z mviswana $
00043 //
00044 
00045 #ifndef LOBOT_SLAM_PARAMS_DOT_H
00046 #define LOBOT_SLAM_PARAMS_DOT_H
00047 
00048 //------------------------------ HEADERS --------------------------------
00049 
00050 // lobot headers
00051 #include "Robots/LoBot/ui/LoDrawable.H"
00052 #include "Robots/LoBot/misc/singleton.hh"
00053 #include "Robots/LoBot/util/range.hh"
00054 #include "Robots/LoBot/util/triple.hh"
00055 
00056 // Standard C++ headers
00057 #include <string>
00058 #include <utility>
00059 
00060 //----------------------------- NAMESPACE -------------------------------
00061 
00062 namespace lobot {
00063 
00064 //------------------------- CLASS DEFINITION ----------------------------
00065 
00066 /**
00067    \class lobot::SlamParams
00068    \brief A helper class for holding the various SLAM related parameters.
00069 
00070    The settings for Robolocust's SLAM subsystem are spread over a couple
00071    of different sections of the config file. This class helps put them
00072    all in one place so that all the SLAM related modules can access these
00073    parameters from one place instead of having to duplicate code or
00074    introduce unweildy module dependencies.
00075 */
00076 class SlamParams : public singleton<SlamParams> {
00077    /// Robolocust uses an occupancy grid for its map. Each cell in this
00078    /// grid holds a probability indicating the confidence level regarding
00079    /// the presence of an obstacle at that particular position in the
00080    /// map.
00081    ///
00082    /// To make the map cover a reasonably substantial physical area while
00083    /// simultaneously minimizing the amount of memory required to hold
00084    /// the grid, we need to discretize the physical space of the robot's
00085    /// environment. Thus, each cell in the grid will represent a small
00086    /// square area of the environment.
00087    ///
00088    /// This setting specifies the size of the above-mentioned square (in
00089    /// mm).
00090    float m_cell_size ;
00091 
00092    /// The map's extents are specified using [left, right, bottom, top]
00093    /// values. These extents are in the physical environment's coordinate
00094    /// system (i.e., mm).
00095    float m_extents[4] ;
00096 
00097    /// The above parameters dictate the size of the map's grid. These two
00098    /// data members are used to store the grid's dimensions.
00099    int m_width, m_height ;
00100 
00101    /// This member holds the length of the map's diagonal. It is useful
00102    /// for the probabilistic beam model applied by the FastSLAM algorithm
00103    /// to the laser range finder measurements.
00104    float m_max_distance ;
00105 
00106    /// This member variable holds the x and y scale factors for
00107    /// converting real/physical coordinates to grid coordinates and vice
00108    /// versa.
00109    std::pair<float, float> m_scale ;
00110 
00111    /// The robot's pose w.r.t. the map is specified using an (x, y)
00112    /// position and an angle indicating the direction in which it is
00113    /// "looking." This setting specifies the robot's initial pose.
00114    triple<float, float, float> m_initial_pose ;
00115 
00116    /// When the robot moves, it will experience some amount of
00117    /// translational and rotational slip. This parameter captures these
00118    /// errors and they are used in the prediction step of the FastSLAM
00119    /// algorithm.
00120    ///
00121    /// The value of this setting is expected to be a triple of floating
00122    /// point numbers. The first two numbers specify the amount of
00123    /// translational error (in mm) to expect in the x and y directions
00124    /// respectively. The third number specifies the amount of rotational
00125    /// error in degrees.
00126    ///
00127    /// NOTE: Ideally, these parameters will be empirically determined via
00128    /// either manual experiments designed to characterize and quantify
00129    /// systematic odometric errors or via some automated learning
00130    /// approach based on sample data.
00131    triple<float, float, float> m_errors ;
00132 
00133    /// The FastSLAM algorithm is a Rao-Blackwellized particle filter.
00134    /// This setting allows us to configure the number of particles to
00135    /// use.
00136    int m_num_particles ;
00137 
00138    /// In order to cut down on the amount of processing required by the
00139    /// FastSLAM algorithm and also to preserve particle diversity,
00140    /// Robolocust will only resample the particle population when the
00141    /// variance of the particle weights becomes high (thus indicating a
00142    /// lot of spread and high uncertainty in the state estimate).
00143    ///
00144    /// To make the actual determination as to when to resample,
00145    /// Robolocust computes the effective sample size by taking the
00146    /// reciprocal of the sum of the squares of all the weights. When the
00147    /// effective sample size (ESS) drops below some threshold, the
00148    /// particle filter's resampling step will kick in.
00149    ///
00150    /// The following setting specifies the effective sample size
00151    /// threshold. Usually, a good value to use for it would be half the
00152    /// number of particles. However, to disable the ESS check, you may
00153    /// set this to zero or to a value greater than the number of
00154    /// particles. In that case, resampling will take place after each and
00155    /// every iteration of the SLAM update.
00156    int m_ess_threshold ;
00157 
00158    /// During resampling, it might be a good idea to introduce some
00159    /// random particles just in case the filter has arrived at an
00160    /// incorrect state estimate. However, we don't want to insert random
00161    /// particles all the time.
00162    ///
00163    /// Therefore, Robolocust tracks the averages of the particle weights
00164    /// and inserts random particles only when the short-term average
00165    /// performs poorly w.r.t. the long-term average. An exponential
00166    /// filter is used to smooth the short and long-term particle weight
00167    /// averages to ensure that momentary glitches don't get misconstrued
00168    /// as incorrect state estimates.
00169    ///
00170    /// The following setting specifies the values of the exponential
00171    /// decays to use for filtering the short and long-term averages.
00172    /// These values are plugged into a running average formula for
00173    /// computing the averages. The long-term average's decay parameter
00174    /// must be much less than that of the short-term average.
00175    ///
00176    /// This setting expects to be given two numbers. The first is the
00177    /// decay parameter for the short-term average and the second is the
00178    /// decay parameter for the long-term average. Both numbers must lie
00179    /// between zero and one.
00180    std::pair<float, float> m_alpha ;
00181 
00182    /// As we know, in a particle filter, each particle makes a guess
00183    /// about the current state. These guesses are, of course, not
00184    /// entirely random; rather they are the result of probabilistic
00185    /// motion and sensor models. Good guesses, i.e., ones that match the
00186    /// sensor data, get more weight while poor ones are assigned lower
00187    /// weights and get filtered out. The overall state of the robot can
00188    /// then be gleaned by analyzing the particle population's density.
00189    ///
00190    /// There are many ways to perform particle density analysis. The one
00191    /// used by Robolocust's FastSLAM implementation works in the
00192    /// following manner:
00193    ///
00194    ///    1. First, find the particle with maximum weight
00195    ///    2. Then, find K particles whose states most closely match that
00196    ///       of the above particle
00197    ///    3. Compute the current state as the average of these K states
00198    ///
00199    /// The following setting specifies the value to use for K. It is
00200    /// specified as a percentage of the total number of particles. To use
00201    /// just the particle with max weight and not bother with computing
00202    /// the average of the top K particles, set this value to a negative
00203    /// number.
00204    int m_k ;
00205 
00206    /// Like all Bayesian filters, the FastSLAM algorithm has a prediction
00207    /// step, wherein the latest control command is used to predict a new
00208    /// state, and a correction step, wherein the latest sensor data is
00209    /// used to correct the state prediction. Since a laser range finder
00210    /// serves as lobot's primary sensing modality, the Robolocust
00211    /// implementation of FastSLAM employs a probabilistic beam model in
00212    /// its correction step. This beam model involves ray casting, a
00213    /// computationally intense operation. To cut down on the number of
00214    /// rays to be cast, we can configure Robolocust to consider only some
00215    /// of the distance measurements returned by the laser range finder.
00216    ///
00217    /// The following setting allows us to do that. It is expected to be a
00218    /// triple of integers. The first two numbers specify the starting and
00219    /// ending angles to consider (e.g., from -90 to +90 degrees). The
00220    /// third number is a step size. Thus, for example, if the beam_specs
00221    /// setting is "-90 90 15," then the FastSLAM algorithm will only
00222    /// consider the laser range finder readings corresponding to -90,
00223    /// -75, -60, -45, -30, -15, 0, 15, 30, 45, 60, 75 and 90 degrees,
00224    /// which makes for a total of 13 ray casting operations instead of
00225    /// (potentially) > 180.
00226    ///
00227    /// NOTE: Limiting the field of view of the laser range finder speeds
00228    /// up the FastSLAM algorithm but at the expense of map accuracy.
00229    triple<int, int, int> m_beam_specs ;
00230 
00231    /// The probabilistic beam model mentioned above works by computing
00232    /// the expected range reading from the current state estimate (i.e.,
00233    /// robot pose and occupancy map) and then seeing how well the actual
00234    /// distance measurements match the expected ones. We expect particles
00235    /// with good state estimates to match the actual sensor data better
00236    /// than those with poor estimates. Thus, good particles will get
00237    /// higher weights and the particle filter will pick those particles
00238    /// while culling the poor ones from the particle population.
00239    ///
00240    /// To rate the state estimates made by different particles, we run
00241    /// the actual range reading through the formula for a normal
00242    /// distribution centered at the expected range. This will produce a
00243    /// number that we can use for the particle weight. The following
00244    /// setting specifies the standard deviation for the above-mentioned
00245    /// application of the normal distribution formula. It is a distance
00246    /// (in mm).
00247    ///
00248    /// The value of this setting should reflect the amount of error we
00249    /// are willing to tolerate between the estimated range readings and
00250    /// the actual ones. It should also take into account the
00251    /// discretization parameters of the occupancy map.
00252    float m_beam_model_sigma ;
00253 
00254    /// The beam model described above computes the likelihood of a single
00255    /// distance measurement. Since the laser range finder returns
00256    /// multiple distance readings, we have to multiply the individual
00257    /// beam probabilities to obtain the final/total measurement
00258    /// likelihood.
00259    ///
00260    /// Unfortunately, as each beam's probability is a number between zero
00261    /// and one, multiplying the individual probabilities together will
00262    /// very rapidly result in extremely small numbers: of the order of
00263    /// ten raised to -50. This causes floating point instabilities.
00264    ///
00265    /// To work around this problem, we multiply individual beam
00266    /// probabilities by a large constant and multiply the resulting
00267    /// numbers instead of the original [0,1] likelihoods. The following
00268    /// setting specifies the value of the above-mentioned large constant.
00269    float m_beam_model_fudge ;
00270 
00271    /// For the beam model described above to work, we need to specify the
00272    /// minimum and maximum range readings the laser range finder can
00273    /// produce. Although the robot can determine this directly from the
00274    /// device itself, depending on the environment and on other factors,
00275    /// we may want the FastSLAM algorithm to consider a range different
00276    /// from the device's actual range. This setting allows us to do that.
00277    /// Its value should be two floating point numbers. The first one
00278    /// specifies the beam's minimum range (in mm) and the second one its
00279    /// maximum range (again in mm).
00280    range<float> m_beam_range ;
00281 
00282    /// In addition to the expected measurement computation, the
00283    /// probabilistic beam model should also consider various other
00284    /// factors that come into play and corrupt sensor data. Instead of
00285    /// explicitly modeling these other things, we simply lump all of them
00286    /// into a uniform distribution based on the range of distance
00287    /// readings returned by the LRF. Since this value is a constant, we
00288    /// can compute and store it with the parameters structure.
00289    float m_prob_rnd ;
00290 
00291    /// During the map update step, the SLAM algorithm uses each distance
00292    /// measurement to determine which cells in the occupancy grid are
00293    /// occupied. Since the grid is a discretized version of the world,
00294    /// there will, naturally, be discrepancies between the actual
00295    /// distance reading and the same range in grid coordinates.
00296    ///
00297    /// This setting specifies the amount of discrepancy that should be
00298    /// tolerated. As an example of how this works, let's say that the
00299    /// value of this setting is set to 100mm and that we get a reading
00300    /// (in some direction) of 622mm. Then, depending on the map's
00301    /// discretization parameters, as the algorithm traces the distance
00302    /// measurement within the occupancy grid in order to find the cell at
00303    /// which the measurement ends, it will accept a cell that is within
00304    /// 100mm of 622, i.e., from 522 to 722mm.
00305    float m_occ_range_error ;
00306 
00307    /// This setting specifies the minimum probability value a cell in the
00308    /// occupancy grid should have for it to be considered as being
00309    /// occupied. Cells with probabilities lower than this threshold will
00310    /// be considered as free space.
00311    ///
00312    /// This parameter's value should be a floating point number between
00313    /// zero and one.
00314    ///
00315    /// NOTE: Internally, this number gets converted to its equivalent
00316    /// log-odds form and the threshold check is then performed in
00317    /// "log-odds space."
00318    float m_occ_threshold ;
00319 
00320    /// As the robot moves around and senses its environment, its internal
00321    /// grid update and query algorithms will not always reliably hit the
00322    /// same cell over and over (due, for example, to sensor and actuator
00323    /// noise). Therefore, when we update a cell (x,y) in the occupancy
00324    /// grid, we should also update its immediate neighbours to ensure
00325    /// that subsequent queries near (x,y) are not entirely off the mark.
00326    ///
00327    /// The following setting specifies a weighting factor to use when
00328    /// updating a cell. This factor will applied to the cell in question
00329    /// and the remaining weight will be applied to its immediate
00330    /// neighbours. To illustrate how this works, let us say the update
00331    /// weight is set to 0.75. Then, when the robot updates a cell (x,y),
00332    /// it will apply 75% of the update delta (see the "occupancy_deltas"
00333    /// setting defined above) to (x,y) and divide the remaining 25% of
00334    /// the delta value equally between the remaining 8 cells in the
00335    /// immediate neighbourhood of (x,y). If (x,y) is in one of the
00336    /// corners of the map, the remaining 25% will be divided equally
00337    /// between the 3 neighbouring cells; if (x,y) is on an edge boundary
00338    /// other than a corner, the remaining 25% will be divided equally
00339    /// between the 5 immediate neighbours.
00340    ///
00341    /// As can be gleaned from the above discussion, the value of this
00342    /// setting should be a floating point number in the range [0,1].
00343    ///
00344    /// NOTE: Although it is referred to as the "update" weight, this
00345    /// parameter is also used when querying the map for occupancy
00346    /// likelihoods. Thus, when the robot wants to check the occupancy
00347    /// likelihood of some location (x,y), this weighting factor (e.g.,
00348    /// 75%) will be applied to the actual value stored in that cell and
00349    /// the remaining weight (25%) will be divided equally between the
00350    /// immediate neighbours of (x,y) to produce a weighted sum for the
00351    /// final occupancy value retrieved from the grid.
00352    float m_update_weight ;
00353 
00354    /// Since odometry tends to be more error-prone than a laser range
00355    /// finder, Robolocust can be configured to use a scan matching
00356    /// algorithm to correct the raw odometry and use the corrected values
00357    /// to compute pose updates in the filter's prediction step. The
00358    /// following flag can be used to turn scan matching on or off
00359    /// (default is off).
00360    bool m_match_scans ;
00361 
00362    /// Although SLAM is designed to learn a map and localize the robot at
00363    /// the same time, we can configure the Robolocust system to only
00364    /// perform localization given a known map. The following setting
00365    /// specifies a file name for a map. The robot will read this map
00366    /// during initialization and then localize itself w.r.t. this map
00367    /// using the Monte Carlo Localization component of the SLAM
00368    /// algorithm.
00369    ///
00370    /// The map file is expected to be a plain text file containing
00371    /// coordinates of obstacles. Each obstacle is specified using four
00372    /// coordinates. The first two coordinates specify the location of the
00373    /// lower left corner of a rectangle where the obstacle "begins" and
00374    /// the next two are for the upper right corner where the obstacle
00375    /// "ends."
00376    ///
00377    /// The coordinates are all expressed in the map's real/physical
00378    /// coordinate system.
00379    ///
00380    /// NOTE: This setting is actually part of the survey behaviour.
00381    std::string m_map_file ;
00382 
00383    /// This member holds the geometry specs for the map's visualization.
00384    Drawable::Geometry m_geometry ;
00385 
00386    /// Private constructor because this class is a singleton.
00387    SlamParams() ;
00388    friend class singleton<SlamParams> ; // boilerplate
00389 
00390 public:
00391    /// This function returns the size of each cell of the occupancy grid,
00392    /// i.e., the amount of actual physical area each cell in the grid
00393    /// takes up.
00394    ///
00395    /// NOTE: Each cell in the occupancy grid is a square. This function
00396    /// returns the length of a side of the square.
00397    static float map_cell_size() {return instance().m_cell_size ;}
00398 
00399    /// This function returns extents of the map in physical coordinates.
00400    static void map_extents(float* L, float* R, float* B, float* T) ;
00401 
00402    /// This function returns the map extents via an array of four
00403    /// numbers ordered like so: left, right, bottom, top. The extents are
00404    /// in physical coordnates.
00405    static void map_extents(float ext[4]) ;
00406 
00407    /// This function returns a pointer to the internal array holding the
00408    /// map extents. This is a convenience function. Clients should not
00409    /// misuse the returned pointer.
00410    static const float* map_extents() {return instance().m_extents ;}
00411 
00412    /// These function return the size of the occupancy grid, i.e., the
00413    /// number of cells in the horizontal and vertical directions. This
00414    /// number is derived from the map discretization as specified in the
00415    /// config file.
00416    //@{
00417    static int map_width()  {return instance().m_width  ;}
00418    static int map_height() {return instance().m_height ;}
00419    //@}
00420 
00421    /// This function returns the max distance that can be traversed
00422    /// within the map.
00423    static float max_map_distance() {return instance().m_max_distance ;}
00424 
00425    /// These functions return the scale factors for converting
00426    /// real/physical coordinates to grid coordinates and vice versa.
00427    //@{
00428    static float Sx() {return instance().m_scale.first  ;}
00429    static float Sy() {return instance().m_scale.second ;}
00430    //@}
00431 
00432    /// This function returns the robot's initial pose as configured by
00433    /// the user.
00434    static const triple<float, float, float>& initial_pose() {
00435       return instance().m_initial_pose ;
00436    }
00437 
00438    /// These functions return the translational and rotational errors for
00439    /// the robot's motion as specified by the user.
00440    //@{
00441    static float x_error() {return instance().m_errors.first  ;}
00442    static float y_error() {return instance().m_errors.second ;}
00443    static float t_error() {return instance().m_errors.third  ;}
00444    //@}
00445 
00446    /// This function returns the number of particles to be used by the
00447    /// FastSLAM algorithm.
00448    static int num_particles() {return instance().m_num_particles ;}
00449 
00450    /// This function returns the threshold value for the effective sample
00451    /// size test, which determines when the particle filter will resample
00452    /// its particle population.
00453    static int ess_threshold() {return instance().m_ess_threshold ;}
00454 
00455    /// These functions return the decay parameters for the short and
00456    /// long-term averages used to determine the appropriate time and
00457    /// number of random particles to be inserted.
00458    //@{
00459    static float alpha_fast() {return instance().m_alpha.first  ;}
00460    static float alpha_slow() {return instance().m_alpha.second ;}
00461    //@}
00462 
00463    /// This function returns the number of particles that should most
00464    /// closely match the particle with max weight when deciding the
00465    /// current best hypothesis regarding the robot's pose and environment
00466    /// map.
00467    static int num_matches() {return instance().m_k ;}
00468 
00469    /// These functions return various parameters used by the
00470    /// probabilistic beam model.
00471    //@{
00472    static int   beam_start()           {return instance().m_beam_specs.first ;}
00473    static int   beam_end()             {return instance().m_beam_specs.second;}
00474    static int   beam_step()            {return instance().m_beam_specs.third ;}
00475    static float beam_sigma()           {return instance().m_beam_model_sigma ;}
00476    static float beam_fudge()           {return instance().m_beam_model_fudge ;}
00477    static range<float> beam_range()    {return instance().m_beam_range       ;}
00478    static float beam_prob_rnd()        {return instance().m_prob_rnd         ;}
00479    static float beam_occ_range_error() {return instance().m_occ_range_error  ;}
00480    //@}
00481 
00482    /// This function returns the minimum occupancy likelihood
00483    /// corresponding to the "occupied" state.
00484    static float occ_threshold() {return instance().m_occ_threshold ;}
00485 
00486    /// This function returns the amount of "spread" associated with
00487    /// checking or setting a cell's likelihood across its immediate
00488    /// neighbours.
00489    static float update_weight() {return instance().m_update_weight ;}
00490 
00491    /// This function returns true if scan matching is enabled; false
00492    /// otherwise.
00493    static bool match_scans() {return instance().m_match_scans ;}
00494 
00495    /// If SLAM is configured to perform localization only, i.e., no
00496    /// mapping, then the user will be expected to specify a file name
00497    /// containing the known map to be used for localization. This
00498    /// function returns the map file name.
00499    static std::string map_file() {return instance().m_map_file ;}
00500 
00501    /// This function returns true if SLAM is configured to perform
00502    /// localization only. In this mode, the user must supply a known map
00503    /// and only the Monte Carlo Localization component of the SLAM
00504    /// algorithm will be used. This mode is useful for testing the
00505    /// localization part of SLAM in isolation from the mapping part.
00506    static bool localization_mode() {return ! instance().m_map_file.empty() ;}
00507 
00508    /// This function returns true if SLAM is configured to perform both
00509    /// localization and mapping. This is the usual operational mode for a
00510    /// SLAM algorithm.
00511    static bool slam_mode() {return ! localization_mode() ;}
00512 
00513    /// This function returns the geometry of the map's UI drawable. It is
00514    /// useful when figuring out transformations for map related rendering
00515    /// operations.
00516    static Drawable::Geometry map_geometry() {return instance().m_geometry ;}
00517 } ;
00518 
00519 //-----------------------------------------------------------------------
00520 
00521 } // end of namespace encapsulating this file's definitions
00522 
00523 #endif
00524 
00525 /* So things look consistent in everyone's emacs... */
00526 /* Local Variables: */
00527 /* indent-tabs-mode: nil */
00528 /* End: */
Generated on Sun May 8 08:41:31 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3