diff --git a/CMakeLists.txt b/CMakeLists.txt index e626b36bac416515f416f3d5a2035c601c6618b4..f9c69b34a4912490c7128a5c9d4f302ddde88c54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -245,7 +245,6 @@ SET(HDRS_LANDMARK include/core/landmark/landmark_match.h ) SET(HDRS_PROCESSOR - include/core/processor/autoconf_processor_factory.h include/core/processor/motion_buffer.h include/core/processor/processor_base.h include/core/processor/processor_diff_drive.h @@ -261,7 +260,6 @@ SET(HDRS_PROCESSOR include/core/processor/track_matrix.h ) SET(HDRS_SENSOR - include/core/sensor/autoconf_sensor_factory.h include/core/sensor/sensor_base.h include/core/sensor/sensor_diff_drive.h include/core/sensor/sensor_factory.h @@ -368,6 +366,7 @@ SET(SRCS_SOLVER ) SET(SRCS_YAML src/yaml/processor_odom_3D_yaml.cpp + src/yaml/sensor_odom_2D_yaml.cpp src/yaml/sensor_odom_3D_yaml.cpp ) #OPTIONALS diff --git a/hello_wolf/processor_range_bearing.cpp b/hello_wolf/processor_range_bearing.cpp index 37c740b4205387be20683601d49fff399de1d70b..20c199203deabc8c8080b6838d73a4b9c0622f09 100644 --- a/hello_wolf/processor_range_bearing.cpp +++ b/hello_wolf/processor_range_bearing.cpp @@ -157,7 +157,6 @@ namespace wolf { WOLF_REGISTER_PROCESSOR("RANGE BEARING", ProcessorRangeBearing) } // namespace wolf -#include "core/processor/autoconf_processor_factory.h" namespace wolf { WOLF_REGISTER_PROCESSOR_AUTO("RANGE BEARING", ProcessorRangeBearing) diff --git a/hello_wolf/sensor_range_bearing.cpp b/hello_wolf/sensor_range_bearing.cpp index 4f0e8f136d08a058ed68d7426db409e34f8b6c2e..5e84c80f955d204c6cb2bf4e7989883581f38322 100644 --- a/hello_wolf/sensor_range_bearing.cpp +++ b/hello_wolf/sensor_range_bearing.cpp @@ -56,7 +56,6 @@ namespace wolf { WOLF_REGISTER_SENSOR("RANGE BEARING", SensorRangeBearing) } // namespace wolf -#include "core/sensor/autoconf_sensor_factory.h" namespace wolf { WOLF_REGISTER_SENSOR_AUTO("RANGE BEARING", SensorRangeBearing) diff --git a/include/core/problem/problem.h b/include/core/problem/problem.h index d1aaba40fa7ff48ee93c83b625f62a80ba52d382..03e9b056ae883487e679edfa49f0ecbd69a4d18a 100644 --- a/include/core/problem/problem.h +++ b/include/core/problem/problem.h @@ -19,8 +19,8 @@ struct ProcessorParamsBase; #include "core/frame/frame_base.h" #include "core/state_block/state_block.h" #include "core/utils/params_server.hpp" -#include "core/sensor/autoconf_sensor_factory.h" -#include "core/processor/autoconf_processor_factory.h" +#include "core/sensor/sensor_factory.h" +#include "core/processor/processor_factory.h" // std includes #include <mutex> diff --git a/include/core/processor/autoconf_processor_factory.h b/include/core/processor/autoconf_processor_factory.h deleted file mode 100644 index 418f488f9587388361dbfab8d015ad458732454e..0000000000000000000000000000000000000000 --- a/include/core/processor/autoconf_processor_factory.h +++ /dev/null @@ -1,184 +0,0 @@ -/** - * \file processor_factory.h - * - * Created on: May 4, 2016 - * \author: jsola - */ - -#ifndef AUTOCONF_PROCESSOR_FACTORY_H_ -#define AUTOCONF_PROCESSOR_FACTORY_H_ - -namespace wolf -{ -class ProcessorBase; -struct ProcessorParamsBase; -} - -// wolf -#include "core/common/factory.h" - -// std - -namespace wolf -{ -/** \brief Processor factory class - * - * This factory can create objects of classes deriving from ProcessorBase. - * - * 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 ProcessorFactory class is a singleton: it can only exist once in your application. - * To obtain an instance of it, use the static method get(), - * - * \code - * ProcessorFactory::get() - * \endcode - * - * You can then call the methods you like, e.g. to create a processor, you type: - * - * \code - * ProcessorFactory::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(). - * You provide a processor type string (above), and a pointer to a static method - * that knows how to create your specific processor, e.g.: - * - * \code - * ProcessorFactory::get().registerCreator("ODOM 2D", 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, ProcessorParamsBasePtr, - * that can be derived for each derived processor. - * - * Here is an example of ProcessorOdom2D::create() extracted from processor_odom_2D.h: - * - * \code - * static ProcessorBasePtr create(const std::string& _name, ProcessorParamsBasePtr _params) - * { - * // cast _params to good type - * ProcessorParamsOdom2D* params = (ProcessorParamsOdom2D*)_params; - * - * ProcessorBasePtr prc = new ProcessorOdom2D(params); - * prc->setName(_name); // pass the name to the created ProcessorOdom2D. - * return prc; - * } - * \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: - * - * \code - * const bool registered_odom_2D = ProcessorFactory::get().registerCreator("ODOM 2D", ProcessorOdom2D::create); - * \endcode - * - * 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. - * - * #### Unregister processor creators - * The method unregisterCreator() unregisters the ProcessorXxx::create() method. - * It only needs to be passed the string of the processor type. - * - * \code - * ProcessorFactory::get().unregisterCreator("ODOM 2D"); - * \endcode - * - * #### Creating processors - * 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 - * ProcessorFactory::get().create("ODOM 2D", "main odometry", params_ptr); - * \endcode - * - * #### Example 1 : using the Factories alone - * We provide the necessary steps to create a processor of class ProcessorOdom2D in our application, - * and bind it to a SensorOdom2D: - * - * \code - * #include "sensor_odom_2D.h" // provides SensorOdom2D and SensorFactory - * #include "processor_odom_2D.h" // provides ProcessorOdom2D and ProcessorFactory - * - * // Note: SensorOdom2D::create() is already registered, automatically. - * // Note: ProcessorOdom2D::create() is already registered, automatically. - * - * // First create the sensor (See SensorFactory for details) - * SensorBasePtr sensor_ptr = SensorFactory::get().create ( "ODOM 2D" , "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: - * - * ProcessorParamsOdom2D params({...}); // fill in the derived struct (note: ProcessorOdom2D actually has no input params) - * - * ProcessorBasePtr processor_ptr = - * ProcessorFactory::get().create ( "ODOM 2D" , "main odometry" , ¶ms ); - * - * // 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 "sensor_odom_2D.h" - * #include "processor_odom_2D.h" - * #include "problem.h" - * - * Problem problem(FRM_PO_2D); - * problem.installSensor ( "ODOM 2D" , "Main odometer" , extrinsics , &intrinsics ); - * problem.installProcessor ( "ODOM 2D" , "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 ParamsServer&> AutoConfProcessorFactory; -template<> -inline std::string AutoConfProcessorFactory::getClass() -{ - return "AutoConfProcessorFactory"; -} - - -#define WOLF_REGISTER_PROCESSOR_AUTO(ProcessorType, ProcessorName) \ - namespace{ const bool WOLF_UNUSED ProcessorName##AutoConf##Registered = \ - wolf::AutoConfProcessorFactory::get().registerCreator(ProcessorType, ProcessorName::createAutoConf); }\ - -} /* namespace wolf */ - -#endif /* PROCESSOR_FACTORY_H_ */ diff --git a/include/core/processor/processor_factory.h b/include/core/processor/processor_factory.h index 4b305a83b944b371a36f151175d4d7ef63633d42..808227484fbfacf511ca4be4793cd1fe84db472a 100644 --- a/include/core/processor/processor_factory.h +++ b/include/core/processor/processor_factory.h @@ -174,9 +174,23 @@ inline std::string ProcessorFactory::getClass() return "ProcessorFactory"; } -#define WOLF_REGISTER_PROCESSOR(ProcessorType, ProcessorName) \ - namespace{ const bool WOLF_UNUSED ProcessorName##Registered = \ - wolf::ProcessorFactory::get().registerCreator(ProcessorType, ProcessorName::create); }\ +#define WOLF_REGISTER_PROCESSOR(ProcessorType, ProcessorName) \ + namespace{ const bool WOLF_UNUSED ProcessorName##Registered = \ + wolf::ProcessorFactory::get().registerCreator(ProcessorType, ProcessorName::create); } \ + +typedef Factory<ProcessorBase, + const std::string&, + const ParamsServer&> AutoConfProcessorFactory; +template<> +inline std::string AutoConfProcessorFactory::getClass() +{ + return "AutoConfProcessorFactory"; +} + + +#define WOLF_REGISTER_PROCESSOR_AUTO(ProcessorType, ProcessorName) \ + namespace{ const bool WOLF_UNUSED ProcessorName##AutoConfRegistered = \ + wolf::AutoConfProcessorFactory::get().registerCreator(ProcessorType, ProcessorName::createAutoConf); } \ } /* namespace wolf */ diff --git a/include/core/sensor/autoconf_sensor_factory.h b/include/core/sensor/autoconf_sensor_factory.h deleted file mode 100644 index 2d36307874fddbe2836ea1f905719007934cf679..0000000000000000000000000000000000000000 --- a/include/core/sensor/autoconf_sensor_factory.h +++ /dev/null @@ -1,227 +0,0 @@ -/** - * \file sensor_factory.h - * - * Created on: Apr 25, 2016 - * \author: jsola - */ - -#ifndef AUTOCONF_SENSOR_FACTORY_H_ -#define AUTOCONF_SENSOR_FACTORY_H_ - -namespace wolf -{ -class SensorBase; -struct IntrinsicsBase; -} - -// wolf -#include "core/common/factory.h" - -namespace wolf -{ - -/** \brief Sensor 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 SensorFactory 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 - * SensorFactory::get() - * \endcode - * - * You can then call the methods you like, e.g. to create a sensor, you type: - * - * \code - * SensorFactory::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 - * SensorFactory::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, IntrinsicsBasePtr, - * that can be derived for each derived sensor: - * - * \code - * static SensorBasePtr create(const std::string& _name, Eigen::VectorXs& _extrinsics_pq, IntrinsicsBasePtr _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 = SensorFactory::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 - * SensorFactory::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 - * SensorFactory::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 - * - IntrinsicsFactory: to create intrinsic structs deriving from IntrinsicsBase directly from YAML files. - * - ProcessorFactory: 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::VectorXs& _extrinsics_pq, IntrinsicsBasePtr _intrinsics) - * { - * // check extrinsics vector - * assert(_extrinsics_pq.size() == 7 && "Bad extrinsics vector length. Should be 7 for 3D."); - * - * // cast instrinsics to good type - * IntrinsicsCamera* intrinsics_ptr = (IntrinsicsCamera*) _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 = SensorFactory::get().registerCreator("CAMERA", SensorCamera::create); - * } - * main () { ... } - * \endcode - * or inside your main(), where a direct call is possible: - * \code - * main () { - * SensorFactory::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 = SensorFactory::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 "sensor_factory.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::VectorXs extrinsics_1(7); // give it some values... - * IntrinsicsCamera intrinsics_1({...}); // see IntrinsicsFactory to fill in the derived struct - * - * SensorBasePtr camera_1_ptr = - * SensorFactory::get().create ( "CAMERA" , "Front-left camera" , extrinsics_1 , &intrinsics_1 ); - * - * // A second camera... with a different name! - * - * Eigen::VectorXs extrinsics_2(7); - * IntrinsicsCamera intrinsics_2({...}); - * - * SensorBasePtr camera_2_ptr = - * SensorFactory::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<SensorBase, - const std::string&, - const ParamsServer&> AutoConfSensorFactory; - -template<> -inline std::string AutoConfSensorFactory::getClass() -{ - return "AutoConfSensorFactory"; -} - -#define WOLF_REGISTER_SENSOR_AUTO(SensorType, SensorName) \ - namespace{ const bool WOLF_UNUSED SensorName##AutConf##Registered = \ - AutoConfSensorFactory::get().registerCreator(SensorType, SensorName::createAutoConf); } \ - -} /* namespace wolf */ - -#endif /* SENSOR_FACTORY_H_ */ diff --git a/include/core/sensor/sensor_factory.h b/include/core/sensor/sensor_factory.h index abe8b64180cdd5f0c2e95cd9eb6ccfe636e83e3a..5d3976e9b335e2db1c9965e9309db88c4633767a 100644 --- a/include/core/sensor/sensor_factory.h +++ b/include/core/sensor/sensor_factory.h @@ -218,9 +218,25 @@ inline std::string SensorFactory::getClass() return "SensorFactory"; } -#define WOLF_REGISTER_SENSOR(SensorType, SensorName) \ - namespace{ const bool WOLF_UNUSED SensorName##Registered = \ - SensorFactory::get().registerCreator(SensorType, SensorName::create); }\ +#define WOLF_REGISTER_SENSOR(SensorType, SensorName) \ + namespace{ const bool WOLF_UNUSED SensorName##Registered = \ + SensorFactory::get().registerCreator(SensorType, SensorName::create); } \ + + +typedef Factory<SensorBase, + const std::string&, + const ParamsServer&> AutoConfSensorFactory; + +template<> +inline std::string AutoConfSensorFactory::getClass() +{ + return "AutoConfSensorFactory"; +} + +#define WOLF_REGISTER_SENSOR_AUTO(SensorType, SensorName) \ + namespace{ const bool WOLF_UNUSED SensorName##AutoConfRegistered = \ + AutoConfSensorFactory::get().registerCreator(SensorType, SensorName::createAutoConf); } \ + } /* namespace wolf */ diff --git a/src/processor/processor_diff_drive.cpp b/src/processor/processor_diff_drive.cpp index 52cf7ebd9550fb1938b6d80983b60789d9db0e8e..261a3e36750ced950a7eb59b4ae48b038adc836b 100644 --- a/src/processor/processor_diff_drive.cpp +++ b/src/processor/processor_diff_drive.cpp @@ -176,7 +176,6 @@ FactorBasePtr ProcessorDiffDrive::emplaceFactor(FeatureBasePtr _feature, namespace wolf { WOLF_REGISTER_PROCESSOR("DIFF DRIVE", ProcessorDiffDrive) } // namespace wolf -#include "core/processor/autoconf_processor_factory.h" namespace wolf { WOLF_REGISTER_PROCESSOR_AUTO("DIFF DRIVE", ProcessorDiffDrive) } // namespace wolf diff --git a/src/processor/processor_odom_2D.cpp b/src/processor/processor_odom_2D.cpp index 25e45242af0d6a52eb77adb8ba0f26c8517b08a3..58131ed9136ba6e89aa893c7abc9e8b0b8d3a875 100644 --- a/src/processor/processor_odom_2D.cpp +++ b/src/processor/processor_odom_2D.cpp @@ -176,7 +176,6 @@ FeatureBasePtr ProcessorOdom2D::emplaceFeature(CaptureMotionPtr _capture_motion) namespace wolf { WOLF_REGISTER_PROCESSOR("ODOM 2D", ProcessorOdom2D) } // namespace wolf -#include "core/processor/autoconf_processor_factory.h" namespace wolf { WOLF_REGISTER_PROCESSOR_AUTO("ODOM 2D", ProcessorOdom2D) } // namespace wolf