LoSurvey.H

Go to the documentation of this file.
00001 /**
00002    \file  Robots/LoBot/control/LoSurvey.H
00003    \brief A cartographic behaviour, i.e., a behaviour that builds the
00004    obstacle map used by Robolocust.
00005 
00006    This file defines a class that implements a map-making behaviour. This
00007    behaviour uses a SLAM algorithm to build a map and record the robot's
00008    trajectory within this map.
00009 */
00010 
00011 // //////////////////////////////////////////////////////////////////// //
00012 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00013 // by the University of Southern California (USC) and the iLab at USC.  //
00014 // See http://iLab.usc.edu for information about this project.          //
00015 // //////////////////////////////////////////////////////////////////// //
00016 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00017 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00018 // in Visual Environments, and Applications'' by Christof Koch and      //
00019 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00020 // pending; application number 09/912,225 filed July 23, 2001; see      //
00021 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00022 // //////////////////////////////////////////////////////////////////// //
00023 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00024 //                                                                      //
00025 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00026 // redistribute it and/or modify it under the terms of the GNU General  //
00027 // Public License as published by the Free Software Foundation; either  //
00028 // version 2 of the License, or (at your option) any later version.     //
00029 //                                                                      //
00030 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00031 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00032 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00033 // PURPOSE.  See the GNU General Public License for more details.       //
00034 //                                                                      //
00035 // You should have received a copy of the GNU General Public License    //
00036 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00037 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00038 // Boston, MA 02111-1307 USA.                                           //
00039 // //////////////////////////////////////////////////////////////////// //
00040 //
00041 // Primary maintainer for this file: mviswana usc edu
00042 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/Robots/LoBot/control/LoSurvey.H $
00043 // $Id: LoSurvey.H 13523 2010-06-07 00:22:03Z mviswana $
00044 //
00045 
00046 #ifndef LOBOT_SURVEY_BEHAVIOUR_DOT_H
00047 #define LOBOT_SURVEY_BEHAVIOUR_DOT_H
00048 
00049 //------------------------------ HEADERS --------------------------------
00050 
00051 // lobot headers
00052 #include "Robots/LoBot/control/LoBehavior.H"
00053 
00054 #include "Robots/LoBot/slam/LoFastSLAM.H"
00055 #include "Robots/LoBot/slam/LoOdometry.H"
00056 
00057 #include "Robots/LoBot/io/LoRobot.H"
00058 #include "Robots/LoBot/thread/LoCondition.H"
00059 #include "Robots/LoBot/misc/factory.hh"
00060 
00061 // Standard C++ headers
00062 #include <memory>
00063 
00064 //----------------------------- NAMESPACE -------------------------------
00065 
00066 namespace lobot {
00067 
00068 //------------------------- CLASS DEFINITION ----------------------------
00069 
00070 /**
00071    \class lobot::Survey
00072 
00073    \brief A behaviour for updating the Robolocust occupancy grid.
00074 
00075    This class implements a behaviour that uses a SLAM algorithm to build
00076    an occupancy map of lobot's environment and record its trajectory
00077    within this map.
00078 
00079    NOTE: This behaviour does not vote for any motor actions.
00080 */
00081 class Survey : public Behavior {
00082    // Prevent copy and assignment
00083    Survey(const Survey&) ;
00084    Survey& operator=(const Survey&) ;
00085 
00086    // Handy type to have around in a derived class
00087    typedef Behavior base ;
00088 
00089    // Boilerplate code to make the generic factory design pattern work
00090    friend  class subfactory<Survey, base> ;
00091    typedef register_factory<Survey, base> my_factory ;
00092    static  my_factory register_me ;
00093 
00094    /// The survey behaviour uses a SLAM algorithm to build a map of the
00095    /// robot's surroundings and keep track of its trajectory.
00096    std::auto_ptr<FastSLAM> m_slam ;
00097 
00098    /// Since SLAM updates can be fairly intense and take a while to
00099    /// complete, this class uses a flag to keep track of when SLAM is in
00100    /// progress and when it is not. This is necessitated by the fact that
00101    /// odometric updates take place in the main thread. If SLAM is
00102    /// currently in progress, then the low-level odometric updates should
00103    /// be accumulated till the SLAM update is done. After the SLAM update
00104    /// is complete, it can be retriggered with the accumulated odometry.
00105    bool m_slam_busy ;
00106 
00107    /// This data member keeps track of the low-level odometry. It
00108    /// accumulates the low-level odometry packets. When the SLAM
00109    /// algorithm is ready for its next iteration, the Survey behaviour
00110    /// will pass the accumulated odometry to the SLAM module and reset
00111    /// this variable so that it can start accumulating odometry again.
00112    Odometry m_odometry ;
00113 
00114    /// As mentioned above, since SLAM updates can take a while, we must
00115    /// accumulate low-level odometry until the SLAM algorithm is ready to
00116    /// run its next iteration. The m_odometry data member is used to
00117    /// accumulate odometry. When the SLAM module is ready, the contents
00118    /// of m_odometry will be copied to this data member, viz., ut, and
00119    /// m_odometry will be reset so it can start accumulating odometry
00120    /// afresh.
00121    ///
00122    /// NOTE: This data member is named ut to denote the latest control
00123    /// input u at time t to the SLAM algorithm.
00124    Odometry ut ;
00125 
00126    /// Low-level odometric updates occur in the main thread whereas SLAM
00127    /// takes place in the survey behaviour's thread. To ensure that the
00128    /// SLAM algorithm is invoked with minimal amounts of odometric
00129    /// accumulation, we use a condition variable to signal the survey
00130    /// behaviour's thread whenever the main thread receives a low-level
00131    /// odometry packet.
00132    Condition m_odometry_cond ;
00133 
00134    /// The lobot::Condition class requires a function or function object
00135    /// to be passed to its waiting and signaling methods. This inner
00136    /// helper class is used to implement a function object that can be
00137    /// used in conjunction with lobot::Condition.
00138    ///
00139    /// This class takes two type parameters:
00140    ///
00141    ///     F -- function or function object implementing the predicate
00142    ///          required by lobot::Condition
00143    ///     R -- the return type for F; usually bool
00144    ///
00145    /// On instantiation, the cond_helper should be given a reference to
00146    /// the Survey object and a function or function object that will
00147    /// implement the desired condition variable test. When its function
00148    /// call operator is invoked, cond_helper will in turn call F, passing
00149    /// it the Survey object, and will return to lobot::Condition whatever
00150    /// F returns.
00151    ///
00152    /// Thus, this helper class acts as an intermediary and a binder. In
00153    /// its role as an intermediary, it transmits/forwards
00154    /// lobot::Condition's predicate call to F and F's return value to
00155    /// lobot::Condition. In its role as a binder, it binds the Survey
00156    /// object to F, since any meaninful synchronization actions between
00157    /// the main and survey behaviour threads will require a Survey object
00158    /// whereas the generic lobot::Condition interface calls functions
00159    /// without any arguments.
00160    template<typename F, typename R = bool>
00161    class cond_helper {
00162       Survey& survey ;
00163       F pred ;
00164    public:
00165       cond_helper(Survey&, F) ;
00166       R operator()() {return pred(survey) ;}
00167    } ;
00168 
00169    // The cond_helper needs access to the Survey class's innards to
00170    // properly keep track of odometry, the SLAM algorithm's state, etc.
00171    template<typename F, typename R> friend class cond_helper ;
00172 
00173    /// This inner class acts as a predicate for signaling the Survey
00174    /// behaviour's thread when new odometry is available. If the SLAM
00175    /// algorithm is currently busy, it will take care of accumulating the
00176    /// odometry. Otherwise, it will check if the odometric thresholds set
00177    /// by the user have been crossed and, if so, will return true to
00178    /// trigger the SLAM update.
00179    class odometry_helper {
00180       int distance, angle ;
00181    public:
00182       odometry_helper(int dist, int ang) ;
00183       bool operator()(Survey&) ;
00184    } ;
00185 
00186    /// This inner class acts as a predicate for blocking the Survey
00187    /// behaviour's thread until the configured odometric thresholds have
00188    /// been crossed. Once this condition is met, the Survey behaviour
00189    /// will trigger the next SLAM update. Before the update is triggered,
00190    /// the SLAM algorithm will be marked busy.
00191    struct threshold_helper {
00192       bool operator()(Survey&) ;
00193    } ;
00194 
00195    /// This inner class acts as a function object for resetting the state
00196    /// of the SLAM module. When this flag is cleared, the main thread's
00197    /// odometric accumulation will cease and the Survey behaviour will be
00198    /// signaled to trigger the next SLAM update.
00199    struct reset_helper {
00200       void operator()(Survey&) ;
00201    } ;
00202 
00203    /// Since it can be cumbersome to directly instantiate the cond_helper
00204    /// template, we use these helper functions to return the desired
00205    /// object with all the correct types and parameters.
00206    //@{
00207    cond_helper<odometry_helper> odometry_update(int dist, int ang) {
00208       return cond_helper<odometry_helper>(*this, odometry_helper(dist, ang)) ;
00209    }
00210 
00211    cond_helper<threshold_helper> threshold_check() {
00212       return cond_helper<threshold_helper>(*this, threshold_helper()) ;
00213    }
00214 
00215    cond_helper<reset_helper, void> reset_slam_busy_flag() {
00216       return cond_helper<reset_helper, void>(*this, reset_helper()) ;
00217    }
00218    //@}
00219 
00220    /// A private constructor because behaviours are instantiated with an
00221    /// object factory and not directly by clients.
00222    Survey() ;
00223 
00224    /// Most behaviours rely on the base class to implement the action
00225    /// processing loop in lobot::Behavior::run(). By default, that
00226    /// function checks the lobot::Shutdown signal and calls the virtual
00227    /// action() method in a loop. Successive iterations are separated by
00228    /// a short sleep.
00229    ///
00230    /// However, for the survey behaviour, we need to override the base
00231    /// class's main loop because a sleep-based loop is inappropriate. If
00232    /// we were to rely on the default run function, then we could
00233    /// potentially accumulate quite a bit of odometry before performing a
00234    /// SLAM update. In general, we would like to invoke the SLAM
00235    /// algorithm with minimal odometric accumulation so that the map and
00236    /// pose get updated with small, incremental motions rather than in
00237    /// relatively large jumps.
00238    ///
00239    /// Therefore, this class needs to provide its own implementation of
00240    /// the run function.
00241    void run() ;
00242 
00243    /// Some things to do before commencing regular action processing.
00244    void pre_run() ;
00245 
00246    /// This is the callback function for the low-level updates of the
00247    /// robot's odometry.
00248    static void sensor_hook(const Robot::Sensors&, unsigned long client_data) ;
00249 
00250    /// This function keeps track of the robot's low-level odometry. It
00251    /// executes in the context of the main thread. Thus, to let the
00252    /// survey behaviour know that new odometry is available, it uses the
00253    /// condition variable m_odometry_cond to signal the survey
00254    /// behaviour's thread.
00255    void accumulate(int distance, int angle) ;
00256 
00257    /// This method triggers the SLAM update using the latest control and
00258    /// sensor inputs. It is called by the run function, which takes care
00259    /// of the necessary signaling/synchronization with the main thread.
00260    void action() ;
00261 
00262    /// Visualization support: functions for rendering the FastSLAM
00263    /// algorithm's particles on the application-wide map so we can see
00264    /// how FastSLAM is working...
00265    //@{
00266    static void render_particles(unsigned long client_data) ;
00267    void render_particles() ;
00268    //@}
00269 
00270    /// Clean-up.
00271    ~Survey() ;
00272 } ;
00273 
00274 //------------------- TEMPLATE FUNCTION DEFINITIONS ---------------------
00275 
00276 // Constructor for the Survey behaviour's odometry condition variable's
00277 // helper function object.
00278 template<typename F, typename R>
00279 Survey::cond_helper<F,R>::cond_helper(Survey& s, F f)
00280    : survey(s), pred(f)
00281 {}
00282 
00283 //-----------------------------------------------------------------------
00284 
00285 } // end of namespace encapsulating this file's definitions
00286 
00287 #endif
00288 
00289 /* So things look consistent in everyone's emacs... */
00290 /* Local Variables: */
00291 /* indent-tabs-mode: nil */
00292 /* End: */
Generated on Sun May 8 08:41:23 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3