diff --git a/include/core/processor/factory_processor.h b/include/core/processor/factory_processor.h index 5fc2f8f14ccffc52653c6f43fa0c07fdb03be825..9d101848eb54966e970a48d08416548a259b7154 100644 --- a/include/core/processor/factory_processor.h +++ b/include/core/processor/factory_processor.h @@ -27,143 +27,92 @@ namespace wolf * * Specific object creation is invoked by create(TYPE, params), and the TYPE of processor is identified with a string. * For example, the following processor types are implemented, - * - "ODOM 3d" for ProcessorOdom3d - * - "ODOM 2d" for ProcessorOdom2d - * - "GPS" for ProcessorGPS - * - * The rule to make new TYPE strings unique is that you skip the prefix 'Processor' from your class name, - * and you build a string in CAPITALS with space separators. - * - ProcessorImageFeature -> ````"IMAGE"```` - * - ProcessorLaser2d -> ````"LASER 2d"```` - * - etc. - * - * The methods to create specific processors are called __creators__. - * Creators must be registered to the factory before they can be invoked for processor creation. - * - * This documentation shows you how to: - * - Access the Factory - * - Register and unregister creators - * - Create processors - * - Write a processor creator for ProcessorOdom2d (example). - * - * #### Accessing the Factory - * The FactoryProcessor class is a singleton: it can only exist once in your application. - * To obtain an instance of it, use the static method get(), - * - * \code - * FactoryProcessor::get() - * \endcode + * - "ProcessorOdom2d" for ProcessorOdom2d + * - "ProcessorOdom3d" for ProcessorOdom3d + * - "ProcessorDiffDrive" for ProcessorDiffDrive * - * You can then call the methods you like, e.g. to create a processor, you type: - * - * \code - * FactoryProcessor::get().create(...); // see below for creating processors ... - * \endcode - * - * #### Registering processor creators - * Prior to invoking the creation of a processor of a particular type, - * you must register the creator for this type into the factory. + * among others. * - * Registering processor creators into the factory is done through registerCreator(). - * You provide a processor type string (above), and a pointer to a static method - * that knows how to create your specific processor, e.g.: + * Find general Factory documentation in class Factory: + * - Access the factory + * - Register/unregister creators + * - Invoke object creation * - * \code - * FactoryProcessor::get().registerCreator("ProcessorOdom2d", ProcessorOdom2d::create); - * \endcode * - * The method ProcessorOdom2d::create() exists in the ProcessorOdom2d class as a static method. - * All these ProcessorXxx::create() methods need to have exactly the same API, regardless of the processor type. - * This API includes a processor name, and a pointer to a base struct of parameters, ParamsProcessorBasePtr, - * that can be derived for each derived processor. + * This documentation shows you how to use the FactoryProcessor specifically: + * - Write a processor creator + * - Create processors * - * Here is an example of ProcessorOdom2d::create() extracted from processor_odom_2d.h: + * #### Write processor creators + * Processor creators have the following API: * * \code - * static ProcessorBasePtr create(const std::string& _name, ParamsProcessorBasePtr _params) - * { - * // cast _params to good type - * ParamsProcessorOdom2d* params = (ParamsProcessorOdom2d*)_params; - * - * ProcessorBasePtr prc = new ProcessorOdom2d(params); - * prc->setName(_name); // pass the name to the created ProcessorOdom2d. - * return prc; - * } + * static ProcessorBasePtr create(const std::string& _name, ParamsProcessorBasePtr _params_processor); * \endcode * - * #### Achieving automatic registration - * Currently, registering is performed in each specific ProcessorXxxx source file, processor_xxxx.cpp. - * For example, in processor_odom_2d.cpp we find the line: + * They follow the general implementation shown below: * * \code - * const bool registered_odom_2d = FactoryProcessor::get().registerCreator("ProcessorOdom2d", ProcessorOdom2d::create); - * \endcode + * static ProcessorBasePtr create(const std::string& _unique_name, ParamsProcessorBasePtr _params_processor) + * { + * // cast processor parameters to good type --- example: ParamsProcessorOdom3d + * auto params_processor_ptr = std::static_pointer_cast<ParamsProcessorOdom3d>(_params_processor); * - * which is a static invocation (i.e., it is placed at global scope outside of the ProcessorOdom2d class). - * Therefore, at application level, all processors that have a .cpp file compiled are automatically registered. + * // Do create the Processor object --- example: ProcessorOdom3d + * auto prc_ptr = std::make_shared<ProcessorOdom3d>(params_processor_ptr); * - * #### Unregister processor creators - * The method unregisterCreator() unregisters the ProcessorXxx::create() method. - * It only needs to be passed the string of the processor type. + * // Complete the processor setup with a unique name identifying the processor + * prc_ptr->setName(_unique_name); * - * \code - * FactoryProcessor::get().unregisterCreator("ProcessorOdom2d"); + * return prc_ptr; + * } * \endcode * * #### Creating processors - * Prior to invoking the creation of a processor of a particular type, + * Note: Prior to invoking the creation of a processor of a particular type, * you must register the creator for this type into the factory. * * To create a ProcessorOdom2d, you type: * * \code - * FactoryProcessor::get().create("ProcessorOdom2d", "main odometry", params_ptr); + * auto prc_odom2d_ptr = FactoryProcessor::get().create("ProcessorOdom2d", "main odometry", params_ptr); * \endcode * - * #### Example 1 : using the Factories alone + * #### Example 1 : Create a sensor and its processor * We provide the necessary steps to create a processor of class ProcessorOdom2d in our application, * and bind it to a SensorOdom2d: * * \code - * #include "core/sensor/sensor_odom_2d.h" // provides SensorOdom2d and FactorySensor + * #include "core/sensor/sensor_odom_2d.h" // provides SensorOdom2d and FactorySensor * #include "core/processor/processor_odom_2d.h" // provides ProcessorOdom2d and FactoryProcessor * * // Note: SensorOdom2d::create() is already registered, automatically. * // Note: ProcessorOdom2d::create() is already registered, automatically. * * // First create the sensor (See FactorySensor for details) - * SensorBasePtr sensor_ptr = FactorySensor::get().create ( "FactorOdom2d" , "Main odometer" , extrinsics , &intrinsics ); + * SensorBasePtr sensor_ptr = FactorySensor::get().create ( "SensorOdom2d" , "Main odometer" , extrinsics , &intrinsics ); * - * // To create a odometry integrator, provide a type="ODOM 2d", a name="main odometry", and a pointer to the parameters struct: + * // To create a odometry integrator, provide a type="ProcessorOdom2d", a name="main odometry", and a pointer to the parameters struct: * - * ParamsProcessorOdom2d params({...}); // fill in the derived struct (note: ProcessorOdom2d actually has no input params) + * auto params = make_shared<ParamsProcessorOdom2d>({...}); // fill in the derived struct (note: ProcessorOdom2d actually has no input params) * * ProcessorBasePtr processor_ptr = - * FactoryProcessor::get().create ( "ProcessorOdom2d" , "main odometry" , ¶ms ); + * FactoryProcessor::get().create ( "ProcessorOdom2d" , "main odometry" , params ); * * // Bind processor to sensor * sensor_ptr->addProcessor(processor_ptr); * \endcode * - * #### Example 2: Using the helper API in class Problem - * The WOLF uppermost node, Problem, makes the creation of sensors and processors, and the binding between them, even simpler. - * - * The creation is basically replicating the factories' API. The binding is accomplished by passing the sensor name to the Processor installer. - * - * The example 1 above can be accomplished as follows (we obviated for simplicity all the parameter creation), - * - * \code - * #include "core/sensor/sensor_odom_2d.h" - * #include "core/processor/processor_odom_2d.h" - * #include "core/problem/problem.h" - * - * Problem problem(FRM_PO_2d); - * problem.installSensor ( "SensorOdom2d" , "Main odometer" , extrinsics , &intrinsics ); - * problem.installProcessor ( "ProcessorOdom2d" , "Odometry" , "Main odometer" , ¶ms ); - * \endcode - * - * You can also check the code in the example file ````src/examples/test_wolf_factories.cpp````. */ +typedef Factory<ProcessorBase, + const std::string&, + const ParamsProcessorBasePtr> FactoryProcessor; +template<> +inline std::string FactoryProcessor::getClass() const +{ + return "FactoryProcessor"; +} + // ParamsProcessor factory struct ParamsProcessorBase; @@ -175,16 +124,6 @@ inline std::string FactoryParamsProcessor::getClass() const return "FactoryParamsProcessor"; } -// Processor factory -typedef Factory<ProcessorBase, - const std::string&, - const ParamsProcessorBasePtr> FactoryProcessor; -template<> -inline std::string FactoryProcessor::getClass() const -{ - return "FactoryProcessor"; -} - #define WOLF_REGISTER_PROCESSOR(ProcessorType) \ namespace{ const bool WOLF_UNUSED ProcessorType##Registered = \ wolf::FactoryProcessor::get().registerCreator(#ProcessorType, ProcessorType::create); } \