Skip to content
Snippets Groups Projects
Commit 4f91dcb7 authored by Angel Santamaria-Navarro's avatar Angel Santamaria-Navarro
Browse files

added a file to try factories.

parent eb93dfc8
No related branches found
No related tags found
No related merge requests found
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
SET(sources vision_utils.cpp cam_utils/cam_utils.cpp feature_detector/feature_detector.cpp feature_descriptor/feature_descriptor.cpp feature_matcher/feature_matcher.cpp) SET(sources vision_utils.cpp cam_utils/cam_utils.cpp feature_detector/feature_detector.cpp feature_descriptor/feature_descriptor.cpp feature_matcher/feature_matcher.cpp)
# application header files # application header files
SET(headers vision_utils.h vu_base/vu_base.h cam_utils/cam_utils.h feature_detector/feature_detector.h feature_descriptor/feature_descriptor.h feature_matcher/feature_matcher.h) SET(headers vision_utils.h common/vu_base.h cam_utils/cam_utils.h feature_detector/feature_detector.h feature_descriptor/feature_descriptor.h feature_matcher/feature_matcher.h)
# locate the necessary dependencies # locate the necessary dependencies
FIND_PACKAGE(Eigen3 REQUIRED) FIND_PACKAGE(Eigen3 REQUIRED)
......
#ifndef FACTORY_H_
#define FACTORY_H_
// wolf
//#include "wolf.h"
// std
#include <string>
#include <map>
#include <iostream>
#include <iomanip>
namespace cv_utils
{
/** \brief Singleton template factory
*
* This class implements a generic factory as a singleton.
*
* > IMPORTANT: This template factory can be used to construct many different objects except:
* > - Objects deriving from DetectorBase --> see DetectorFactory
* > - Objects deriving from DescriptorBase --> see DescriptorFactory
* > - Objects deriving from MatcherBase --> see MatcherFactory
* >
* > 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 TypeInput type of the input argument. Typical cases are std::string for file names, and YAML::Node for YAML nodes.
*
* - The class is templatized on the class of the produced objects, __TypeBase__.
* The produced objects are always of a class deriving from TypeBase.
* The returned data is always a pointer to TypeBase.
*
* For example, you may use as __TypeBase__ the following types:
* - DetectorBase: the Factory creates detectors deriving from DetectorBase and returns base pointers ````DetectorBasePtr```` 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__:
* - ````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.
*
* ### Operation of the factory
*
* #### Rationale
*
* This factory can create objects of classes deriving from TypeBase.
*
* > For example, if you want to make a Detector factory, set TypeBase = DetectorBase.\n
* > Then, the factory will create specific detectors deriving from DetectorBase.\n
* > The specific type of detector (e.g. FAST, SIFT, ORB, 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
* - the TYPE of object to create is identified with a string
* - the params may be provided in different forms -- see TypeInput.
*
* The methods to create specific objects are called __creators__.
* Creators must be registered to the factory before they can be invoked for object creation.
*
* This documentation shows you how to:
* - Define correct TYPE names
* - Access the factory
* - Write object creators
* - Register and unregister object creators to the factory
* - Create objects using the factory
* - Examples: Write and register a detector creator for FAST.
*
* #### Define correct TYPE names
* The rule to make new TYPE strings unique is that you skip the generic 'Type' prefix from your class name,
* and you build a string in CAPITALS with space separators, e.g.:
* - ParamsDetectorORB -> ````"ORB PARAMS"````
* - ParamsMatcherKnn -> ````"KNN PARAMS"````
* - etc.
*
* #### Access the factory
* The first thing to know is that we have defined typedefs for the templates that we are using. For example:
*
* \code
* typedef Factory<ParamsBase, std::string> ParamsFactory;
* typedef Factory<DetectorBase, std::string> DetectorFactory;
* typedef Factory<DescriptorBase, YAML::Node> DescriptorFactory;
* \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.
* To access it, use the static method get(),
*
* \code
* Factory<MyTypeBase, MyTypeInput>::get()
* \endcode
*
* where, of course, you better make use of the appropriate typedef in place of ````Factory<MyTypeBase, MyTypeInput>````.
*
* You can then call the methods you like, e.g. to create a detector, you use:
*
* \code
* DetectorFactory::get().create(...); // see below for creating objects ...
* \endcode
*
* #### Write creator methods (in your derived object classes)
* The method DetectorORB::create(...) exists in the DetectorORB class as a static method.
* 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:
*
* \code
* static TypeBase* create( const TypeInput& );
* \endcode
*
* 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.
* - ````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:
*
* \code
* static ParamsBasePtr create(const std::string& _params_dot_yaml)
* static DetectorBasePtr create(const YAML::Node& _lmk_yaml_node)
* \endcode
*
* See further down for an implementation example.
*
* #### Register object creators
* Prior to invoking the creation of an object of a particular TYPE,
* you must register the creator for this type into the factory.
*
* Registering object creators into the factory is done through registerCreator().
* You provide an object TYPE string (above), and a pointer to a static method
* that knows how to create your specific object, e.g.:
*
* \code
* DetectorFactory::get().registerCreator("DETECTOR ORB", DetectorORB::create);
* \endcode
*
* #### Automatic registration
* Currently, registering is performed in specific source files, object_xxxx.cpp.
* For example, in detector_orb_yaml.cpp we find the line:
*
* \code
* const bool registered_detector_params = ParamsFactory::get().registerCreator("ORB PARAMS", createORBParams);
* \endcode
*
* which is a static invocation (i.e., it is placed at global scope outside of the ORBParams class).
*
* Therefore, at application level, all objects that have a .cpp file compiled are automatically registered.
*
* #### Unregister object creators
* The method unregisterCreator() unregisters the ObjectXxx::create() method. It only needs to be passed the string of the object type.
*
* \code
* Factory<MyTypeBase, MyTypeInput>::get().unregisterCreator("CAMERA");
* \endcode
*
* #### Create objects using the factory
* Note: Prior to invoking the creation of a object of a particular type,
* you must register the creator for this type into the factory.
*
* To create e.g. a DetectorORB from a YAML node you type:
*
* \code
* DetectorBasePtr det_orb_ptr = Factory<DetectorBasePtr, YAML::Node>::get().create("DETECTOR ORB", det_orb_yaml_node);
* \endcode
*
* or even better, make use of the convenient typedefs:
*
* \code
* DetectorBasePtr det_orb_ptr = DetectorFactory::get().create("DETECTOR ORB", det_orb_yaml_node);
* \endcode
*
* ### Examples
* TODO: Update this
* #### Example 1: Writing the creator of DetectorORB from a YAML node
*
* You can find this code in the detector_orb.cpp file.
*
* \code
* // Creator (this method is static):
* DetectorBasePtr DetectorORB::create(const YAML::Node& _det_orb_node)
* {
* // Parse YAML node with lmk info and data
* unsigned int id = _det_orb_node["id"].as<unsigned int>();
* int first_id = _det_orb_node["first_id"].as<int>();
* bool first_defined = _det_orb_node["first_defined"].as<bool>();
* bool last_defined = _det_orb_node["last_defined"].as<bool>();
* unsigned int npoints = _det_orb_node["points"].size();
* Eigen::MatrixXs points(2,npoints);
* for (unsigned int i = 0; i < npoints; i++)
* {
* points.col(i) = _lmk_node["points"][i].as<Eigen::Vector2s>();
* }
*
* // Create a new landmark
* LandmarkBasePtr lmk_ptr = new LandmarkPolyline2D(points, first_defined, last_defined, first_id);
* lmk_ptr->setId(id);
*
* return lmk_ptr;
* }
* \endcode
*
* #### Example 2: Registering the creator of LandmarkPolyline2D from a YAML node
*
* You can find this code in the landmark_polyline_2D.cpp file.
*
* \code
* // Register landmark creator (put the register code inside an unnamed namespace):
* namespace
* {
* const bool registered_lmk_polyline_2D = LandmarkFactory::get().registerCreator("POLYLINE 2D", LandmarkPolyline2D::create);
* }
*
* \endcode
*
* ### More information
* - IntrinsicsFactory: typedef of this template to create intrinsic structs deriving from IntrinsicsBase directly from YAML files.
* - ProcessorParamsFactory: typedef of this template to create processor params structs deriving from ProcessorParamsBase directly from YAML files.
* - LandmarkFactory: typedef of this template to create landmarks deriving from LandmarkBase directly from YAML nodes.
* - Problem::loadMap() : to load a maps directly from YAML files.
* - You can also check the code in the example file ````src/examples/test_map_yaml.cpp````.
*
* #### See also
* - SensorFactory: to create sensors
* - ProcessorFactory: to create processors.
* - Problem::installSensor() : to install sensors in WOLF Problem.
* - Problem::installProcessor() : to install processors in WOLF Problem.
*
*/
template<class TypeBase, typename... TypeInput>
class Factory
{
typedef std::shared_ptr<TypeBase> TypeBasePtr;
public:
// example of creator callback (see typedefs below)
typedef TypeBasePtr (*CreatorCallback)(TypeInput... _input);
// Main factory API
bool registerCreator(const std::string& _type, CreatorCallback createFn);
bool unregisterCreator(const std::string& _type);
TypeBasePtr create(const std::string& _type, TypeInput... _input);
std::string getClass();
private:
typedef std::map<std::string, CreatorCallback> CallbackMap;
CallbackMap callbacks_;
// Singleton ---------------------------------------------------
// This class is a singleton. The code below guarantees this.
// See: http://stackoverflow.com/questions/1008019/c-singleton-design-pattern
public:
static Factory& get();
Factory(const Factory&) = delete;
void operator=(Factory const&) = delete;
private:
Factory() { }
~Factory() { }
};
template<class TypeBase, typename... TypeInput>
inline bool Factory<TypeBase, TypeInput...>::registerCreator(const std::string& _type, CreatorCallback createFn)
{
bool reg = callbacks_.insert(typename CallbackMap::value_type(_type, createFn)).second;
if (reg)
std::cout << std::setw(22) << std::left << getClass() << " <-- registered " << _type << std::endl;
else
std::cout << std::setw(22) << std::left << getClass() << " X-- skipping " << _type << ": already registered." << std::endl;
return reg;
}
template<class TypeBase, typename... TypeInput>
inline bool Factory<TypeBase, TypeInput...>::unregisterCreator(const std::string& _type)
{
return callbacks_.erase(_type) == 1;
}
template<class TypeBase, typename... TypeInput>
inline typename Factory<TypeBase, TypeInput...>::TypeBasePtr Factory<TypeBase, TypeInput...>::create(const std::string& _type, TypeInput... _input)
{
typename CallbackMap::const_iterator creator_callback_it = callbacks_.find(_type);
if (creator_callback_it == callbacks_.end())
// not found
throw std::runtime_error(getClass() + " : Unknown type \"" + _type + "\". Possibly you tried to use an unregistered creator.");
// Invoke the creation function
return (creator_callback_it->second)(std::forward<TypeInput>(_input)...);
}
template<class TypeBase, typename... TypeInput>
inline Factory<TypeBase, TypeInput...>& Factory<TypeBase, TypeInput...>::get()
{
static Factory instance_;
return instance_;
}
template<class TypeBase, typename... TypeInput>
inline std::string Factory<TypeBase, TypeInput...>::getClass()
{
return "Factory<class TypeBase>";
}
// Some specializations
//======================
// Parameters
struct ParamsBase;
typedef Factory<ParamsBase,
const std::string&> ParamsFactory;
template<>
inline std::string ParamsFactory::getClass()
{
return "ParamsFactory";
}
// Frames
class FrameBase;
class TimeStamp;
typedef Factory<FrameBase, const FrameType&, const TimeStamp&, const Eigen::VectorXs&> FrameFactory;
template<>
inline std::string FrameFactory::getClass()
{
return "FrameFactory";
}
#define WOLF_REGISTER_FRAME(FrameType, FrameName) \
namespace{ const bool FrameName##Registered = \
FrameFactory::get().registerCreator(FrameType, FrameName::create); }\
} /* namespace cv_utils */
#endif /* FACTORY_H_ */
File moved
#ifndef _FEATURE_DESCRIPTOR_H #ifndef _FEATURE_DESCRIPTOR_H
#define _FEATURE_DESCRIPTOR_H #define _FEATURE_DESCRIPTOR_H
#include <vu_base/vu_base.h> #include "../common/vu_base.h"
typedef cv::Ptr<cv::DescriptorExtractor> FeatureDescriptorPtr; typedef cv::Ptr<cv::DescriptorExtractor> FeatureDescriptorPtr;
......
#ifndef _FEATURE_DETECTOR_H #ifndef _FEATURE_DETECTOR_H
#define _FEATURE_DETECTOR_H #define _FEATURE_DETECTOR_H
#include <vu_base/vu_base.h> #include "../common/vu_base.h"
#define SCALE_FACTOR_LINE_DETECTOR 2 #define SCALE_FACTOR_LINE_DETECTOR 2
#define NUM_OCTAVE_LINE_DETECTOR 1 #define NUM_OCTAVE_LINE_DETECTOR 1
......
#ifndef _FEATURE_MATCHER_H #ifndef _FEATURE_MATCHER_H
#define _FEATURE_MATCHER_H #define _FEATURE_MATCHER_H
#include "vu_base/vu_base.h" #include "../common/vu_base.h"
typedef cv::Ptr<cv::DescriptorMatcher> FeatureMatcherPtr; typedef cv::Ptr<cv::DescriptorMatcher> FeatureMatcherPtr;
......
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