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"
......@@ -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" , &params );
* 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" , &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
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); } \
......
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