Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
vpFeatureMomentCentered.cpp
1/****************************************************************************
2 *
3 * ViSP, open source Visual Servoing Platform software.
4 * Copyright (C) 2005 - 2023 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 https://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 * Implementation for all supported moment features.
33 *
34 * Authors:
35 * Filip Novotny
36 * Manikandan Bakthavatchalam
37 *****************************************************************************/
38
39#include <visp3/core/vpConfig.h>
40
41#include <limits>
42#include <vector>
43
44#include <visp3/core/vpMomentCentered.h>
45#include <visp3/core/vpMomentGravityCenter.h>
46#include <visp3/core/vpMomentObject.h>
47#include <visp3/visual_features/vpFeatureMomentBasic.h>
48#include <visp3/visual_features/vpFeatureMomentCentered.h>
49#include <visp3/visual_features/vpFeatureMomentDatabase.h>
50#include <visp3/visual_features/vpFeatureMomentGravityCenter.h>
51
61vpFeatureMomentCentered::vpFeatureMomentCentered(vpMomentDatabase &moments_, double A_, double B_, double C_,
62 vpFeatureMomentDatabase *featureMoments)
63 : vpFeatureMoment(moments_, A_, B_, C_, featureMoments), order(0)
64{
65}
66
73vpMatrix vpFeatureMomentCentered::interaction(unsigned int select_one, unsigned int select_two) const
74{
75 if (select_one + select_two > moment->getObject().getOrder())
76 throw vpException(vpException::badValue, "The requested value has not "
77 "been computed, you should "
78 "specify a higher order.");
79 return interaction_matrices[select_two * order + select_one];
80}
81
87vpMatrix vpFeatureMomentCentered::compute_Lmu_pq(const unsigned int &p, const unsigned int &q, const double &xg,
88 const double &yg, const vpMatrix &L_xg, const vpMatrix &L_yg,
89 const vpMomentBasic &m,
90 const vpFeatureMomentBasic &feature_moment_m) const
91{
92 // term1, term2 and Lterm3 (matrix) will be repeatedly computed inside the
93 // innermost loop
94 double term1 = 0.0;
95 double term2 = 0.0;
96 vpMatrix Lterm3(1, 6);
97
98 double qcombl = 0.0;
99 double pcombkqcombl = 0.0;
100
101 double mkl = 0.0;
102 vpMatrix L_mkl;
103
104 int qml = 0; // q-l
105 double minus1pow = 0.; // (-1)^(p+q-k-l)
106 double pintom = 0.;
107
108 for (unsigned int k = 0; k <= p; ++k) {
109 int pmk = (int)p - (int)k;
110 double pcombk = static_cast<double>(vpMath::comb(p, k));
111 for (unsigned int l = 0; l <= q; ++l) {
112 qml = (int)q - (int)l;
113 qcombl = static_cast<double>(vpMath::comb(q, l));
114 minus1pow = pow((double)-1, (double)(pmk + qml));
115 pcombkqcombl = pcombk * qcombl;
116 mkl = m.get(k, l);
117 pintom = pcombkqcombl * mkl;
118 L_mkl = feature_moment_m.interaction(k, l);
119 if (pmk > 0)
120 term1 += pintom * pmk * pow(xg, pmk - 1) * pow(yg, qml) * minus1pow;
121 if (qml > 0)
122 term2 += pintom * qml * pow(xg, pmk) * pow(yg, qml - 1) * minus1pow;
123 Lterm3 += pcombkqcombl * pow(xg, pmk) * pow(yg, qml) * L_mkl * minus1pow;
124 }
125 }
126
127 // L_xg and L_yg stay constant with respect to the above loops. Lterm3 is
128 // summed over
129 vpMatrix L_mupq = L_xg * term1 + L_yg * term2 + Lterm3;
130 return L_mupq;
131}
132
145{
146#ifdef VISP_MOMENTS_COMBINE_MATRICES
147 const vpMomentObject &momentObject = moment->getObject();
148 order = momentObject.getOrder() + 1;
150 for (std::vector<vpMatrix>::iterator i = interaction_matrices.begin(); i != interaction_matrices.end(); ++i)
151 i->resize(1, 6);
152
153 bool found_moment_gravity;
154 const vpMomentGravityCenter &momentGravity =
155 static_cast<const vpMomentGravityCenter &>(moments.get("vpMomentGravityCenter", found_moment_gravity));
156 if (!found_moment_gravity)
157 throw vpException(vpException::notInitialized, "vpMomentGravityCenter not found");
158 double xg = momentGravity.get()[0];
159 double yg = momentGravity.get()[1];
160
161 bool found_feature_gravity_center;
162 vpFeatureMomentGravityCenter &featureMomentGravityCenter = (static_cast<vpFeatureMomentGravityCenter &>(
163 featureMomentsDataBase->get("vpFeatureMomentGravityCenter", found_feature_gravity_center)));
164 if (!found_feature_gravity_center)
165 throw vpException(vpException::notInitialized, "vpFeatureMomentGravityCenter not found");
166 vpMatrix Lxg = featureMomentGravityCenter.interaction(1 << 0);
167 vpMatrix Lyg = featureMomentGravityCenter.interaction(1 << 1);
168
169 bool found_moment_basic;
170 const vpMomentBasic &momentbasic =
171 static_cast<const vpMomentBasic &>(moments.get("vpMomentBasic", found_moment_basic));
172 if (!found_moment_basic)
173 throw vpException(vpException::notInitialized, "vpMomentBasic not found");
174
175 bool found_featuremoment_basic;
176 vpFeatureMomentBasic &featureMomentBasic = (static_cast<vpFeatureMomentBasic &>(
177 featureMomentsDataBase->get("vpFeatureMomentBasic", found_featuremoment_basic)));
178 if (!found_featuremoment_basic)
179 throw vpException(vpException::notInitialized, "vpFeatureMomentBasic not found");
180
181 // Calls the main compute_Lmu_pq function for moments upto order-1
182 for (int i = 0; i < (int)order - 1; i++) {
183 for (int j = 0; j < (int)order - 1 - i; j++) {
184 interaction_matrices[(unsigned int)j * order + (unsigned int)i] =
185 compute_Lmu_pq(i, j, xg, yg, Lxg, Lyg, momentbasic, featureMomentBasic);
186 }
187 }
188#else // #ifdef VISP_MOMENTS_COMBINE_MATRICES
189 bool found_moment_centered;
190 bool found_moment_gravity;
191
192 const vpMomentCentered &momentCentered =
193 (static_cast<const vpMomentCentered &>(moments.get("vpMomentCentered", found_moment_centered)));
194 const vpMomentGravityCenter &momentGravity =
195 static_cast<const vpMomentGravityCenter &>(moments.get("vpMomentGravityCenter", found_moment_gravity));
196
197 if (!found_moment_centered)
198 throw vpException(vpException::notInitialized, "vpMomentCentered not found");
199 if (!found_moment_gravity)
200 throw vpException(vpException::notInitialized, "vpMomentGravityCenter not found");
201
202 int delta;
203 int epsilon;
204 const vpMomentObject &momentObject = moment->getObject();
205 order = momentObject.getOrder() + 1;
207 for (std::vector<vpMatrix>::iterator i = interaction_matrices.begin(); i != interaction_matrices.end(); ++i)
208 i->resize(1, 6);
209 if (momentObject.getType() == vpMomentObject::DISCRETE) {
210 delta = 0;
211 epsilon = 1;
212 } else {
213 delta = 1;
214 epsilon = 4;
215 }
216 double n11 = momentCentered.get(1, 1) / momentObject.get(0, 0);
217 double n20 = momentCentered.get(2, 0) / momentObject.get(0, 0);
218 double n02 = momentCentered.get(0, 2) / momentObject.get(0, 0);
219 double Xg = momentGravity.getXg();
220 double Yg = momentGravity.getYg();
221 double mu00 = momentCentered.get(0, 0);
222
223 unsigned int VX = 0;
224 unsigned int VY = 1;
225 unsigned int VZ = 2;
226 unsigned int WX = 3;
227 unsigned int WY = 4;
228 unsigned int WZ = 5;
229
230 interaction_matrices[0][0][VX] = -(delta)*A * mu00;
231 interaction_matrices[0][0][VY] = -(delta)*B * mu00;
232
233 // Since mu10=0 and mu01=0
234 // interaction_matrices[0][0][WX] = (3*delta)*MU(0,1)+(3*delta)*Yg*mu00;
235 // interaction_matrices[0][0][WY] = -(3*delta)*MU(1,0)-(3*delta)*Xg*mu00;
236 // we get the simplification:
237 interaction_matrices[0][0][WX] = (3 * delta) * Yg * mu00;
238 interaction_matrices[0][0][WY] = -(3 * delta) * Xg * mu00;
239 interaction_matrices[0][0][VZ] =
240 -A * interaction_matrices[0][0][WY] + B * interaction_matrices[0][0][WX] + (2 * delta) * C * mu00;
241 interaction_matrices[0][0][WZ] = 0.;
242
243 for (int i = 1; i < (int)order - 1; i++) {
244 unsigned int i_ = (unsigned int)i;
245 unsigned int im1_ = i_ - 1;
246 unsigned int ip1_ = i_ + 1;
247
248 double mu_im10 = momentCentered.get(im1_, 0);
249 double mu_ip10 = momentCentered.get(ip1_, 0);
250 double mu_im11 = momentCentered.get(im1_, 1);
251 double mu_i0 = momentCentered.get(i_, 0);
252 double mu_i1 = momentCentered.get(i_, 1);
253
254 interaction_matrices[i_][0][VX] = -(i + delta) * A * mu_i0 - (i * B * mu_im11);
255 interaction_matrices[i_][0][VY] = -(delta)*B * mu_i0;
256
257 interaction_matrices[i_][0][WX] =
258 (i + 3 * delta) * mu_i1 + (i + 3 * delta) * Yg * mu_i0 + i * Xg * mu_im11 - i * epsilon * n11 * mu_im10;
259 interaction_matrices[i_][0][WY] =
260 -(i + 3 * delta) * mu_ip10 - (2 * i + 3 * delta) * Xg * mu_i0 + i * epsilon * n20 * mu_im10;
261 interaction_matrices[i_][0][VZ] =
262 -A * interaction_matrices[i_][0][WY] + B * interaction_matrices[i_][0][WX] + (i + 2 * delta) * C * mu_i0;
263 interaction_matrices[i_][0][WZ] = i * mu_im11;
264 }
265
266 for (int j = 1; j < (int)order - 1; j++) {
267 unsigned int j_ = (unsigned int)j;
268 unsigned int jm1_ = j_ - 1;
269 unsigned int jp1_ = j_ + 1;
270
271 double mu_0jm1 = momentCentered.get(0, jm1_);
272 double mu_0jp1 = momentCentered.get(0, jp1_);
273 double mu_1jm1 = momentCentered.get(1, jm1_);
274 double mu_0j = momentCentered.get(0, j_);
275 double mu_1j = momentCentered.get(1, j_);
276
277 interaction_matrices[j_ * order][0][VX] = -(delta)*A * mu_0j;
278 interaction_matrices[j_ * order][0][VY] = -j * A * mu_1jm1 - (j + delta) * B * mu_0j;
279
280 interaction_matrices[j_ * order][0][WX] =
281 (j + 3 * delta) * mu_0jp1 + (2 * j + 3 * delta) * Yg * mu_0j - j * epsilon * n02 * mu_0jm1;
282 interaction_matrices[j_ * order][0][WY] =
283 -(j + 3 * delta) * mu_1j - (j + 3 * delta) * Xg * mu_0j - j * Yg * mu_1jm1 + j * epsilon * n11 * mu_0jm1;
284 interaction_matrices[j_ * order][0][VZ] = -A * interaction_matrices[j_ * order][0][WY] +
285 B * interaction_matrices[j_ * order][0][WX] + (j + 2 * delta) * C * mu_0j;
286 interaction_matrices[j_ * order][0][WZ] = -j * mu_1jm1;
287 }
288
289 for (int j = 1; j < (int)order - 1; j++) {
290 unsigned int j_ = (unsigned int)j;
291 unsigned int jm1_ = j_ - 1;
292 unsigned int jp1_ = j_ + 1;
293 for (int i = 1; i < (int)order - j - 1; i++) {
294 unsigned int i_ = (unsigned int)i;
295 unsigned int im1_ = i_ - 1;
296 unsigned int ip1_ = i_ + 1;
297
298 double mu_ijm1 = momentCentered.get(i_, jm1_);
299 double mu_ij = momentCentered.get(i_, j_);
300 double mu_ijp1 = momentCentered.get(i_, jp1_);
301 double mu_im1j = momentCentered.get(im1_, j_);
302 double mu_im1jp1 = momentCentered.get(im1_, jp1_);
303 double mu_ip1jm1 = momentCentered.get(ip1_, jm1_);
304 double mu_ip1j = momentCentered.get(ip1_, j_);
305
306 interaction_matrices[j_ * order + i_][0][VX] = -(i + delta) * A * mu_ij - i * B * mu_im1jp1;
307 interaction_matrices[j_ * order + i_][0][VY] = -j * A * mu_ip1jm1 - (j + delta) * B * mu_ij;
308
309 interaction_matrices[j_ * order + i_][0][WX] = (i + j + 3 * delta) * mu_ijp1 +
310 (i + 2 * j + 3 * delta) * Yg * mu_ij + i * Xg * mu_im1jp1 -
311 i * epsilon * n11 * mu_im1j - j * epsilon * n02 * mu_ijm1;
312 interaction_matrices[j_ * order + i_][0][WY] = -(i + j + 3 * delta) * mu_ip1j -
313 (2 * i + j + 3 * delta) * Xg * mu_ij - j * Yg * mu_ip1jm1 +
314 i * epsilon * n20 * mu_im1j + j * epsilon * n11 * mu_ijm1;
315 interaction_matrices[j_ * order + i_][0][VZ] = -A * interaction_matrices[j_ * order + i_][0][WY] +
316 B * interaction_matrices[j_ * order + i_][0][WX] +
317 (i + j + 2 * delta) * C * mu_ij;
318 interaction_matrices[j_ * order + i_][0][WZ] = i * mu_im1jp1 - j * mu_ip1jm1;
319 }
320 }
321#endif // #ifdef VISP_MOMENTS_COMBINE_MATRICES
322}
323
328std::ostream &operator<<(std::ostream &os, const vpFeatureMomentCentered &mu)
329{
330 vpTRACE(" << Ls - CENTRED MOMENTS >>");
331 unsigned int order_m_1 = (unsigned int)(mu.order - 1);
332 for (unsigned int i = 0; i < order_m_1; i++) {
333 for (unsigned int j = 0; j < order_m_1 - i; j++) {
334 os << "L_mu[" << i << "," << j << "] = ";
335 mu.interaction(i, j).matlabPrint(os);
336 }
337 }
338 return os;
339}
error that can be emitted by ViSP classes.
Definition vpException.h:59
@ badValue
Used to indicate that a value is not in the allowed range.
Definition vpException.h:85
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition vpException.h:86
Functionality computation for basic moment feature. Computes the interaction matrix associated with v...
vpMatrix interaction(unsigned int select_one, unsigned int select_two) const
friend VISP_EXPORT std::ostream & operator<<(std::ostream &os, const vpFeatureMomentCentered &v)
vpFeatureMomentCentered(vpMomentDatabase &moments, double A, double B, double C, vpFeatureMomentDatabase *featureMoments=NULL)
vpMatrix interaction(unsigned int select_one, unsigned int select_two) const
vpMatrix compute_Lmu_pq(const unsigned int &p, const unsigned int &q, const double &xg, const double &yg, const vpMatrix &L_xg, const vpMatrix &L_yg, const vpMomentBasic &m, const vpFeatureMomentBasic &feature_moment_m) const
This class allows to register all feature moments (implemented in vpFeatureMoment....
Functionality computation for gravity center moment feature. Computes the interaction matrix associat...
std::vector< vpMatrix > interaction_matrices
vpFeatureMomentDatabase * featureMomentsDataBase
vpFeatureMoment(vpMomentDatabase &data_base, double A_=0.0, double B_=0.0, double C_=0.0, vpFeatureMomentDatabase *featureMoments=NULL, unsigned int nbmatrices=1)
vpMomentDatabase & moments
vpMatrix interaction(unsigned int select=FEATURE_ALL)
const vpMoment * moment
static long double comb(unsigned int n, unsigned int p)
Definition vpMath.h:309
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:152
std::ostream & matlabPrint(std::ostream &os) const
This class defines the 2D basic moment . This class is a wrapper for vpMomentObject wich allows to us...
const std::vector< double > & get() const
This class defines the double-indexed centered moment descriptor .
double get(unsigned int i, unsigned int j) const
This class allows to register all vpMoments so they can access each other according to their dependen...
Class describing 2D gravity center moment.
const std::vector< double > & get() const
Class for generic objects.
unsigned int getOrder() const
const std::vector< double > & get() const
vpObjectType getType() const
#define vpTRACE
Definition vpDebug.h:411