diff --git a/include/core/common/factory.h b/include/core/common/factory.h index f03cabec9a7527801464d9e4e025464a7d23f0ad..810871e64fd3ed645d3412a21836ea8d3e6b93cc 100644 --- a/include/core/common/factory.h +++ b/include/core/common/factory.h @@ -25,35 +25,61 @@ namespace wolf /** \brief Singleton template factory * - * This class implements a generic factory as a singleton. - * - * > IMPORTANT: This template factory can be used to construct many different objects except: - * > - Objects deriving from SensorBase --> see SensorFactory - * > - Objects deriving from ProcessorBase --> see ProcessorFactory - * > - * > The reason for this is that the two cases above need a more elaborated API than the one in this template class. + * This template class implements a generic factory as a singleton. * * \param TypeBase base type of all the objects created by the factory - * \param TypeInput type of the input argument. Typical cases are std::string for file names, and YAML::Node for YAML nodes. + * \param TypeInput variadic type for the input arguments. + * + * ### Template specialization * * - The class is templatized on the class of the produced objects, __TypeBase__. * The produced objects are always of a class deriving from TypeBase. - * The returned data is always a pointer to TypeBase. + * The returned data is always a shared pointer to TypeBase. * * For example, you may use as __TypeBase__ the following types: * - LandmarkBase: the Factory creates landmarks deriving from LandmarkBase and returns base pointers ````LandmarkBasePtr```` to them * - ParamsSensorBase: the Factory creates intrinsic parameters deriving from ParamsSensorBase and returns base pointers ````ParamsSensorBasePtr```` to them * - XxxBase: the Factory creates objects deriving from XxxBase and returns pointers ````XxxBasePtr```` to them. * - * - The class in also templatized on the type of the input parameter of the creator, __TypeInput__: - * - ````std::string```` is used when the input parameter is a file name from which to read data (typically a YAML file). - * - ````YAML::Node```` is used when the input parameter is a YAML node with structured data. + * - The class is variadic-templatized on the types of the input parameter of the creator, __TypeInput__: + * - ````std::string```` is used when the input parameter is a file name from which to read data (typically a YAML file). + * - ````std::string, wolf::ParamsServer``` is used when nodes are build from parameters in the ParamsServer + * - ````YAML::Node```` is used when the input parameter is a YAML node with structured data. + * - Any other variadic list of inputs is possible. + * + * - Examples of specific factories existing in Wolf are: + * \code + * + * // SensorFactory + * typedef Factory<SensorBase, // Type of objects to be created: SensorBasePtr + * const std::string&, // Name of the sensor + * const Eigen::VectorXd&, // Sensor extrinsics + * const ParamsSensorBasePtr> // Sensor parameters + * SensorFactory; + * + * // ProcessorFactory + * typedef Factory<ProcessorBase, // Type of object created: ProcessorBasePtr + * const std::string&, // Name of the processor + * const ParamsProcessorBasePtr> // Parameters for creating the processor + * ProcessorFactory; + * + * // AutoConfProcessorFactory + * typedef Factory<ProcessorBase, // Type of object created: ProcessorBasePtr + * const std::string&, // Name of the processor + * const ParamsServer> // Parameters for creating the processor + * AutoConfProcessorFactory; + * + * // Landmarks from YAML + * typedef Factory<LandmarkBase, // Type of node created: LandmarkBasePtr + * const YAML::Node&> // YAML node with the lmk params + * LandmarkFactory; + * \endcode * * ### Operation of the factory * * #### Rationale * - * This factory can create objects of classes deriving from TypeBase. + * Once specialized, this factory can create objects of classes deriving from TypeBase. * * > For example, if you want to make a Landmark factory, set TypeBase = LandmarkBase.\n * > Then, the factory will create specific landmarks deriving from LandmarkBase.\n @@ -75,18 +101,18 @@ namespace wolf * - Examples: Write and register a landmark creator for LandmarkPolyline2d. * * #### Define correct TYPE names - * The rule to make new TYPE strings unique is that you skip the generic 'Type' prefix from your class name, - * and you build a string in CAPITALS with space separators, e.g.: - * - ParamsSensorCamera -> ````"CAMERA"```` - * - ParamsSensorLaser2d -> ````"LASER 2d"```` - * - LandmarkPolyline2d -> ````"POLYLINE 2d"```` + * We use a std::string with literally the same text as the derived class name, e.g.: + * - ParamsSensorCamera -> ````"ParamsSensorCamera"```` + * - ParamsSensorLaser2d -> ````"ParamsSensorLaser2d"```` + * - LandmarkPolyline2d -> ````"LandmarkPolyline2d"```` * - etc. * * #### Access the factory + * * The first thing to know is that we have defined typedefs for the templates that we are using. For example: * * \code - * typedef Factory<ParamsSensorBase, std::string> ParamsSensorFactory; + * typedef Factory<ParamsSensorBase, std::string> ParamsSensorFactory; * typedef Factory<ProcessorParamsBase, std::string> ProcessorParamsFactory; * typedef Factory<LandmarkBase, YAML::Node> LandmarkFactory; * \endcode @@ -103,10 +129,11 @@ namespace wolf * You can then call the methods you like, e.g. to create a landmark, you use: * * \code - * LandmarkFactory::get().create(...); // see below for creating objects ... + * LandmarkFactory::get().create(TYPE, args...); // see below for creating objects ... * \endcode * * #### Write creator methods (in your derived object classes) + * * The method LandmarkPolyline2d::create(...) exists in the LandmarkPolyline2d class as a static method. * All these ````XxxXxx::create()```` methods need to have exactly the same API, regardless of the object type. * The API puts into play the two template parameters: @@ -234,12 +261,16 @@ namespace wolf template<class TypeBase, typename... TypeInput> class Factory { + private: typedef std::shared_ptr<TypeBase> TypeBasePtr; + public: // example of creator callback (see typedefs below) typedef TypeBasePtr (*CreatorCallback)(TypeInput... _input); + private: typedef std::map<std::string, CreatorCallback> CallbackMap; + public: bool registerCreator(const std::string& _type, CreatorCallback createFn); bool unregisterCreator(const std::string& _type);