Skip to content
Snippets Groups Projects
Commit d50159ab authored by Joan Solà Ortega's avatar Joan Solà Ortega
Browse files

Document FactoryProcessor

parent 122a3384
No related branches found
No related tags found
1 merge request!350Resolve "Factory documentation"
This commit is part of merge request !350. Comments created here will be created in the context of that merge request.
...@@ -27,143 +27,92 @@ namespace wolf ...@@ -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. * 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, * For example, the following processor types are implemented,
* - "ODOM 3d" for ProcessorOdom3d * - "ProcessorOdom2d" for ProcessorOdom2d
* - "ODOM 2d" for ProcessorOdom2d * - "ProcessorOdom3d" for ProcessorOdom3d
* - "GPS" for ProcessorGPS * - "ProcessorDiffDrive" for ProcessorDiffDrive
*
* 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
* *
* You can then call the methods you like, e.g. to create a processor, you type: * among others.
*
* \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.
* *
* Registering processor creators into the factory is done through registerCreator(). * Find general Factory documentation in class Factory:
* You provide a processor type string (above), and a pointer to a static method * - Access the factory
* that knows how to create your specific processor, e.g.: * - 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. * This documentation shows you how to use the FactoryProcessor specifically:
* All these ProcessorXxx::create() methods need to have exactly the same API, regardless of the processor type. * - Write a processor creator
* This API includes a processor name, and a pointer to a base struct of parameters, ParamsProcessorBasePtr, * - Create processors
* that can be derived for each derived processor.
* *
* Here is an example of ProcessorOdom2d::create() extracted from processor_odom_2d.h: * #### Write processor creators
* Processor creators have the following API:
* *
* \code * \code
* static ProcessorBasePtr create(const std::string& _name, ParamsProcessorBasePtr _params) * static ProcessorBasePtr create(const std::string& _name, ParamsProcessorBasePtr _params_processor);
* {
* // 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;
* }
* \endcode * \endcode
* *
* #### Achieving automatic registration * They follow the general implementation shown below:
* Currently, registering is performed in each specific ProcessorXxxx source file, processor_xxxx.cpp.
* For example, in processor_odom_2d.cpp we find the line:
* *
* \code * \code
* const bool registered_odom_2d = FactoryProcessor::get().registerCreator("ProcessorOdom2d", ProcessorOdom2d::create); * static ProcessorBasePtr create(const std::string& _unique_name, ParamsProcessorBasePtr _params_processor)
* \endcode * {
* // 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). * // Do create the Processor object --- example: ProcessorOdom3d
* Therefore, at application level, all processors that have a .cpp file compiled are automatically registered. * auto prc_ptr = std::make_shared<ProcessorOdom3d>(params_processor_ptr);
* *
* #### Unregister processor creators * // Complete the processor setup with a unique name identifying the processor
* The method unregisterCreator() unregisters the ProcessorXxx::create() method. * prc_ptr->setName(_unique_name);
* It only needs to be passed the string of the processor type.
* *
* \code * return prc_ptr;
* FactoryProcessor::get().unregisterCreator("ProcessorOdom2d"); * }
* \endcode * \endcode
* *
* #### Creating processors * #### 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. * you must register the creator for this type into the factory.
* *
* To create a ProcessorOdom2d, you type: * To create a ProcessorOdom2d, you type:
* *
* \code * \code
* FactoryProcessor::get().create("ProcessorOdom2d", "main odometry", params_ptr); * auto prc_odom2d_ptr = FactoryProcessor::get().create("ProcessorOdom2d", "main odometry", params_ptr);
* \endcode * \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, * We provide the necessary steps to create a processor of class ProcessorOdom2d in our application,
* and bind it to a SensorOdom2d: * and bind it to a SensorOdom2d:
* *
* \code * \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 * #include "core/processor/processor_odom_2d.h" // provides ProcessorOdom2d and FactoryProcessor
* *
* // Note: SensorOdom2d::create() is already registered, automatically. * // Note: SensorOdom2d::create() is already registered, automatically.
* // Note: ProcessorOdom2d::create() is already registered, automatically. * // Note: ProcessorOdom2d::create() is already registered, automatically.
* *
* // First create the sensor (See FactorySensor for details) * // 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 = * ProcessorBasePtr processor_ptr =
* FactoryProcessor::get().create ( "ProcessorOdom2d" , "main odometry" , &params ); * FactoryProcessor::get().create ( "ProcessorOdom2d" , "main odometry" , params );
* *
* // Bind processor to sensor * // Bind processor to sensor
* sensor_ptr->addProcessor(processor_ptr); * sensor_ptr->addProcessor(processor_ptr);
* \endcode * \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" , &params );
* \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 // ParamsProcessor factory
struct ParamsProcessorBase; struct ParamsProcessorBase;
...@@ -175,16 +124,6 @@ inline std::string FactoryParamsProcessor::getClass() const ...@@ -175,16 +124,6 @@ inline std::string FactoryParamsProcessor::getClass() const
return "FactoryParamsProcessor"; 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) \ #define WOLF_REGISTER_PROCESSOR(ProcessorType) \
namespace{ const bool WOLF_UNUSED ProcessorType##Registered = \ namespace{ const bool WOLF_UNUSED ProcessorType##Registered = \
wolf::FactoryProcessor::get().registerCreator(#ProcessorType, ProcessorType::create); } \ wolf::FactoryProcessor::get().registerCreator(#ProcessorType, ProcessorType::create); } \
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment