Skip to content
Snippets Groups Projects

Resolve "Factory documentation"

Merged Joan Solà Ortega requested to merge 299-factory-documentation into devel
1 file
+ 1
185
Compare changes
  • Side-by-side
  • Inline
@@ -21,192 +21,8 @@ struct ParamsSensorBase;
namespace wolf
{
/** \brief Sensor factory class
/** \brief Solver factory class
*
* This factory can create objects of classes deriving from SensorBase.
*
* Specific object creation is invoked by ````create(TYPE, params ... )````, and the TYPE of sensor is identified with a string.
* Currently, the following sensor types are implemented,
* - "CAMERA" for SensorCamera
* - "ODOM 2d" for SensorOdom2d
* - "GPS FIX" for SensorGPSFix
*
* The rule to make new TYPE strings unique is that you skip the prefix 'Sensor' from your class name,
* and you build a string in CAPITALS with space separators, e.g.:
* - SensorCamera -> ````"CAMERA"````
* - SensorLaser2d -> ````"LASER 2d"````
* - etc.
*
* The methods to create specific sensors are called __creators__.
* Creators must be registered to the factory before they can be invoked for sensor creation.
*
* This documentation shows you how to:
* - Access the factory
* - Register and unregister creators
* - Create sensors
* - Write a sensor creator for SensorCamera (example).
*
* #### Accessing the factory
* The FactorySensor class is a <a href="http://stackoverflow.com/questions/1008019/c-singleton-design-pattern#1008289">singleton</a>: it can only exist once in your application.
* To obtain an instance of it, use the static method get(),
*
* \code
* FactorySensor::get()
* \endcode
*
* You can then call the methods you like, e.g. to create a sensor, you type:
*
* \code
* FactorySensor::get().create(...); // see below for creating sensors ...
* \endcode
*
* #### Registering sensor creators
* Prior to invoking the creation of a sensor of a particular type,
* you must register the creator for this type into the factory.
*
* Registering sensor creators into the factory is done through registerCreator().
* You provide a sensor type string (above), and a pointer to a static method
* that knows how to create your specific sensor, e.g.:
*
* \code
* FactorySensor::get().registerCreator("CAMERA", SensorCamera::create);
* \endcode
*
* The method SensorCamera::create() exists in the SensorCamera class as a static method.
* All these ````SensorXxx::create()```` methods need to have exactly the same API, regardless of the sensor type.
* This API includes a sensor name, a vector of extrinsic parameters,
* and a pointer to a base struct of intrinsic parameters, ParamsSensorBasePtr,
* that can be derived for each derived sensor:
*
* \code
* static SensorBasePtr create(const std::string& _name, Eigen::VectorXd& _extrinsics_pq, ParamsSensorBasePtr _intrinsics)
* \endcode
*
* See further down for an implementation example.
*
* #### Achieving automatic registration
* Currently, registering is performed in each specific SensorXxxx source file, sensor_xxxx.cpp.
* For example, in sensor_camera.cpp we find the line:
*
* \code
* const bool registered_camera = FactorySensor::get().registerCreator("CAMERA", SensorCamera::create);
* \endcode
*
* which is a static invocation (i.e., it is placed at global scope outside of the SensorCamera class).
* Therefore, at application level, all sensors that have a .cpp file compiled are automatically registered.
*
* #### Unregistering sensor creators
* The method unregisterCreator() unregisters the SensorXxx::create() method. It only needs to be passed the string of the sensor type.
*
* \code
* FactorySensor::get().unregisterCreator("CAMERA");
* \endcode
*
* #### Creating sensors
* Note: Prior to invoking the creation of a sensor of a particular type,
* you must register the creator for this type into the factory.
*
* To create e.g. a SensorCamera, you type:
*
* \code
* FactorySensor::get().create("CAMERA", "Front-left camera", extrinsics, intrinsics_ptr);
* \endcode
*
* where ABSOLUTELY ALL input parameters are important. In particular, the sensor name "Front-left camera" will be used to identify this camera
* and to assign it the appropriate processors. DO NOT USE IT WITH DUMMY PARAMETERS!
*
* #### See also
* - FactoryParamsSensor: to create intrinsic structs deriving from ParamsSensorBase directly from YAML files.
* - FactoryProcessor: to create processors that will be bound to sensors.
* - Problem::installSensor() : to install sensors in WOLF Problem.
*
* #### Example 1: writing a specific sensor creator
* Here is an example of SensorCamera::create() extracted from sensor_camera.cpp:
*
* \code
* static SensorBasePtr create(const std::string& _name, Eigen::VectorXd& _extrinsics_pq, ParamsSensorBasePtr _intrinsics)
* {
* // check extrinsics vector
* assert(_extrinsics_pq.size() == 7 && "Bad extrinsics vector length. Should be 7 for 3d.");
*
* // cast instrinsics to good type
* ParamsSensorCamera* intrinsics_ptr = (ParamsSensorCamera*) _intrinsics;
*
* // Do create the SensorCamera object, and complete its setup
* SensorCamera* sen_ptr = new SensorCamera(_extrinsics_pq, intrinsics_ptr);
* sen_ptr->setName(_unique_name);
*
* return sen_ptr;
* }
* \endcode
*
* #### Example 2: registering a sensor creator into the factory
* Registration can be done manually or automatically. It involves the call to static functions.
* It is advisable to put these calls within unnamed namespaces.
*
* - __Manual registration__: you control registration at application level.
* Put the code either at global scope (you must define a dummy variable for this),
* \code
* namespace {
* const bool registered_camera = FactorySensor::get().registerCreator("CAMERA", SensorCamera::create);
* }
* main () { ... }
* \endcode
* or inside your main(), where a direct call is possible:
* \code
* main () {
* FactorySensor::get().registerCreator("CAMERA", SensorCamera::create);
* ...
* }
* \endcode
*
* - __Automatic registration__: registration is performed at library level.
* Put the code at the last line of the sensor_xxx.cpp file,
* \code
* namespace {
* const bool registered_camera = FactorySensor::get().registerCreator("CAMERA", SensorCamera::create);
* }
* \endcode
* Automatic registration is recommended in wolf, and implemented in the classes shipped with it.
* You are free to comment out these lines and place them wherever you consider it more convenient for your design.
*
* #### Example 2: creating sensors
* We finally provide the necessary steps to create a sensor of class SensorCamera in our application:
*
* \code
* #include "factory_sensor.h"
* #include "sensor_camera.h" // provides SensorCamera
*
* // Note: SensorCamera::create() is already registered, automatically.
*
* using namespace wolf;
* int main() {
*
* // To create a camera, provide:
* // a type = "CAMERA",
* // a name = "Front-left camera",
* // an extrinsics vector, and
* // a pointer to the intrinsics struct:
*
* Eigen::VectorXd extrinsics_1(7); // give it some values...
* ParamsSensorCamera intrinsics_1({...}); // see FactoryParamsSensor to fill in the derived struct
*
* SensorBasePtr camera_1_ptr =
* FactorySensor::get().create ( "CAMERA" , "Front-left camera" , extrinsics_1 , &intrinsics_1 );
*
* // A second camera... with a different name!
*
* Eigen::VectorXd extrinsics_2(7);
* ParamsSensorCamera intrinsics_2({...});
*
* SensorBasePtr camera_2_ptr =
* FactorySensor::get().create( "CAMERA" , "Front-right camera" , extrinsics_2 , &intrinsics_2 );
*
* return 0;
* }
* \endcode
*
* You can also check the code in the example file ````src/examples/test_wolf_factories.cpp````.
*/
typedef Factory<SolverManager,
Loading