00001 /** 00002 \file Robots/LoBot/misc/LoExperiment.H 00003 \brief An object to store a parsed metrics log. 00004 00005 This file defines a class that implements a simple object for storing 00006 a parsed metrics log, i.e., this class holds all the relevant data for 00007 an experiment conducted to record the robot's trajectory from start 00008 position to goal using an LGMD-based obstacle avoidance algorithm. 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/metlog/LoExperiment.H $ 00043 // $Id: LoExperiment.H 14285 2010-12-01 17:33:15Z mviswana $ 00044 // 00045 00046 #ifndef LOBOT_EXPERIMENT_DOT_H 00047 #define LOBOT_EXPERIMENT_DOT_H 00048 00049 //------------------------------ HEADERS -------------------------------- 00050 00051 // lobot headers 00052 #include "Robots/LoBot/metlog/LoPointList.H" 00053 #include "Robots/LoBot/metlog/LoPointTypes.H" 00054 #include "Robots/LoBot/util/LoStats.H" 00055 00056 // Standard C++ headers 00057 #include <string> 00058 #include <vector> 00059 00060 //----------------------------- NAMESPACE ------------------------------- 00061 00062 namespace lobot { 00063 00064 //------------------------- CLASS DEFINITION ---------------------------- 00065 00066 /** 00067 \class lobot::Experiment 00068 \brief A class for storing all the relevant info from 00069 trajectory-related metrics logs. 00070 00071 This class is used to hold all of the relevant data from a metlog and 00072 provide a convenient API for assisting with various number crunching 00073 tasks for the data analysis. 00074 */ 00075 class Experiment { 00076 // Prevent copy and assignment 00077 Experiment(const Experiment&) ; 00078 Experiment& operator=(const Experiment&) ; 00079 00080 /// Each experiment is loaded from a metrics log. This data member is 00081 /// used to store the name of that log file. 00082 std::string m_name ; 00083 00084 /// These two data members hold the experiment's start and end times 00085 /// expressed as the number of milliseconds elapsed since the Unix 00086 /// epoch. 00087 /// 00088 /// DEVNOTE: We use "finis" rather than "finish" because "finis" is 00089 /// the same length string as "start" and this makes code line up 00090 /// nicely. 00091 long long int m_start_time, m_finis_time ; 00092 00093 /// As the robot moves from start to finish, it periodically records 00094 /// its position. Some of these position checks correspond to specific 00095 /// events such as an emergency stop, an extrication or a bump. Most 00096 /// of them are simply trajectory information recorded for analysis. 00097 /// These lists are used to store the positions in their proper 00098 /// "slots." 00099 //@{ 00100 PointList m_trajectory ; 00101 PointList m_emergency_stop ; 00102 PointList m_extricate ; 00103 PointList m_lgmd_extricate ; 00104 PointList m_bump ; 00105 //@} 00106 00107 /// In addition to recording its position, the robot also periodically 00108 /// records its speed. This list holds all the speed readings. 00109 std::vector<float> m_speed ; 00110 00111 /// These data members record the means and standard deviations for 00112 /// the different kinds of events we are interested in analyzing from 00113 /// all the experiments in a dataset. In addition to the means and 00114 /// standard deviations (which are used to produce pretty plots), we 00115 /// also record some other values such as the number of data points, 00116 /// the sum of all the data and the sum of the squares. These values 00117 /// are used for two-way ANOVA. 00118 /// 00119 /// DEVNOTE: This class does double duty: it stores the information 00120 /// extracted by the metlog parsing process and is also used to store 00121 /// the final data analysis results. 00122 /// 00123 /// Yes, this is lousy design. 00124 /// 00125 /// However, since lomet was originally conceived as a 00126 /// quick-and-dirty, one-time use, throwaway kind of program, 00127 /// expediency was put above design correctness, extensibility, 00128 /// robustness and all that jazz. 00129 //@{ 00130 typedef generic_stats<int> istats ; // shortcut to make code line up 00131 typedef generic_stats<float> fstats ; // shortcut to make code line up 00132 istats m_emstop_stats, 00133 m_lrf_extr_stats, m_lgmd_extr_stats, m_total_extr_stats ; 00134 fstats m_lgmd_success_stats, m_extr_success_stats, m_duration_stats ; 00135 //@} 00136 00137 /// A private constructor because Experiment objects are created with 00138 /// a "named constructor" to ensure that clients don't create them on 00139 /// the stack. 00140 Experiment(const std::string& name) ; 00141 00142 public: 00143 /// This method can be used to create Experiment objects. This "named 00144 /// constructor" ensures that all instances of this class are created 00145 /// with the new operator and not as local objects on the stack. 00146 static Experiment* create(const std::string& name) ; 00147 00148 /// Return this experiment's name. 00149 std::string name() const {return m_name ;} 00150 00151 /// These methods record the times at which the experiment began and 00152 /// ended. These time stamps are expressed as the number of 00153 /// milliseconds elapsed since the Unix epoch. 00154 /// 00155 /// These methods are meant to be used by the metlog parsing module, 00156 /// i.e., within the lex-generated rules in LoMetlogParser.l. 00157 /// 00158 /// DEVNOTE: We use "finis" rather than "finish" because "finis" is 00159 /// the same length string as "start" and this makes code line up 00160 /// nicely (as can be seen with the definitions of these functions). 00161 //@{ 00162 void start_time(long long int t) {m_start_time = t ;} 00163 void finis_time(long long int t) {m_finis_time = t ;} 00164 //@} 00165 00166 /// This function returns the duration of the experiment in 00167 /// milliseconds. 00168 int duration() const {return m_finis_time - m_start_time ;} 00169 00170 /// These methods add trajectory info to their corresponding lists. 00171 /// They are meant to be used by the metlog parsing module, i.e., 00172 /// within the lex-generated rules in LoMetlogParser.l. 00173 //@{ 00174 void add_trajectory(int x, int y) {m_trajectory.add(x, y) ;} 00175 void add_emergency_stop(int x, int y) {m_emergency_stop.add(x, y) ;} 00176 void add_extricate(int x, int y) {m_extricate.add(x, y) ;} 00177 void add_lgmd_extricate(int x, int y) {m_lgmd_extricate.add(x, y) ;} 00178 void add_bump(int x, int y) {m_bump.add(x, y) ;} 00179 //@} 00180 00181 /// This method adds a point to the named list. 00182 void add_point(PointListName, int x, int y) ; 00183 00184 /// This method adds an entire point list to the one named by its 00185 /// parameter. It is meant to be used by the lomet program's main 00186 /// thread for building the result "experiment" from the analysis 00187 /// performed on the entire dataset. 00188 void point_list(PointListName, const PointList&) ; 00189 00190 /// These functions return the sizes of the different point lists 00191 /// maintained by an experiment. 00192 //@{ 00193 int trajectory_size() const {return m_trajectory.size() ;} 00194 int emergency_stop_size() const {return m_emergency_stop.size() ;} 00195 int extricate_size() const {return m_extricate.size() ;} 00196 int lgmd_extricate_size() const {return m_lgmd_extricate.size() ;} 00197 int bump_size() const {return m_bump.size() ;} 00198 //@} 00199 00200 /// This function returns the size of the named point list. 00201 int size(PointListName) const ; 00202 00203 /// This method returns the named point list. 00204 /// 00205 /// NOTE: This method returns a reference to an internal data 00206 /// structure. Clients should consider the returned data structure 00207 /// read-only, i.e., they should refrain from casting away the 00208 /// constness of the returned object and doing nasty things to it. 00209 const PointList& point_list(PointListName) const ; 00210 00211 /// This method adds a speed reading to the list of speed readings 00212 /// subject to the condition that the speed actually represents a 00213 /// forward driving speed. This information is used to compute the 00214 /// average forward driving speed over the entire run. 00215 /// 00216 /// This method is meant to be used by the metlog parsing module, 00217 /// i.e., with the lex-generated rules in LoMetlogParser.l. 00218 void add_speed(float) ; 00219 00220 /// This method adds all the speed readings in the given std::vector 00221 /// to this object's list of speed readings. 00222 /// 00223 /// NOTE: This method is meant to be used by the lomet main thread for 00224 /// computing the final result, which is represented using an instance 00225 /// of this class. Yes, dreadful design. Ideally, we should have split 00226 /// the result related functionality into a separate class, viz., 00227 /// Result, which could have used private derivation from Experiment 00228 /// to take advantage of the functionality encapsulated here. Anyway, 00229 /// since the lomet program was originally conceived as a one-time, 00230 /// throwaway sort of thing, these shortcuts were deemed acceptable. 00231 void speed_list(const std::vector<float>&) ; 00232 00233 /// This function returns an std::vector of floats containing the 00234 /// speed readings recorded by this experiment. 00235 /// 00236 /// WARNING: This function actually returns a const reference to an 00237 /// internal data structure. Yes, yes, bad design. Anyhoo, clients are 00238 /// advised/requested to treat the returned object as read-only. 00239 const std::vector<float>& speed_list() const {return m_speed ;} 00240 00241 /// These functions record the means and standard deviations for 00242 /// various things such as the time-to-goal, number of extrication 00243 /// events, LGMD-based obstacle avoidance algorithm success rate, etc. 00244 /// These functions are meant to be used by the lomet main thread as 00245 /// part of the results computation (double duty, bad design, etc.; 00246 /// see comments appearing earlier). 00247 /// 00248 /// NOTE: In addition to the means and standard deviations, we also 00249 /// record some other values such as the n and sum and sum of squares. 00250 /// These are useful for two-way ANOVA. 00251 //@{ 00252 void emergency_stop_stats (const istats& s) {m_emstop_stats = s ;} 00253 void lrf_extricate_stats (const istats& s) {m_lrf_extr_stats = s ;} 00254 void lgmd_extricate_stats (const istats& s) {m_lgmd_extr_stats = s ;} 00255 void total_extricate_stats (const istats& s) {m_total_extr_stats = s ;} 00256 void lgmd_success_stats (const fstats& s) {m_lgmd_success_stats = s ;} 00257 void extricate_success_stats(const fstats& s) {m_extr_success_stats = s ;} 00258 void duration_stats (const fstats& s) {m_duration_stats = s ;} 00259 //@} 00260 00261 /// This method saves the experiment to a file whose name is the same 00262 /// as the experiment's name. It is meant to be called by the lomet 00263 /// main thread for saving the data analysis results. 00264 /// 00265 /// It returns false to indicate that saving failed; this would happen 00266 /// if there is already an extant file that has the same name as this 00267 /// experiment. This feature ensures that metlogs loaded and parsed 00268 /// into an Experiment won't be overwritten if a client inadvertently 00269 /// calls this function. It also ensures that a previous result file 00270 /// won't be overwritten unless the user explicitly takes some action 00271 /// to allow the save to proceed, e.g., delete the old result file or 00272 /// reconfigure the program to save results to a differently named 00273 /// file. 00274 bool save() const ; 00275 00276 /// Debugging support: dumps all the info to a file named dump-foo, 00277 /// where "foo" is actually the experiment's name, i.e., the same as 00278 /// the name of the log file from which this data object was created. 00279 void dump() const ; 00280 } ; 00281 00282 //----------------------------------------------------------------------- 00283 00284 } // end of namespace encapsulating this file's definitions 00285 00286 #endif 00287 00288 /* So things look consistent in everyone's emacs... */ 00289 /* Local Variables: */ 00290 /* indent-tabs-mode: nil */ 00291 /* End: */