iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Manager.H
Go to the documentation of this file.
1 /*! @file
2  @author Laurent Itti
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 #ifndef INCLUDE_NRT_CORE_MODEL_MANAGER_H
36 #define INCLUDE_NRT_CORE_MODEL_MANAGER_H
37 
39 #include <nrt/Core/Typing/Enum.H>
40 
41 #include <vector>
42 
43 namespace nrt
44 {
45  //! Namespace for Manager parameters
46  namespace manager
47  {
48  static ParameterCategory const ManagerParamCateg("General Options");
49 
50  NRT_DECLARE_PARAMETER(help, bool, "Print this help message", false, ManagerParamCateg);
51 
52  NRT_DECLARE_PARAMETER_WITH_CALLBACK(profilebb, bool, "Profile Blackboard operation", false, ManagerParamCateg);
53 
54  NRT_DECLARE_PARAMETER_WITH_CALLBACK(profilelog, bool, "Profile log messages", false, ManagerParamCateg);
55 
56  NRT_DECLARE_PARAMETER(onlineprofile, bool, "Write profile messages online", false, ManagerParamCateg);
57 
58  NRT_DECLARE_PARAMETER(profilesaveto, std::string, "Profile log file to save to", "", ManagerParamCateg);
59 
60  //! Define the possible log levels
61  NRT_DEFINE_ENUM_CLASS(LogLevel, (fatal) (warning) (info) (debug) (bbdebug));
62 
63  NRT_DECLARE_PARAMETER_WITH_CALLBACK(loglevel, LogLevel, "Set the minimum log level to display",
64  LogLevel::info, LogLevel_Values);
65  }
66 
67  // ######################################################################
68  //! Manager of an entire model of Components
69  /*! A Manager should be the top-level Component of any hierarchy of Components. It is primarily responsible for
70  handling the setting of Parameters via the command-line or otherwise.
71 
72  Users should only need to construct a Manager, add any subComponents to it, and then call start(), which will
73  parse all command line options (via parseCommandLine()), bind them to their relevant Parameters, and call start()
74  on all subComponents (which in turn calls start() on all of their subComponents, etc.).
75 
76  Beware that the Manager is not thread-safe so make sure only one thread at a time calls init(), start(), etc,
77  typically this would be your main thread.
78 
79  The Manager resets the nrt::CentralTimer at each start(), such that durations returned by the nrt::CentralTimer
80  are since the last start().
81 
82  \ingroup component */
83  class Manager : public Component,
84  public Parameter<manager::help, manager::profilebb, manager::profilelog, manager::onlineprofile,
85  manager::profilesaveto, manager::loglevel>
86  {
87  public:
88  //! Constructor without command-line args
89  /*! The command-line args should be passed later using setArgs(), before you init(), otherwise the manager will
90  issue a non-fatal warning. */
91  Manager(std::string const & instanceID = "TheManager");
92 
93  //! Constructor
94  /*! Creates the Manager, and optionally takes in the command line arguments. */
95  Manager(int argc, char const* argv[], std::string const & instanceID = "TheManager");
96 
97  //! Set the command-line arguments, call this before start() if args were not passed at construction
98  void setCommandLineArgs(int argc, char const* argv[]);
99 
100  //! Destructor
101  virtual ~Manager();
102 
103  //! @name Component hierarchies
104  //! @{
105 
106  //! Pseudo-constructor: construct a top-level Component
107  /*! A component of type Comp (which must derive from nrt::Component) will be created and added as a sub-component
108  of the manager (making it a so-called top-level component). The child logically "belongs" to the Manager, and
109  will automatically be deleted when the Manager is deleted. In addition to construction, the component will be
110  brought to the same runstate as the Manager. */
111  template <class Comp>
112  std::shared_ptr<Comp> addComponent(std::string const & instanceName = "");
113 
114  //! Use addComponent() on the Manager as opposed to nrt::Component::addSubComponent()
115  template <class Comp>
116  std::shared_ptr<Comp> addSubComponent(std::string const & instanceName) = delete;
117 
118  //! Remove a top-level Component from the Manager, by shared_ptr
119  /*! \note Beware that the passed shared_ptr is invalidated in the process. A warning is issued if the use_count is
120  not down to zero after that (i.e., there are additional shared_ptr pointers to this Component floating around,
121  which prevent it from actually being deleted. */
122  template <class Comp>
123  void removeComponent(std::shared_ptr<Comp> & component);
124 
125  //! Use removeComponent() on the Manager as opposed to nrt::Component::removeSubComponent()
126  template <class Comp>
127  void removeSubComponent(std::shared_ptr<Comp> & component) = delete;
128 
129  //! Remove a top-level Component from the Manager, by instance name
130  void removeComponent(std::string const & instanceName);
131 
132  //! Use removeComponent() on the Manager as opposed to nrt::Component::removeSubComponent()
133  void removeSubComponent(std::string const & instanceName) = delete;
134 
135  //! Get a top-level component by instance name
136  /*! This method does a dynamic_pointer_cast to Comp if it is not the default (nrt::Component). Throws if component
137  is not found by instance name, or it is found but not of type Comp (if Comp is specified). Note that once you
138  hold a shared_ptr to a Component, it is guaranteed that the component will not be destroyed until that
139  shared_ptr is released. If the NRT system tries to destroy the component (e.g., someone calls
140  removeSubComponent()), the component will be un-initialized and its parent will be unset, so it will not be
141  fully operational and will be actually deleted when the last shared_ptr to it runs out of scope. */
142  template <class Comp = nrt::Component>
143  std::shared_ptr<Comp> getComponent(std::string const & instanceName) const;
144 
145  //! Use getComponent() on the Manager as opposed to nrt::Component::getSubComponent()
146  template <class Comp>
147  std::shared_ptr<Comp> getSubComponent(std::string const & instanceName) const = delete;
148 
149  //! @}
150 
151  //! Users can call init() on the manager to initialize the whole Component tree
152  /*! This will, in particular, trigger parsing of command-line arguments. */
153  using Component::init;
154 
155  //! Users can call start() on the manager to start the whole Component tree
156  /*! If init() has not been called yet, start() will call it automatically. */
157  using Component::start;
158 
159  //! Users can call launch() on the manager to launch the run() functions on the whole Component tree
160  /*! If start() has not been called yet, launch() will call it automatically. */
161  using Component::launch;
162 
163  //! Users can call wait() on the manager to wait for voluntary completion of all run() functions
164  using Component::wait;
165 
166  //! Users can call endrun() on the manager to request all run() functions to finish up
167  using Component::endrun;
168 
169  //! Users can call stop() on the manager to stop the whole Component tree
170  /*! If running(), this will first call endrun(). */
171  using Component::stop;
172 
173  //! Users can call uninit() on the manager to un-initialize the whole Component tree
174  /*! If started(), this will first call stop() */
175  using Component::uninit;
176 
177  //! Get the remaining arguments that were not parsed by the command line
178  /*! Any command line arguments after a lone '--' will be available in remainingArgs() */
179  std::vector<std::string> const & remainingArgs() const;
180 
181  //! Do not parse command-line arguments during preInit()
182  /*! By default, the Manager automatically parses the command-line arguments and sets parameters during
183  preInit(). In general, this is the best time to do this. In some applications where setting parameters could
184  trigger Blackboard operations, however, preInit() is too early to start setting parameters. People who "know
185  what they are doing" can use delayParseCommandLine() to prevent the automatic parsing during preInit() and
186  instead do it during postInit(), at which point the Blackboard should be fully operational. */
187  void delayParseCommandLine();
188 
189  protected:
190  //! Calls parseCommandLine()
191  void preInit();
192 
193  //! Checks for the --help flag
194  void postInit();
195 
196  //! Resets the nrt::CentralTimer
197  void preStart();
198 
199  //! Constructs a help message from all parameters in the model, and outputs it to 'out'
200  void constructHelpMessage(std::ostream & out) const;
201 
202  //! Constructs a help message and tries to send it to /usr/bin/less
203  void printHelpMessage() const;
204 
205  private:
206  //! Parse the command line and internally store the resulting remaining args
207  void doParseCommandLine();
208 
209  //! Parses the command line, and applies settings to all Parameters
210  /*! See the definition of Parameter for details on how to specify them from the command line. */
211  std::vector<std::string> const parseCommandLine(std::vector<std::string> const & commandLineArgs);
212 
213  //! The original command line arguments
214  std::vector<std::string> itsCommandLineArgs;
215 
216  //! Did we get command-line args (even though there may be none, just to detect if forgot)
217  bool itsGotArgs;
218 
219  //! Do we want to delay command-line parsing:
220  bool itsDelayParseCommandLine;
221 
222  //! Any command line arguments not used by the model
223  std::vector<std::string> itsRemainingArgs;
224 
225  void onParamChange(nrt::manager::profilebb const & param, bool const & newval);
226  void onParamChange(nrt::manager::profilelog const & param, bool const & newval);
227  void onParamChange(nrt::manager::loglevel const & param, nrt::manager::LogLevel const & newval);
228 
229  std::ostream * itsOnlineProfileLog;
230  };
231 } // namespace nrt
232 
233 // Include implementation details
235 
236 #endif // INCLUDE_NRT_CORE_MODEL_MANAGER_H
237