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

Resolve "Factory documentation"

parent 7d330cb7
No related branches found
No related tags found
No related merge requests found
...@@ -25,42 +25,68 @@ namespace wolf ...@@ -25,42 +25,68 @@ namespace wolf
/** \brief Singleton template factory /** \brief Singleton template factory
* *
* This class implements a generic factory as a singleton. * This template 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 FactorySensor
* > - Objects deriving from ProcessorBase --> see FactoryProcessor
* >
* > The reason for this is that the two cases above need a more elaborated API than the one in this template class.
* *
* \param TypeBase base type of all the objects created by the factory * \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 class is templatized on the class of the produced objects, __TypeBase__.
* The produced objects are always of a class deriving from 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: * 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 * - 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 * - 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. * - 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__: * - 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```` 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. * - ````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
*
* // FactorySensor
* typedef Factory<SensorBase, // Type of objects to be returned: SensorBasePtr
* const std::string&, // Type of the sensor: name of the derived sensor class
* const Eigen::VectorXd&, // Sensor extrinsics
* const ParamsSensorBasePtr> // Sensor parameters
* FactorySensor;
*
* // FactoryProcessor
* typedef Factory<ProcessorBase, // Type of object returned: ProcessorBasePtr
* const std::string&, // Type of the processor: name of the derived processor class
* const ParamsProcessorBasePtr> // Parameters for creating the processor
* FactoryProcessor;
*
* // AutoConfProcessorFactory
* typedef Factory<ProcessorBase, // Type of object returned: ProcessorBasePtr
* const std::string&, // Type of the processor: name of the derived processor class
* 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 * ### Operation of the factory
* *
* #### Rationale * #### 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 * > 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 * > Then, the factory will create specific landmarks deriving from LandmarkBase.\n
* > The specific type of landmark (e.g. LandmarkCorner2d, LandmarkAHP, LandmarkPolyline2d, etc) is indicated by a string that we call TYPE in this documentation. * > The specific type of landmark (e.g. LandmarkCorner2d, LandmarkAHP, LandmarkPolyline2d, etc) is indicated by a string that we call TYPE in this documentation.
* *
* Specific object creation is invoked by the method ````create(TYPE, params ... )````, where * Specific object creation is invoked by the method ````create(TYPE, params ... )````, where
* - the TYPE of object to create is identified with a string * - the TYPE of object to create is identified with a string. This string matches the name of the derived class.
* - the params may be provided in different forms -- see TypeInput. * - the params may be provided in different forms -- see TypeInput.
* *
* The methods to create specific objects are called __creators__. * The methods to create specific objects are called __creators__.
...@@ -75,23 +101,31 @@ namespace wolf ...@@ -75,23 +101,31 @@ namespace wolf
* - Examples: Write and register a landmark creator for LandmarkPolyline2d. * - Examples: Write and register a landmark creator for LandmarkPolyline2d.
* *
* #### Define correct TYPE names * #### Define correct TYPE names
* The rule to make new TYPE strings unique is that you skip the generic 'Type' prefix from your class name, * We use a std::string with literally the same text as the derived class name, e.g.:
* and you build a string in CAPITALS with space separators, e.g.: * - ParamsSensorCamera -> ````"ParamsSensorCamera"````
* - ParamsSensorCamera -> ````"CAMERA"```` * - SensorCamera -> ````"SensorCamera"````
* - ParamsSensorLaser2d -> ````"LASER 2d"```` * - ParamsSensorLaser2d -> ````"ParamsSensorLaser2d"````
* - LandmarkPolyline2d -> ````"POLYLINE 2d"```` * - SensorLaser2d -> ````"SensorLaser2d"````
* - LandmarkPolyline2d -> ````"LandmarkPolyline2d"````
* - etc. * - etc.
* *
* #### Access the factory * #### Access the factory
*
* The first thing to know is that we have defined typedefs for the templates that we are using. For example: * The first thing to know is that we have defined typedefs for the templates that we are using. For example:
* *
* \code * \code
* typedef Factory<ParamsSensorBase, std::string> FactoryParamsSensor; * typedef Factory<ParamsSensorBase, std::string> FactoryParamsSensor;
* typedef Factory<ParamsProcessorBase, std::string> FactoryParamsProcessor; * typedef Factory<ParamsProcessorBase, std::string> FactoryParamsProcessor;
* typedef Factory<LandmarkBase, YAML::Node> FactoryLandmark; * typedef Factory<LandmarkBase, YAML::Node> FactoryLandmark;
* typedef Factory<SensorBase,
* const std::string&,
* const Eigen::VectorXd&,
* const ParamsSensorBasePtr> FactorySensor;
*
* \endcode * \endcode
* *
* Second to know, the Factory 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. * Second to know, the Factory 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 access it, use the static method get(), * To access it, use the static method get(),
* *
* \code * \code
...@@ -103,10 +137,11 @@ namespace wolf ...@@ -103,10 +137,11 @@ namespace wolf
* You can then call the methods you like, e.g. to create a landmark, you use: * You can then call the methods you like, e.g. to create a landmark, you use:
* *
* \code * \code
* FactoryLandmark::get().create(...); // see below for creating objects ... * FactoryLandmark::get().create(TYPE, args...); // see below for creating objects ...
* \endcode * \endcode
* *
* #### Write creator methods (in your derived object classes) * #### Write creator methods (in your derived object classes)
*
* The method LandmarkPolyline2d::create(...) exists in the LandmarkPolyline2d class as a static method. * 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. * 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: * The API puts into play the two template parameters:
...@@ -117,13 +152,13 @@ namespace wolf ...@@ -117,13 +152,13 @@ namespace wolf
* *
* This API includes an element of type TypeInput, which might be either a std::string, or a YAML::node: * This API includes an element of type TypeInput, which might be either a std::string, or a YAML::node:
* - ````std::string```` is used to indicate the name of a configuration file. These files are usually YAML files containing configuration data to create your object. * - ````std::string```` is used to indicate the name of a configuration file. These files are usually YAML files containing configuration data to create your object.
* - ````YAML::Node```` is used to access parts of a YAML file already encoded as nodes, such as when loading landmarks from a SLAM map stored as a YAML file. * - ````YAML::Node```` is used to access parts of a YAML file already encoded as nodes, such as when loading landmarks from a SLAM map stored as a YAML file.
* *
* Two examples: * Two examples:
* *
* \code * \code
* static ParamsSensorBasePtr create(const std::string& _intrinsics_dot_yaml) * static ParamsSensorBasePtr create(const std::string& _intrinsics_dot_yaml)
* static LandmarkBasePtr create(const YAML::Node& _lmk_yaml_node) * static LandmarkBasePtr create(const YAML::Node& _lmk_yaml_node)
* \endcode * \endcode
* *
* See further down for an implementation example. * See further down for an implementation example.
...@@ -137,7 +172,7 @@ namespace wolf ...@@ -137,7 +172,7 @@ namespace wolf
* that knows how to create your specific object, e.g.: * that knows how to create your specific object, e.g.:
* *
* \code * \code
* FactoryLandmark::get().registerCreator("POLYLINE 2d", LandmarkPolyline2d::create); * FactoryLandmark::get().registerCreator("LandmarkPolyline2d", LandmarkPolyline2d::create);
* \endcode * \endcode
* *
* #### Automatic registration * #### Automatic registration
...@@ -145,7 +180,7 @@ namespace wolf ...@@ -145,7 +180,7 @@ namespace wolf
* For example, in sensor_camera_yaml.cpp we find the line: * For example, in sensor_camera_yaml.cpp we find the line:
* *
* \code * \code
* const bool registered_camera_intr = FactoryParamsSensor::get().registerCreator("CAMERA", createParamsSensorCamera); * const bool registered_camera_intr = FactoryParamsSensor::get().registerCreator("ParamsSensorCamera", createParamsSensorCamera);
* \endcode * \endcode
* *
* which is a static invocation (i.e., it is placed at global scope outside of the ParamsSensorCamera class). * which is a static invocation (i.e., it is placed at global scope outside of the ParamsSensorCamera class).
...@@ -156,7 +191,7 @@ namespace wolf ...@@ -156,7 +191,7 @@ namespace wolf
* The method unregisterCreator() unregisters the ObjectXxx::create() method. It only needs to be passed the string of the object type. * The method unregisterCreator() unregisters the ObjectXxx::create() method. It only needs to be passed the string of the object type.
* *
* \code * \code
* Factory<MyTypeBase, MyTypeInput>::get().unregisterCreator("CAMERA"); * Factory<MyTypeBase, MyTypeInput>::get().unregisterCreator("ParamsSensorCamera");
* \endcode * \endcode
* *
* #### Create objects using the factory * #### Create objects using the factory
...@@ -166,13 +201,13 @@ namespace wolf ...@@ -166,13 +201,13 @@ namespace wolf
* To create e.g. a LandmarkPolyline2d from a YAML node you type: * To create e.g. a LandmarkPolyline2d from a YAML node you type:
* *
* \code * \code
* LandmarkBasePtr lmk_ptr = Factory<LandmarkBasePtr, YAML::Node>::get().create("POLYLINE 2d", lmk_yaml_node); * LandmarkBasePtr lmk_ptr = Factory<LandmarkBasePtr, YAML::Node>::get().create("LandmarkPolyline2d", lmk_yaml_node);
* \endcode * \endcode
* *
* or even better, make use of the convenient typedefs: * or even better, make use of the convenient typedefs:
* *
* \code * \code
* LandmarkBasePtr lmk_ptr = FactoryLandmark::get().create("POLYLINE 2d", lmk_yaml_node); * LandmarkBasePtr lmk_ptr = FactoryLandmark::get().create("LandmarkPolyline2d", lmk_yaml_node);
* \endcode * \endcode
* *
* ### Examples * ### Examples
...@@ -197,7 +232,7 @@ namespace wolf ...@@ -197,7 +232,7 @@ namespace wolf
* } * }
* *
* // Create a new landmark * // Create a new landmark
* LandmarkBasePtr lmk_ptr = new LandmarkPolyline2d(points, first_defined, last_defined, first_id); * LandmarkBasePtr lmk_ptr = std::make_shared<LandmarkPolyline2d>(points, first_defined, last_defined, first_id);
* lmk_ptr->setId(id); * lmk_ptr->setId(id);
* *
* return lmk_ptr; * return lmk_ptr;
...@@ -212,7 +247,7 @@ namespace wolf ...@@ -212,7 +247,7 @@ namespace wolf
* // Register landmark creator (put the register code inside an unnamed namespace): * // Register landmark creator (put the register code inside an unnamed namespace):
* namespace * namespace
* { * {
* const bool registered_lmk_polyline_2d = FactoryLandmark::get().registerCreator("POLYLINE 2d", LandmarkPolyline2d::create); * const bool registered_lmk_polyline_2d = FactoryLandmark::get().registerCreator("LandmarkPolyline2d", LandmarkPolyline2d::create);
* } * }
* *
* \endcode * \endcode
...@@ -234,12 +269,16 @@ namespace wolf ...@@ -234,12 +269,16 @@ namespace wolf
template<class TypeBase, typename... TypeInput> template<class TypeBase, typename... TypeInput>
class Factory class Factory
{ {
private:
typedef std::shared_ptr<TypeBase> TypeBasePtr; typedef std::shared_ptr<TypeBase> TypeBasePtr;
public: public:
// example of creator callback (see typedefs below) // example of creator callback (see typedefs below)
typedef TypeBasePtr (*CreatorCallback)(TypeInput... _input); typedef TypeBasePtr (*CreatorCallback)(TypeInput... _input);
private: private:
typedef std::map<std::string, CreatorCallback> CallbackMap; typedef std::map<std::string, CreatorCallback> CallbackMap;
public: public:
bool registerCreator(const std::string& _type, CreatorCallback createFn); bool registerCreator(const std::string& _type, CreatorCallback createFn);
bool unregisterCreator(const std::string& _type); bool unregisterCreator(const std::string& _type);
......
...@@ -29,15 +29,6 @@ ...@@ -29,15 +29,6 @@
namespace wolf { namespace wolf {
/**
* \brief scalar type for the Wolf project
*
* Do NEVER forget to use Wolf scalar definitions when you code!!!
*
* Do NEVER use plain Eigen scalar types!!! (This is redundant with the above. But just to make sure you behave!)
*/
//typedef double double;
/** /**
* \brief Vector and Matrices size type for the Wolf project * \brief Vector and Matrices size type for the Wolf project
* *
......
...@@ -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); } \
......
...@@ -25,81 +25,51 @@ namespace wolf ...@@ -25,81 +25,51 @@ namespace wolf
* *
* This factory can create objects of classes deriving from SensorBase. * 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. * 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, * Currently, the following sensor types are implemented,
* - "CAMERA" for SensorCamera * - "SensorOdom2d" for SensorOdom2d
* - "ODOM 2d" for SensorOdom2d * - "SensorOdom3d" for SensorOdom3d
* - "GPS FIX" for SensorGPSFix * - "SensorDiffDrive" for SensorDiffDrive
* - "SensorCamera" for SensorCamera // in plugin 'vision'
* - "SensorLaser2d" for SensorLaser2d // in plugin 'laser'
* *
* The rule to make new TYPE strings unique is that you skip the prefix 'Sensor' from your class name, * among others.
* 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__. * Find general Factory documentation in class Factory:
* Creators must be registered to the factory before they can be invoked for sensor creation.
*
* This documentation shows you how to:
* - Access the factory * - Access the factory
* - Register and unregister creators * - Register/unregister creators
* - Create sensors * - Invoke object creation
* - 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 * This documentation shows you how to use the FactorySensor specifically:
* FactorySensor::get() * - Write sensor creators.
* \endcode * - Create sensors
* *
* You can then call the methods you like, e.g. to create a sensor, you type: * #### Write sensor creators
* Sensor creators have the following API:
* *
* \code * \code
* FactorySensor::get().create(...); // see below for creating sensors ... * static SensorBasePtr create(const std::string& _name, Eigen::VectorXd& _params_extrinsics, ParamsSensorBasePtr _params_sensor);
* \endcode * \endcode
* *
* #### Registering sensor creators * They follow the general implementation shown below:
* 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 * \code
* FactorySensor::get().registerCreator("CAMERA", SensorCamera::create); * static SensorBasePtr create(const std::string& _unique_name, Eigen::VectorXd& _params_extrinsics, ParamsSensorBasePtr _params_sensor)
* \endcode * {
* * // check extrinsics vector --- example: 3D pose
* The method SensorCamera::create() exists in the SensorCamera class as a static method. * assert(_params_extrinsics.size() == 7 && "Bad extrinsics vector length. Should be 7 for 3d.");
* 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 * // cast sensor parameters to good type --- example: ParamsSensorCamera
* const bool registered_camera = FactorySensor::get().registerCreator("CAMERA", SensorCamera::create); * auto intrinsics_ptr = std::static_pointer_cast<ParamsSensorCamera>(_params_sensor);
* \endcode
* *
* which is a static invocation (i.e., it is placed at global scope outside of the SensorCamera class). * // Do create the Sensor object --- example: SensorCamera
* Therefore, at application level, all sensors that have a .cpp file compiled are automatically registered. * auto sen_ptr = std::make_shared<SensorCamera>(_extrinsics_pq, intrinsics_ptr);
* *
* #### Unregistering sensor creators * // Complete the sensor setup with a unique name identifying the sensor
* The method unregisterCreator() unregisters the SensorXxx::create() method. It only needs to be passed the string of the sensor type. * sen_ptr->setName(_unique_name);
* *
* \code * return sen_ptr;
* FactorySensor::get().unregisterCreator("CAMERA"); * }
* \endcode * \endcode
* *
* #### Creating sensors * #### Creating sensors
...@@ -109,7 +79,7 @@ namespace wolf ...@@ -109,7 +79,7 @@ namespace wolf
* To create e.g. a SensorCamera, you type: * To create e.g. a SensorCamera, you type:
* *
* \code * \code
* FactorySensor::get().create("CAMERA", "Front-left camera", extrinsics, intrinsics_ptr); * auto camera_ptr = FactorySensor::get().create("SensorCamera", "Front-left camera", params_extrinsics, params_camera);
* \endcode * \endcode
* *
* where ABSOLUTELY ALL input parameters are important. In particular, the sensor name "Front-left camera" will be used to identify this camera * where ABSOLUTELY ALL input parameters are important. In particular, the sensor name "Front-left camera" will be used to identify this camera
...@@ -120,20 +90,21 @@ namespace wolf ...@@ -120,20 +90,21 @@ namespace wolf
* - FactoryProcessor: to create processors that will be bound to sensors. * - FactoryProcessor: to create processors that will be bound to sensors.
* - Problem::installSensor() : to install sensors in WOLF Problem. * - Problem::installSensor() : to install sensors in WOLF Problem.
* *
* #### Example 1: writing a specific sensor creator * #### Example 1: writing a SensorCamera creator
* Here is an example of SensorCamera::create() extracted from sensor_camera.cpp: * Here is an example of SensorCamera::create() extracted from sensor_camera.cpp:
* *
* \code * \code
* static SensorBasePtr create(const std::string& _name, Eigen::VectorXd& _extrinsics_pq, ParamsSensorBasePtr _intrinsics) * static SensorBasePtr create(const std::string& _unique_name, Eigen::VectorXd& _extrinsics_pq, ParamsSensorBasePtr _intrinsics)
* { * {
* // check extrinsics vector * // check extrinsics vector
* assert(_extrinsics_pq.size() == 7 && "Bad extrinsics vector length. Should be 7 for 3d."); * assert(_extrinsics_pq.size() == 7 && "Bad extrinsics vector length. Should be 7 for 3d.");
* *
* // cast instrinsics to good type * // cast instrinsics to good type
* ParamsSensorCamera* intrinsics_ptr = (ParamsSensorCamera*) _intrinsics; * auto intrinsics_ptr = std::static_pointer_cast<ParamsSensorCamera>(_intrinsics);
* *
* // Do create the SensorCamera object, and complete its setup * // Do create the SensorCamera object, and complete its setup
* SensorCamera* sen_ptr = new SensorCamera(_extrinsics_pq, intrinsics_ptr); * auto sen_ptr = std::make_shared<SensorCamera>(_extrinsics_pq, intrinsics_ptr);
*
* sen_ptr->setName(_unique_name); * sen_ptr->setName(_unique_name);
* *
* return sen_ptr; * return sen_ptr;
...@@ -148,14 +119,14 @@ namespace wolf ...@@ -148,14 +119,14 @@ namespace wolf
* Put the code either at global scope (you must define a dummy variable for this), * Put the code either at global scope (you must define a dummy variable for this),
* \code * \code
* namespace { * namespace {
* const bool registered_camera = FactorySensor::get().registerCreator("CAMERA", SensorCamera::create); * const bool registered_camera = FactorySensor::get().registerCreator("SensorCamera", SensorCamera::create);
* } * }
* main () { ... } * main () { ... }
* \endcode * \endcode
* or inside your main(), where a direct call is possible: * or inside your main(), where a direct call is possible:
* \code * \code
* main () { * main () {
* FactorySensor::get().registerCreator("CAMERA", SensorCamera::create); * FactorySensor::get().registerCreator("SensorCamera", SensorCamera::create);
* ... * ...
* } * }
* \endcode * \endcode
...@@ -164,7 +135,7 @@ namespace wolf ...@@ -164,7 +135,7 @@ namespace wolf
* Put the code at the last line of the sensor_xxx.cpp file, * Put the code at the last line of the sensor_xxx.cpp file,
* \code * \code
* namespace { * namespace {
* const bool registered_camera = FactorySensor::get().registerCreator("CAMERA", SensorCamera::create); * const bool registered_camera = FactorySensor::get().registerCreator("SensorCamera", SensorCamera::create);
* } * }
* \endcode * \endcode
* Automatic registration is recommended in wolf, and implemented in the classes shipped with it. * Automatic registration is recommended in wolf, and implemented in the classes shipped with it.
...@@ -174,8 +145,8 @@ namespace wolf ...@@ -174,8 +145,8 @@ namespace wolf
* We finally provide the necessary steps to create a sensor of class SensorCamera in our application: * We finally provide the necessary steps to create a sensor of class SensorCamera in our application:
* *
* \code * \code
* #include "factory_sensor.h" * #include "core/sensor/factory_sensor.h"
* #include "core/sensor/sensor_camera.h" // provides SensorCamera * #include "vision/sensor/sensor_camera.h" // provides SensorCamera
* *
* // Note: SensorCamera::create() is already registered, automatically. * // Note: SensorCamera::create() is already registered, automatically.
* *
...@@ -183,43 +154,43 @@ namespace wolf ...@@ -183,43 +154,43 @@ namespace wolf
* int main() { * int main() {
* *
* // To create a camera, provide: * // To create a camera, provide:
* // a type = "CAMERA", * // a type = "SensorCamera",
* // a name = "Front-left camera", * // a name = "Front-left camera",
* // an extrinsics vector, and * // an extrinsics vector, and
* // a pointer to the intrinsics struct: * // a pointer to the intrinsics struct:
* *
* Eigen::VectorXd extrinsics_1(7); // give it some values... * Eigen::VectorXd extrinsics_1(7); // give it some values...
* ParamsSensorCamera intrinsics_1({...}); // see FactoryParamsSensor to fill in the derived struct *
* // Create a pointer to the struct of sensor parameters stored in a YAML file ( see FactoryParamsSensor )
* ParamsSensorCameraPtr intrinsics_1 =
* FactoryParamsSensor::get().create("ParamsSensorCamera",
* camera_1.yaml);
* *
* SensorBasePtr camera_1_ptr = * SensorBasePtr camera_1_ptr =
* FactorySensor::get().create ( "CAMERA" , "Front-left camera" , extrinsics_1 , &intrinsics_1 ); * FactorySensor::get().create ( "SensorCamera" ,
* "Front-left camera" ,
* extrinsics_1 ,
* intrinsics_1 );
* *
* // A second camera... with a different name! * // A second camera... with a different name!
* *
* Eigen::VectorXd extrinsics_2(7); * Eigen::VectorXd extrinsics_2(7);
* ParamsSensorCamera intrinsics_2({...}); *
* ParamsSensorCameraPtr intrinsics_2 =
* FactoryParamsSensor::get().create("ParamsSensorCamera",
* camera_2.yaml);
* *
* SensorBasePtr camera_2_ptr = * SensorBasePtr camera_2_ptr =
* FactorySensor::get().create( "CAMERA" , "Front-right camera" , extrinsics_2 , &intrinsics_2 ); * FactorySensor::get().create( "SensorCamera" ,
* "Front-right camera" ,
* extrinsics_2 ,
* intrinsics_2 );
* *
* return 0; * return 0;
* } * }
* \endcode * \endcode
* *
* You can also check the code in the example file ````src/examples/test_wolf_factories.cpp````.
*/ */
// ParamsSensor factory
struct ParamsSensorBase;
typedef Factory<ParamsSensorBase,
const std::string&> FactoryParamsSensor;
template<>
inline std::string FactoryParamsSensor::getClass() const
{
return "FactoryParamsSensor";
}
// Sensor factory
typedef Factory<SensorBase, typedef Factory<SensorBase,
const std::string&, const std::string&,
const Eigen::VectorXd&, const Eigen::VectorXd&,
...@@ -231,6 +202,16 @@ inline std::string FactorySensor::getClass() const ...@@ -231,6 +202,16 @@ inline std::string FactorySensor::getClass() const
return "FactorySensor"; return "FactorySensor";
} }
// ParamsSensor factory
struct ParamsSensorBase;
typedef Factory<ParamsSensorBase,
const std::string&> FactoryParamsSensor;
template<>
inline std::string FactoryParamsSensor::getClass() const
{
return "FactoryParamsSensor";
}
#define WOLF_REGISTER_SENSOR(SensorType) \ #define WOLF_REGISTER_SENSOR(SensorType) \
namespace{ const bool WOLF_UNUSED SensorType##Registered = \ namespace{ const bool WOLF_UNUSED SensorType##Registered = \
FactorySensor::get().registerCreator(#SensorType, SensorType::create); } \ FactorySensor::get().registerCreator(#SensorType, SensorType::create); } \
......
...@@ -21,192 +21,8 @@ struct ParamsSensorBase; ...@@ -21,192 +21,8 @@ struct ParamsSensorBase;
namespace wolf 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, typedef Factory<SolverManager,
......
/* /*
* factory_state_block.h * \file factory_state_block.h
* *
* Created on: Apr 27, 2020 * Created on: Apr 27, 2020
* Author: jsola * \author: jsola
*/ */
#ifndef STATE_BLOCK_FACTORY_STATE_BLOCK_H_ #ifndef STATE_BLOCK_FACTORY_STATE_BLOCK_H_
...@@ -14,13 +14,107 @@ ...@@ -14,13 +14,107 @@
namespace wolf namespace wolf
{ {
// State blocks factory /** \brief StateBlock factory class
*
* This factory can create objects of class StateBlock and classes deriving from StateBlock.
*
* Specific object creation is invoked by create(TYPE, state, fixed),
* and the TYPE of state block is identified with a string.
* For example, the following processor types are implemented,
* - "StateBlock" for StateBlock
* - "StateQuaternion" for StateQuaternion
* - "StateAngle" for StateAngle
* - "StateHomogeneous3d" for StateHomogeneous3d
*
* The factory also creates state blocks according to the block key used in to identify state blocks in each Wolf node.
* These keys are single-letter strings. The following letters are implemented
* - "O" for 2d orientation, creates StateAngle
* - "O" for 3d orientation, creates StateQuaternion
* - "H" crestes StateHomogeneous3d
*
* Any other letter creates the base StateBlock.
*
* Find general Factory documentation in class Factory:
* - Access the factory
* - Register/unregister creators
* - Invoke object creation
*
* This documentation shows you how to use the FactoryStateBlock specifically:
* - Write a state block creator
* - Create state blocks
*
* #### Write state block creators
* StateBlock creators have the following API:
*
* \code
* static StateBlockPtr create(const Eigen::VectorXd& _state, bool _fixed);
* \endcode
*
* They follow the general implementation shown below:
*
* \code
* static StateBlockPtr create(const Eigen::VectorXd& _state, bool _fixed)
* {
* return std::make_shared<StateBlockDerived>(_state, _fixed);
* }
* \endcode
*
* #### Creating processors
* Note: Prior to invoking the creation of a processor of a derived type,
* you must register the creator for this type into the factory.
*
* Note: State blocks of the base type do not need to be registered.
*
* To create a StateQuaternion, you type:
*
* \code
* auto sq_ptr = FactoryStateBlock::get().create("StateQuaternion", Vector4d(1,0,0,0), false);
* \endcode
*
* If your problem has dimension 3 (e.g. is 3D), you can use the key "O" to create a StateQuaternion,
*
* \code
* auto sq_ptr = FactoryStateBlock::get().create("O", Vector4d(1,0,0,0), false);
* \endcode
*
* However if your problem has dimension 2 (e.g. is 2D), the key "O" will create a StateAngle,
*
* \code
* auto sa_ptr = FactoryStateBlock::get().create("O", Vector1d(angle_in_radians), false);
* \endcode
*
* Note: It is an error to provide state vectors of the wrong size (4 for 3D orientation, 1 for 2D).
*
* To create StateBlocks to store 2D position and velocity, you type:
*
* \code
* auto sp2_ptr = FactoryStateBlock::get().create("StateBlock", Vector2d(1,2), false);
* auto sv2_ptr = FactoryStateBlock::get().create("StateBlock", Vector2d(1,2), false);
* \endcode
*
* To create StateBlocks to store 2D position and velocity, you can also use the key letters:
*
* \code
* auto sp2_ptr = FactoryStateBlock::get().create("P", Vector2d(1,2), false);
* auto sv2_ptr = FactoryStateBlock::get().create("V", Vector2d(1,2), false);
* \endcode
*
* To create StateBlocks to store 3D position and velocity, you type:
*
* \code
* auto sp3_ptr = FactoryStateBlock::get().create("P", Vector3d(1,2,3), false);
* auto sv3_ptr = FactoryStateBlock::get().create("V", Vector3d(1,2,3), false);
* \endcode
*
* Note: for base state blocks, the size is determined by the size of the provided vector parameter `VectorXd& _state`.
*/
typedef Factory<StateBlock, const Eigen::VectorXd&, bool> FactoryStateBlock; typedef Factory<StateBlock, const Eigen::VectorXd&, bool> FactoryStateBlock;
template<> template<>
inline std::string FactoryStateBlock::getClass() const inline std::string FactoryStateBlock::getClass() const
{ {
return "FactoryStateBlock"; return "FactoryStateBlock";
} }
template<> template<>
inline StateBlockPtr FactoryStateBlock::create(const std::string& _type, const Eigen::VectorXd& _state, bool _fixed) inline StateBlockPtr FactoryStateBlock::create(const std::string& _type, const Eigen::VectorXd& _state, bool _fixed)
{ {
......
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