1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Pose computation from any features.
33  *
34  * Authors:
35  * Aurelien Yol
36  *
37  *****************************************************************************/
38 
39 /*!
40   \file vpPose.h
41   \brief Tools for pose computation from any feature.
42 
43   \author Aurelien Yol
44   \date   June, 5 2012
45 */
46 
47 #ifndef vpPoseFeatures_HH
48 #define vpPoseFeatures_HH
49 
50 #include <visp3/core/vpConfig.h>
51 
52 #ifdef VISP_HAVE_MODULE_VISUAL_FEATURES
53 
54 #include <visp3/core/vpCircle.h>
55 #include <visp3/core/vpCylinder.h>
56 #include <visp3/core/vpDebug.h>
57 #include <visp3/core/vpException.h>
58 #include <visp3/core/vpExponentialMap.h>
59 #include <visp3/core/vpForwardProjection.h>
60 #include <visp3/core/vpLine.h>
61 #include <visp3/core/vpPoint.h>
62 #include <visp3/core/vpRobust.h>
63 #include <visp3/core/vpSphere.h>
64 #include <visp3/visual_features/vpBasicFeature.h>
65 #include <visp3/visual_features/vpFeatureBuilder.h>
66 #include <visp3/visual_features/vpFeatureEllipse.h>
67 #include <visp3/visual_features/vpFeaturePoint.h>
68 
69 #include <iostream>
70 #include <vector>
71 
72 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
73 #include <tuple>
74 
75 #ifndef DOXYGEN_SHOULD_SKIP_THIS
76 //#################################################
77 //##  Call a function with a tuple as parameters
78 //#################################################
79 template <unsigned int N> struct vpDesiredFeatureBuilderWithTuple {
80   template <typename featureType, typename RetType, typename... ArgsF, typename... ArgsT, typename... Args>
buildDesiredFeatureWithTuplevpDesiredFeatureBuilderWithTuple81   static void buildDesiredFeatureWithTuple(featureType &feature, RetType (*f)(ArgsF...), const std::tuple<ArgsT...> &t,
82                                            Args &&... args)
83   {
84     vpDesiredFeatureBuilderWithTuple<N - 1>::buildDesiredFeatureWithTuple(feature, f, t, std::get<N - 1>(t), args...);
85   }
86 };
87 
88 template <> struct vpDesiredFeatureBuilderWithTuple<0> {
89   template <typename featureType, typename RetType, typename... ArgsF, typename... ArgsT, typename... Args>
90   static void buildDesiredFeatureWithTuple(featureType & /* feature */, RetType (*f)(ArgsF...),
91                                            const std::tuple<ArgsT...> & /* t */, Args &&... args)
92   {
93     f(args...);
94   }
95 };
96 
97 template <> struct vpDesiredFeatureBuilderWithTuple<1> {
98   template <typename featureType, typename RetType, typename... ArgsF, typename... ArgsT, typename... Args>
99   static void buildDesiredFeatureWithTuple(featureType &feature, RetType (*f)(ArgsF...), const std::tuple<ArgsT...> &t,
100                                            Args &&... args)
101   {
102     vpDesiredFeatureBuilderWithTuple<0>::buildDesiredFeatureWithTuple(feature, f, t, feature, args...);
103   }
104 };
105 
106 template <typename featureType, typename RetType, typename... Args, typename... ArgsFunc>
107 void buildDesiredFeatureWithTuple(featureType &feature, RetType (*f)(ArgsFunc...), std::tuple<Args...> const &t)
108 {
109   vpDesiredFeatureBuilderWithTuple<sizeof...(Args)>::buildDesiredFeatureWithTuple(feature, f, t);
110 }
111 
112 //#################################################
113 //##  Call a function with a tuple as parameters
114 //##  Object Mode
115 //#################################################
116 
117 template <unsigned int N> struct vpDesiredFeatureBuilderObjectWithTuple {
118   template <typename objType, typename featureType, typename RetType, typename... ArgsF, typename... ArgsT,
119             typename... Args>
120   static void buildDesiredFeatureObjectWithTuple(objType *obj, featureType &feature, RetType (objType::*f)(ArgsF...),
121                                                  const std::tuple<ArgsT...> &t, Args &&... args)
122   {
123     vpDesiredFeatureBuilderObjectWithTuple<N - 1>::buildDesiredFeatureObjectWithTuple(obj, feature, f, t,
124                                                                                       std::get<N - 1>(t), args...);
125   }
126 };
127 
128 template <> struct vpDesiredFeatureBuilderObjectWithTuple<0> {
129   template <typename objType, typename featureType, typename RetType, typename... ArgsF, typename... ArgsT,
130             typename... Args>
131   static void buildDesiredFeatureObjectWithTuple(objType *obj, featureType & /*feature*/,
132                                                  RetType (objType::*f)(ArgsF...), const std::tuple<ArgsT...> & /* t */,
133                                                  Args &&... args)
134   {
135     (obj->*f)(args...);
136   }
137 };
138 
139 template <> struct vpDesiredFeatureBuilderObjectWithTuple<1> {
140   template <typename objType, typename featureType, typename RetType, typename... ArgsF, typename... ArgsT,
141             typename... Args>
142   static void buildDesiredFeatureObjectWithTuple(objType *obj, featureType &feature, RetType (objType::*f)(ArgsF...),
143                                                  const std::tuple<ArgsT...> &t, Args &&... args)
144   {
145     vpDesiredFeatureBuilderObjectWithTuple<0>::buildDesiredFeatureObjectWithTuple(obj, feature, f, t, feature, args...);
146   }
147 };
148 
149 template <typename objType, typename featureType, typename RetType, typename... Args, typename... ArgsFunc>
150 void buildDesiredFeatureObjectWithTuple(objType *obj, featureType &feature, RetType (objType::*f)(ArgsFunc...),
151                                         std::tuple<Args...> const &t)
152 {
153   vpDesiredFeatureBuilderObjectWithTuple<sizeof...(Args)>::buildDesiredFeatureObjectWithTuple(obj, feature, f, t);
154 }
155 
156 //#####################################################
157 //##  Call un function with a tuple as parameters
158 //##  Track all the parameters with the cMo
159 //##  Except the first one (must be de "BasicFeature"
160 //#####################################################
161 
162 template <unsigned int N> struct vpCurrentFeatureBuilderWithTuple {
163   template <typename featureType, typename RetType, typename... ArgsTuple, typename... ArgsDecomposed,
164             typename... ArgsF>
165   static void buildCurrentFeatureWithTuple(featureType &feature, const vpHomogeneousMatrix &cMo, RetType (*f)(ArgsF...),
166                                            std::tuple<ArgsTuple...> &t, ArgsDecomposed &&... args)
167   {
168     auto proj = std::get<N - 1>(t);
169     proj.track(cMo);
170     vpCurrentFeatureBuilderWithTuple<N - 1>::buildCurrentFeatureWithTuple(feature, cMo, f, t, proj, args...);
171   }
172 };
173 
174 template <> struct vpCurrentFeatureBuilderWithTuple<0> {
175   template <typename featureType, typename RetType, typename... ArgsTuple, typename... ArgsDecomposed,
176             typename... ArgsF>
177   static void buildCurrentFeatureWithTuple(featureType & /*feature*/, const vpHomogeneousMatrix & /*cMo*/,
178                                            RetType (*f)(ArgsF...), std::tuple<ArgsTuple...> &,
179                                            ArgsDecomposed &&... args)
180   {
181     f(args...);
182   }
183 };
184 
185 template <> struct vpCurrentFeatureBuilderWithTuple<1> {
186   template <typename featureType, typename RetType, typename... ArgsTuple, typename... ArgsDecomposed,
187             typename... ArgsF>
188   static void buildCurrentFeatureWithTuple(featureType &feature, const vpHomogeneousMatrix &cMo, RetType (*f)(ArgsF...),
189                                            std::tuple<ArgsTuple...> &t, ArgsDecomposed &&... args)
190   {
191     vpCurrentFeatureBuilderWithTuple<0>::buildCurrentFeatureWithTuple(feature, cMo, f, t, feature, args...);
192   }
193 };
194 
195 template <typename featureType, typename RetType, typename... ArgsTuple, typename... ArgsFunc>
196 void buildCurrentFeatureWithTuple(featureType &feature, const vpHomogeneousMatrix &cMo, RetType (*f)(ArgsFunc...),
197                                   std::tuple<ArgsTuple...> &t)
198 {
199   vpCurrentFeatureBuilderWithTuple<sizeof...(ArgsTuple)>::buildCurrentFeatureWithTuple(feature, cMo, f, t);
200 }
201 
202 //#####################################################
203 //##  Call un function with a tuple as parameters
204 //##  Track all the parameters with the cMo
205 //##  Except the first one (must be de "BasicFeature"
206 //##  Object Mode
207 //#####################################################
208 
209 template <unsigned int N> struct vpCurrentFeatureBuilderObjectWithTuple {
210   template <typename objType, typename featureType, typename RetType, typename... ArgsTuple, typename... ArgsDecomposed,
211             typename... ArgsF>
212   static void buildCurrentFeatureObjectWithTuple(objType *obj, featureType &feature, const vpHomogeneousMatrix &cMo,
213                                                  RetType (objType::*f)(ArgsF...), std::tuple<ArgsTuple...> &t,
214                                                  ArgsDecomposed &&... args)
215   {
216     auto proj = std::get<N - 1>(t);
217     proj.track(cMo);
218     vpCurrentFeatureBuilderObjectWithTuple<N - 1>::buildCurrentFeatureObjectWithTuple(obj, feature, cMo, f, t, proj,
219                                                                                       args...);
220   }
221 };
222 
223 template <> struct vpCurrentFeatureBuilderObjectWithTuple<0> {
224   template <typename objType, typename featureType, typename RetType, typename... ArgsTuple, typename... ArgsDecomposed,
225             typename... ArgsF>
226   static void buildCurrentFeatureObjectWithTuple(objType *obj, featureType & /*feature*/,
227                                                  const vpHomogeneousMatrix & /*cMo*/, RetType (objType::*f)(ArgsF...),
228                                                  std::tuple<ArgsTuple...> &, ArgsDecomposed &&... args)
229   {
230     (obj->*f)(args...);
231   }
232 };
233 
234 template <> struct vpCurrentFeatureBuilderObjectWithTuple<1> {
235   template <typename objType, typename featureType, typename RetType, typename... ArgsTuple, typename... ArgsDecomposed,
236             typename... ArgsF>
237   static void buildCurrentFeatureObjectWithTuple(objType *obj, featureType &feature, const vpHomogeneousMatrix &cMo,
238                                                  RetType (objType::*f)(ArgsF...), std::tuple<ArgsTuple...> &t,
239                                                  ArgsDecomposed &&... args)
240   {
241     vpCurrentFeatureBuilderObjectWithTuple<0>::buildCurrentFeatureObjectWithTuple(obj, feature, cMo, f, t, feature,
242                                                                                   args...);
243   }
244 };
245 
246 template <typename objType, typename featureType, typename RetType, typename... ArgsTuple, typename... ArgsFunc>
247 void buildCurrentFeatureObjectWithTuple(objType *obj, featureType &feature, const vpHomogeneousMatrix &cMo,
248                                         RetType (objType::*f)(ArgsFunc...), std::tuple<ArgsTuple...> &t)
249 {
250   vpCurrentFeatureBuilderObjectWithTuple<sizeof...(ArgsTuple)>::buildCurrentFeatureObjectWithTuple(obj, feature, cMo, f,
251                                                                                                    t);
252 }
253 
254 //#################################################
255 //##  Call that will be used in our vpPoseFeatures
256 //##  to store the specific features.
257 //#################################################
258 /*!
259   \class vpPoseSpecificFeature
260   \ingroup group_vision_pose
261   \brief Class used to define specific features that could be considered in
262   pose estimation from visual features implemented in vpPoseFeatures.
263 */
264 class VISP_EXPORT vpPoseSpecificFeature
265 {
266 public:
267   vpPoseSpecificFeature() {}
268   virtual ~vpPoseSpecificFeature() {}
269 
270   virtual vpColVector error() = 0;
271   virtual vpMatrix currentInteraction() = 0;
272   virtual void createDesired() = 0;
273   virtual void createCurrent(const vpHomogeneousMatrix &cMo) = 0;
274 };
275 
276 //#################################################
277 //##  Template for all kind of specific features
278 //#################################################
279 
280 /*!
281   \class vpPoseSpecificFeatureTemplate
282   \ingroup group_vision_pose
283   \brief Template class that allows to estimate a pose from all kind of
284   specific features if the compiler support C++ 11.
285 */
286 template <typename featureType, typename RetType, typename... Args>
287 class vpPoseSpecificFeatureTemplate : public vpPoseSpecificFeature
288 {
289 private:
290   featureType desiredFeature;
291   featureType currentFeature;
292   std::tuple<Args...> *tuple;
293   RetType (*func_ptr)(Args...);
294 
295 public:
296   vpPoseSpecificFeatureTemplate(RetType (*f_ptr)(Args...), Args &&... args)
297   {
298     func_ptr = f_ptr; // std::move(f_ptr);
299     tuple = new std::tuple<Args...>(args...);
300   }
301 
302   virtual ~vpPoseSpecificFeatureTemplate() { delete tuple; }
303 
304   virtual void createDesired() { buildDesiredFeatureWithTuple(desiredFeature, func_ptr, *tuple); }
305 
306   virtual vpColVector error()
307   {
308     // std::cout << "Getting S... : " << std::get<0>(*tuple).get_s() <<
309     // std::endl;
310     return currentFeature.error(desiredFeature);
311   }
312 
313   virtual vpMatrix currentInteraction() { return currentFeature.interaction(); }
314 
315   virtual void createCurrent(const vpHomogeneousMatrix &cMo)
316   {
317     buildCurrentFeatureWithTuple(currentFeature, cMo, func_ptr, *tuple);
318   }
319 };
320 
321 //#################################################
322 //##  Template for all kind of specific features
323 //##  Object Mode
324 //#################################################
325 
326 /*!
327   \class vpPoseSpecificFeatureTemplateObject
328   \ingroup group_vision_pose
329   \brief Template class that allows to estimate a pose from all kind of
330   specific features if the compiler support C++ 11.
331 */
332 template <typename ObjectType, typename featureType, typename RetType, typename... Args>
333 class vpPoseSpecificFeatureTemplateObject : public vpPoseSpecificFeature
334 {
335 private:
336   featureType desiredFeature;
337   featureType currentFeature;
338   std::tuple<Args...> *tuple;
339   RetType (ObjectType::*func_ptr)(Args...);
340   ObjectType *obj;
341 
342 public:
343   vpPoseSpecificFeatureTemplateObject(ObjectType *o, RetType (ObjectType::*f_ptr)(Args...), Args &&... args)
344   {
345     func_ptr = f_ptr; // std::move(f_ptr);
346     tuple = new std::tuple<Args...>(args...);
347     obj = o;
348   }
349 
350   virtual ~vpPoseSpecificFeatureTemplateObject() { delete tuple; }
351 
352   virtual void createDesired() { buildDesiredFeatureObjectWithTuple(obj, desiredFeature, func_ptr, *tuple); }
353 
354   virtual vpColVector error() { return currentFeature.error(desiredFeature); }
355 
356   virtual vpMatrix currentInteraction() { return currentFeature.interaction(); }
357 
358   virtual void createCurrent(const vpHomogeneousMatrix &cMo)
359   {
360     buildCurrentFeatureObjectWithTuple(obj, currentFeature, cMo, func_ptr, *tuple);
361   }
362 };
363 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
364 #endif // (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
365 
366 /*!
367   \class vpPoseFeatures
368   \brief Tools for pose computation from any feature.
369   \ingroup group_vision_pose
370 
371   This class allows to estimate a pose by virtual visual servoing from visual
372   features. The features that are considered are points, segments, lines,
373   ellipses. If the compiler is compatible with C++ 11, it is possible to
374   introduce specific features that are not directly implemented in ViSP.
375   */
376 class VISP_EXPORT vpPoseFeatures
377 {
378 public:
379   /*!
380     Method that will be used to estimate the pose from visual features.
381     */
382   typedef enum {
383     VIRTUAL_VS,       /*!< Virtual visual servoing approach. */
384     ROBUST_VIRTUAL_VS /*!< Robust virtual visual servoing approach. */
385   } vpPoseFeaturesMethodType;
386 
387 private:
388 #ifndef DOXYGEN_SHOULD_SKIP_THIS
389   template <typename FeatureType, typename FirstParamType> struct vpDuo {
390     FeatureType *desiredFeature;
391     FirstParamType firstParam;
392     vpDuo() : desiredFeature(NULL), firstParam() {}
393   };
394 
395   template <typename FeatureType, typename FirstParamType, typename SecondParamType> struct vpTrio {
396     FeatureType *desiredFeature;
397     FirstParamType firstParam;
398     SecondParamType secondParam;
399 
400     vpTrio() : desiredFeature(NULL), firstParam(), secondParam() {}
401   };
402 #endif //#ifndef DOXYGEN_SHOULD_SKIP_THIS
403 
404   unsigned int maxSize;
405   unsigned int totalSize;
406   unsigned int vvsIterMax;
407   double lambda;
408 
409   bool verbose;
410 
411   bool computeCovariance;
412   vpMatrix covarianceMatrix;
413 
414   // vpFeaturePoint
415   std::vector<vpDuo<vpFeaturePoint, vpPoint> > featurePoint_Point_list;
416   // vpFeaturePoint3D
417   std::vector<vpDuo<vpFeaturePoint3D, vpPoint> > featurePoint3D_Point_list;
418   // vpFeatureVanishingPoint
419   std::vector<vpDuo<vpFeatureVanishingPoint, vpPoint> > featureVanishingPoint_Point_list;
420   std::vector<vpTrio<vpFeatureVanishingPoint, vpLine, vpLine> > featureVanishingPoint_DuoLine_list;
421   // vpFeatureEllipse
422   std::vector<vpDuo<vpFeatureEllipse, vpSphere> > featureEllipse_Sphere_list;
423   std::vector<vpDuo<vpFeatureEllipse, vpCircle> > featureEllipse_Circle_list;
424   // vpFeatureLine
425   std::vector<vpDuo<vpFeatureLine, vpLine> > featureLine_Line_list;
426   std::vector<vpTrio<vpFeatureLine, vpCylinder, int> > featureLine_DuoLineInt_List;
427   // vpFeatureSegment
428   std::vector<vpTrio<vpFeatureSegment, vpPoint, vpPoint> > featureSegment_DuoPoints_list;
429 
430 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
431   // Specific features
432   std::vector<vpPoseSpecificFeature *> featureSpecific_list;
433 #endif
434 
435 public:
436   vpPoseFeatures();
437   virtual ~vpPoseFeatures();
438 
439   // ! Features addition
440   void addFeaturePoint(const vpPoint &);
441 
442   void addFeaturePoint3D(const vpPoint &);
443 
444   void addFeatureVanishingPoint(const vpPoint &);
445   void addFeatureVanishingPoint(const vpLine &, const vpLine &);
446 
447   void addFeatureEllipse(const vpCircle &);
448   void addFeatureEllipse(const vpSphere &);
449 
450   void addFeatureLine(const vpLine &);
451   void addFeatureLine(const vpCylinder &, const int &line);
452 
453   void addFeatureSegment(vpPoint &, vpPoint &);
454 
455 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
456   template <typename RetType, typename... ArgsFunc, typename... Args>
457   void addSpecificFeature(RetType (*fct_ptr)(ArgsFunc...), Args &&... args);
458 
459   template <typename ObjType, typename RetType, typename... ArgsFunc, typename... Args>
460   void addSpecificFeature(ObjType *obj, RetType (ObjType::*fct_ptr)(ArgsFunc...), Args &&... args);
461 #endif
462 
463   void clear();
464 
465   // ! Pose computation
466   void computePose(vpHomogeneousMatrix &cMo, const vpPoseFeaturesMethodType &type = VIRTUAL_VS);
467 
468   /*!
469     Get the covariance matrix of the pose parameters computed by virtual
470     visual servoing.
471 
472     \warning By default, the covariance matrix is not computed. To enable the
473     computation, use setCovarianceComputation().
474   */
475   vpMatrix getCovarianceMatrix() const
476   {
477     if (!computeCovariance)
478       vpTRACE("Warning : The covariance matrix has not been computed. See "
479               "setCovarianceComputation() to do it.");
480 
481     return covarianceMatrix;
482   }
483 
484   /*!
485     Get the gain that is used to compute the pose with the control law \f${\bf
486     v} = -\lambda {\bf L}^+ ({\bf s} - {\bf s}^*)\f$.
487 
488     \return Value of \f$\lambda\f$, the gain of the control law.
489   */
490   double getLambda() { return lambda; }
491 
492   /*!
493     Get the maximum number of iterations of the virtual visual servoing (VVS)
494     scheme implemented in computePose().
495 
496     \return Maximum number of iterations used during VVS minimization.
497   */
498   unsigned int getVVSIterMax() { return vvsIterMax; }
499 
500   /*!
501     Enable or disable covariance computation of the pose parameters.
502 
503     \param flag : True if the covariance has to be computed, false otherwise.
504   */
505   void setCovarianceComputation(const bool &flag) { computeCovariance = flag; }
506 
507   /*!
508     Set the gain used in the virtual visual servoing scheme : \f${\bf v} =
509     -\lambda {\bf L}^+ ({\bf s} - {\bf s}^*)\f$.
510 
511     \param val : Value of the gain \f$\lambda\f$.
512   */
513   void setLambda(const double &val) { lambda = val; }
514 
515   /*!
516     Set the maximum number of iterations used in computePose().
517 
518     \param val : Maximum number of iteration used in the VVS scheme.
519   */
520   void setVVSIterMax(const unsigned int &val) { vvsIterMax = val; }
521 
522   /*!
523    Turn the verbose mode ON / OFF.
524 
525    \param mode : new verbose state. True to turn ON, false otherwise.
526   */
527   void setVerbose(const bool &mode) { verbose = mode; }
528 
529 private:
530   void error_and_interaction(vpHomogeneousMatrix &cMo, vpColVector &err, vpMatrix &L);
531 
532   void computePoseVVS(vpHomogeneousMatrix &cMo);
533   void computePoseRobustVVS(vpHomogeneousMatrix &cMo);
534 };
535 
536 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
537 /*!
538   Add a specific feature for the pose computation.
539 
540   \param fct_ptr : pointer on the function used to create the feature.
541   \param args : List of function parameters;
542                 First argument supposed to be derived from vpBasicFeature
543   (redefine interaction() and error() functions), others are supposed to be
544   derived from vpForwardProjection (redefine track() function)
545 
546   \warning This function is only available with C++11. It has to be activated
547   with USE_CPP11 option from CMake.
548 
549   \code
550 #include <visp3/vision/vpPoseFeatures.h>
551 
552 void vp_createPoint(vpFeaturePoint &fp,const vpPoint &p){
553   vpFeatureBuilder::create(fp,p);
554 }
555 
556 void vp_createTwoPoint(vpFeaturePoint &fp,const vpPoint &p, const vpPoint&p2){
557   vpFeatureBuilder::create(fp,p);
558   vpFeatureBuilder::create(fp,p2);
559 }
560 
561 void vp_createLine(vpFeatureLine &fp,const vpLine &l){
562   vpFeatureBuilder::create(fp,l);
563 }
564 
565 int main()
566 {
567   vpPoseFeatures pose;
568 
569   vpPoint pts[4];
570   vpLine line;
571 
572   //... Projection of the points and line
573 
574   vpFeaturePoint fp;
575   vpFeatureLine fl;
576   void (*ptr)(vpFeaturePoint&, const vpPoint&) = &vpFeatureBuilder::create;
577 
578 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
579   pose.addSpecificFeature(ptr, fp, pts[0]);
580   pose.addSpecificFeature(&vp_createPoint, fp, pts[1]);
581   pose.addSpecificFeature(&vp_createTwoPoint, fp, pts[2], pts[3]);
582   pose.addSpecificFeature(&vp_createLine, fl, line);
583 #endif
584 
585   //... Pose Computation
586 
587   return 0;
588 }
589   \endcode
590 */
591 template <typename RetType, typename... ArgsFunc, typename... Args>
592 void vpPoseFeatures::addSpecificFeature(RetType (*fct_ptr)(ArgsFunc...), Args &&... args)
593 {
594   typedef typename std::tuple_element<0, std::tuple<Args...> >::type featureTypeReference;
595   typedef typename std::remove_reference<featureTypeReference>::type featureType;
596   featureSpecific_list.push_back(
597       new vpPoseSpecificFeatureTemplate<featureType, RetType, ArgsFunc...>(fct_ptr, std::forward<ArgsFunc>(args)...));
598 
599   featureSpecific_list.back()->createDesired();
600 
601   totalSize++;
602   if (featureSpecific_list.size() > maxSize)
603     maxSize = static_cast<unsigned int>(featureSpecific_list.size());
604 }
605 
606 /*!
607   Add a specific feature for the pose computation.
608 
609   \param obj : object used to call the function defined by fct_ptr.
610   \param fct_ptr : pointer on the function used to create the feature.
611   \param args : List of function parameters;
612                 First argument supposed to be derived from vpBasicFeature
613 (redefine interaction() and error() functions), others are supposed to be
614 derived from vpForwardProjection (redefine track() function)
615 
616   \warning This function is only available with C++11. It has to be activated
617 with USE_CPP11 option from CMake.
618 
619   \code
620 #include <visp3/vision/vpPoseFeatures.h>
621 
622 class vp_createClass{
623 public:
624   vp_createClass(){}
625 
626   int vp_createPoint(vpFeaturePoint &fp,const vpPoint &p) {
627     vpFeatureBuilder::create(fp,p);
628     return 2;
629   }
630 
631   void vp_createTwoPoint(vpFeaturePoint &fp,const vpPoint &p, const vpPoint &p2) {
632     vpFeatureBuilder::create(fp,p); vpFeatureBuilder::create(fp,p2);
633   }
634 
635   void vp_createLine(vpFeatureLine &fp,const vpLine &l) {
636     vpFeatureBuilder::create(fp,l);
637   }
638 };
639 
640 int main()
641 {
642   vpPoseFeatures pose;
643 
644   vpPoint pts[3];
645   vpLine line;
646 
647   //... Projection of the points and line
648 
649   vpFeaturePoint fp;
650   vpFeatureLine fl;
651 
652   vp_createClass cpClass;
653   int (vp_createClass::*ptrClassPoint)(vpFeaturePoint&, const vpPoint&)
654     = &vp_createClass::vp_createPoint;
655   void (vp_createClass::*ptrClassTwoPoint)(vpFeaturePoint&, const vpPoint&, const vpPoint&)
656     = &vp_createClass::vp_createTwoPoint;
657   void (vp_createClass::*ptrClassLine)(vpFeatureLine &, const vpLine &)
658     = &vp_createClass::vp_createLine;
659 
660 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
661   pose.addSpecificFeature(&cpClass, ptrClassPoint, fp, pts[0]);
662   pose.addSpecificFeature(&cpClass, ptrClassTwoPoint, fp, pts[1], pts[2]);
663   pose.addSpecificFeature(&cpClass, ptrClassLine, fl, line);
664 #endif
665 
666   //... Pose Computation
667 
668   return 0;
669 }
670   \endcode
671 */
672 template <typename ObjType, typename RetType, typename... ArgsFunc, typename... Args>
673 void vpPoseFeatures::addSpecificFeature(ObjType *obj, RetType (ObjType::*fct_ptr)(ArgsFunc...), Args &&... args)
674 {
675   typedef typename std::tuple_element<0, std::tuple<Args...> >::type featureTypeReference;
676   typedef typename std::remove_reference<featureTypeReference>::type featureType;
677   featureSpecific_list.push_back(new vpPoseSpecificFeatureTemplateObject<ObjType, featureType, RetType, ArgsFunc...>(
678       obj, fct_ptr, std::forward<ArgsFunc>(args)...));
679 
680   featureSpecific_list.back()->createDesired();
681 
682   totalSize++;
683   if (featureSpecific_list.size() > maxSize)
684     maxSize = static_cast<unsigned int>(featureSpecific_list.size());
685 }
686 #endif
687 
688 #endif //#ifdef VISP_HAVE_MODULE_VISUAL_FEATURES
689 
690 #endif
691