API review
Proposer: Tully Foote
Present at review:
- Josh
- Tully
- Melonee
- Sachin
Question / concerns / comments
Enter your thoughts on the API and any questions / concerns you have here. Please sign your name. Anything you want to address in the API review should be marked down here before the start of the meeting.
Josh:
In general, anything implicitly allocated through a function (ie. FilterFactory::CreateObject) should be freed through a function in the library as well, rather than just deleting it. I'm not sure if Loki::Factory supports this.
Base Class and Factory Definition
/** \todo there's got to be a better way to do this. */
template <typename T>
std::string getTypeString();
template <>
std::string getTypeString<float>() { return std::string("<float>");};
template <>
std::string getTypeString<double>() { return std::string("<double>");};
/** \brief A Base filter class to provide a standard interface for all filters
*
*/
template<typename T>
class FilterBase
{
public:
FilterBase(){};
virtual ~FilterBase(){};
virtual bool configure(unsigned int number_of_elements, const std::string & arguments)=0;
/** \brief Update the filter and return the data seperately
*/
virtual bool update(const T* const data_in, T* data_out)=0;
std::string getType() {return getTypeString<T>();};
};
template <typename T>
class FilterFactory : public Loki::SingletonHolder < Loki::Factory< filters::FilterBase<T>, std::string >,
Loki::CreateUsingNew,
Loki::LongevityLifetime::DieAsSmallObjectChild >
{
//empty
};
Factory Registration Macro
#define ROS_REGISTER_FILTER(c,t) \
filters::FilterBase<t> * Filters_New_##c##__##t() {return new c<t>;}; \
bool ROS_FILTER_## c ## _ ## t = \
filters::FilterFactory<t>::Instance().Register(#c "<" #t ">", Filters_New_##c##__##t);
Example Filter
/** \brief A median filter which works on double arrays.
*
*/
template <typename T>
class MeanFilter: public FilterBase <T>
{
public:
/** \brief Construct the filter with the expected width and height */
MeanFilter();
/** \brief Destructor to clean up
*/
~MeanFilter();
virtual bool configure(unsigned int elements_per_observation, const std::string& number_of_observations);
/** \brief Update the filter and return the data seperately
* \param data_in T array with length elements_per_observation
* \param data_out T array with length elements_per_observation
*/
virtual bool update(T const * const data_in, T* data_out);
protected:
T * data_storage_; ///< Storage for data between updates
uint32_t last_updated_row_; ///< The last row to have been updated by the filter
uint32_t iterations_; ///< Number of iterations up to number of observations
uint32_t number_of_observations_; ///< Number of observations over which to filter
uint32_t elements_per_observation_; ///< Number of elements per observation
bool configured_;
};
ROS_REGISTER_FILTER(MeanFilter, double)
ROS_REGISTER_FILTER(MeanFilter, float)
Example Factory Usage
filters::FilterBase<float> * a_filter = filters::FilterFactory<float>::Instance().CreateObject("TestFilter<float>"); filters::FilterBase<float> * a1_filter = filters::FilterFactory<float>::Instance().CreateObject("TestFilter<float>"); filters::FilterBase<double> * b_filter = filters::FilterFactory<double>::Instance().CreateObject("TestFilter<double>"); printf("a is of type: %s\n b is of type: %s \n", a_filter->getType().c_str(), b_filter->getType().c_str()); a_filter->configure(4, ""); delete a_filter; delete a1_filter; delete b_filter;
FIlter Chain Object
template <typename T>
class FilterChain
{
public:
/** \brief Create the filter chain object */
FilterChain()
/** \brief Configure the filter chain
* This will call configure on all filters which have been added
* as well as allocate the buffers*/
bool configure(unsigned int size);
/** \brief Add filters to the list of filters to run on incoming data
* This will not configure, you must call configure before they will
* be useful. */
bool add(const std::string& filter_name, const std::string& filter_arguments);
/** \brief Clear all filters from this chain */
bool clear();
/** \brief process data through each of the filters added sequentially */
bool update(const T* const data_in, T* data_out);
~FilterChain();
Meeting agenda
Conclusion
Package status change mark change manifest)
Action items that need to be taken.
Major issues that need to be resolved
find a way to use the template type of the factory instead of passing the type in a string. - create/use a way to delete the factory generated filters
- document that all filters should be realtime safe
- except for configure
- want to see intermediate values for debugging
- provide facility to get callback for intermediate values
- callback will provide name of filter and resultant values pointer
- blocking on filter progress
standardize arguments with something (yaml, tinyxml, key value pair?, ros::node::param syntax)
standard way to do vectors with examples
initialize/add from xml would be useful - simpler interface to tinyxml which might be extended to controllers if it works well
Stu:
- I would feel better if update took std::vector's instead of plain arrays so that we avoid memory issues.
- Is the getType method really necessary?
FilterChain::add should not create and configure the filter itself. Instead, it should take ownership of a filter constructed elsewhere
FilterChain::add should check that the order of the filter matches the order of the chain (order = number of data elements. Maybe "width" is a better word)