Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpFeatureMomentCentered.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Implementation for all supported moment features.
32 */
33
34#include <visp3/core/vpConfig.h>
35
36#include <vector>
37
38#include <visp3/core/vpDebug.h>
39#include <visp3/core/vpMomentCentered.h>
40#include <visp3/core/vpMomentGravityCenter.h>
41#include <visp3/core/vpMomentObject.h>
42#include <visp3/visual_features/vpFeatureMomentBasic.h>
43#include <visp3/visual_features/vpFeatureMomentCentered.h>
44#include <visp3/visual_features/vpFeatureMomentDatabase.h>
45#include <visp3/visual_features/vpFeatureMomentGravityCenter.h>
46
56 vpFeatureMomentCentered::vpFeatureMomentCentered(vpMomentDatabase &moments_, double A_, double B_, double C_,
57 vpFeatureMomentDatabase *featureMoments)
58 : vpFeatureMoment(moments_, A_, B_, C_, featureMoments), order(0)
59{ }
60
67vpMatrix vpFeatureMomentCentered::interaction(unsigned int select_one, unsigned int select_two) const
68{
69 if (select_one + select_two > moment->getObject().getOrder())
70 throw vpException(vpException::badValue, "The requested value has not "
71 "been computed, you should "
72 "specify a higher order.");
73 return interaction_matrices[select_two * order + select_one];
74}
75
81vpMatrix vpFeatureMomentCentered::compute_Lmu_pq(const unsigned int &p, const unsigned int &q, const double &xg,
82 const double &yg, const vpMatrix &L_xg, const vpMatrix &L_yg,
83 const vpMomentBasic &m,
84 const vpFeatureMomentBasic &feature_moment_m) const
85{
86 // term1, term2 and Lterm3 (matrix) will be repeatedly computed inside the
87 // innermost loop
88 double term1 = 0.0;
89 double term2 = 0.0;
90 vpMatrix Lterm3(1, 6);
91
92 double qcombl = 0.0;
93 double pcombkqcombl = 0.0;
94
95 double mkl = 0.0;
96 vpMatrix L_mkl;
97
98 int qml = 0; // q-l
99 double minus1pow = 0.; // (-1)^(p+q-k-l)
100 double pintom = 0.;
101
102 for (unsigned int k = 0; k <= p; ++k) {
103 int pmk = static_cast<int>(p) - static_cast<int>(k);
104 double pcombk = static_cast<double>(vpMath::comb(p, k));
105 for (unsigned int l = 0; l <= q; ++l) {
106 qml = static_cast<int>(q) - static_cast<int>(l);
107 qcombl = static_cast<double>(vpMath::comb(q, l));
108 minus1pow = pow(-1.0, static_cast<double>(pmk + qml));
109 pcombkqcombl = pcombk * qcombl;
110 mkl = m.get(k, l);
111 pintom = pcombkqcombl * mkl;
112 L_mkl = feature_moment_m.interaction(k, l);
113 if (pmk > 0)
114 term1 += pintom * pmk * pow(xg, pmk - 1) * pow(yg, qml) * minus1pow;
115 if (qml > 0)
116 term2 += pintom * qml * pow(xg, pmk) * pow(yg, qml - 1) * minus1pow;
117 Lterm3 += pcombkqcombl * pow(xg, pmk) * pow(yg, qml) * L_mkl * minus1pow;
118 }
119 }
120
121 // L_xg and L_yg stay constant with respect to the above loops. Lterm3 is
122 // summed over
123 vpMatrix L_mupq = L_xg * term1 + L_yg * term2 + Lterm3;
124 return L_mupq;
125}
126
140{
141#ifdef VISP_MOMENTS_COMBINE_MATRICES
142 const vpMomentObject &momentObject = moment->getObject();
143 order = momentObject.getOrder() + 1;
145 for (std::vector<vpMatrix>::iterator i = interaction_matrices.begin(); i != interaction_matrices.end(); ++i)
146 i->resize(1, 6);
147
148 bool found_moment_gravity;
149 const vpMomentGravityCenter &momentGravity =
150 static_cast<const vpMomentGravityCenter &>(moments.get("vpMomentGravityCenter", found_moment_gravity));
151 if (!found_moment_gravity)
152 throw vpException(vpException::notInitialized, "vpMomentGravityCenter not found");
153 double xg = momentGravity.get()[0];
154 double yg = momentGravity.get()[1];
155
156 bool found_feature_gravity_center;
157 vpFeatureMomentGravityCenter &featureMomentGravityCenter = (static_cast<vpFeatureMomentGravityCenter &>(
158 featureMomentsDataBase->get("vpFeatureMomentGravityCenter", found_feature_gravity_center)));
159 if (!found_feature_gravity_center)
160 throw vpException(vpException::notInitialized, "vpFeatureMomentGravityCenter not found");
161 vpMatrix Lxg = featureMomentGravityCenter.interaction(1 << 0);
162 vpMatrix Lyg = featureMomentGravityCenter.interaction(1 << 1);
163
164 bool found_moment_basic;
165 const vpMomentBasic &momentbasic =
166 static_cast<const vpMomentBasic &>(moments.get("vpMomentBasic", found_moment_basic));
167 if (!found_moment_basic)
168 throw vpException(vpException::notInitialized, "vpMomentBasic not found");
169
170 bool found_featuremoment_basic;
171 vpFeatureMomentBasic &featureMomentBasic = (static_cast<vpFeatureMomentBasic &>(
172 featureMomentsDataBase->get("vpFeatureMomentBasic", found_featuremoment_basic)));
173 if (!found_featuremoment_basic)
174 throw vpException(vpException::notInitialized, "vpFeatureMomentBasic not found");
175
176 // Calls the main compute_Lmu_pq function for moments upto order-1
177 for (int i = 0; i < static_cast<int>(order) - 1; i++) {
178 for (int j = 0; j < static_cast<int>(order) - 1 - i; j++) {
179 interaction_matrices[static_cast<unsigned int>(j) * order + static_cast<unsigned int>(i)] =
180 compute_Lmu_pq(i, j, xg, yg, Lxg, Lyg, momentbasic, featureMomentBasic);
181 }
182 }
183#else // #ifdef VISP_MOMENTS_COMBINE_MATRICES
184 bool found_moment_centered;
185 bool found_moment_gravity;
186
187 const vpMomentCentered &momentCentered =
188 (static_cast<const vpMomentCentered &>(moments.get("vpMomentCentered", found_moment_centered)));
189 const vpMomentGravityCenter &momentGravity =
190 static_cast<const vpMomentGravityCenter &>(moments.get("vpMomentGravityCenter", found_moment_gravity));
191
192 if (!found_moment_centered)
193 throw vpException(vpException::notInitialized, "vpMomentCentered not found");
194 if (!found_moment_gravity)
195 throw vpException(vpException::notInitialized, "vpMomentGravityCenter not found");
196
197 int delta;
198 int epsilon;
199 const vpMomentObject &momentObject = moment->getObject();
200 order = momentObject.getOrder() + 1;
202 for (std::vector<vpMatrix>::iterator i = interaction_matrices.begin(); i != interaction_matrices.end(); ++i)
203 i->resize(1, 6);
204 if (momentObject.getType() == vpMomentObject::DISCRETE) {
205 delta = 0;
206 epsilon = 1;
207 }
208 else {
209 delta = 1;
210 epsilon = 4;
211 }
212 double n11 = momentCentered.get(1, 1) / momentObject.get(0, 0);
213 double n20 = momentCentered.get(2, 0) / momentObject.get(0, 0);
214 double n02 = momentCentered.get(0, 2) / momentObject.get(0, 0);
215 double Xg = momentGravity.getXg();
216 double Yg = momentGravity.getYg();
217 double mu00 = momentCentered.get(0, 0);
218
219 unsigned int VX = 0;
220 unsigned int VY = 1;
221 unsigned int VZ = 2;
222 unsigned int WX = 3;
223 unsigned int WY = 4;
224 unsigned int WZ = 5;
225
226 interaction_matrices[0][0][VX] = -(delta)*A * mu00;
227 interaction_matrices[0][0][VY] = -(delta)*B * mu00;
228
229 // Since mu10=0 and mu01=0
230 // interaction_matrices[0][0][WX] = (3*delta)*MU(0,1)+(3*delta)*Yg*mu00;
231 // interaction_matrices[0][0][WY] = -(3*delta)*MU(1,0)-(3*delta)*Xg*mu00;
232 // we get the simplification:
233 interaction_matrices[0][0][WX] = (3 * delta) * Yg * mu00;
234 interaction_matrices[0][0][WY] = -(3 * delta) * Xg * mu00;
235 interaction_matrices[0][0][VZ] =
236 -A * interaction_matrices[0][0][WY] + B * interaction_matrices[0][0][WX] + (2 * delta) * C * mu00;
237 interaction_matrices[0][0][WZ] = 0.;
238
239 for (int i = 1; i < static_cast<int>(order) - 1; i++) {
240 unsigned int i_ = static_cast<unsigned int>(i);
241 unsigned int im1_ = i_ - 1;
242 unsigned int ip1_ = i_ + 1;
243
244 double mu_im10 = momentCentered.get(im1_, 0);
245 double mu_ip10 = momentCentered.get(ip1_, 0);
246 double mu_im11 = momentCentered.get(im1_, 1);
247 double mu_i0 = momentCentered.get(i_, 0);
248 double mu_i1 = momentCentered.get(i_, 1);
249
250 interaction_matrices[i_][0][VX] = -(i + delta) * A * mu_i0 - (i * B * mu_im11);
251 interaction_matrices[i_][0][VY] = -(delta)*B * mu_i0;
252
253 interaction_matrices[i_][0][WX] =
254 (i + 3 * delta) * mu_i1 + (i + 3 * delta) * Yg * mu_i0 + i * Xg * mu_im11 - i * epsilon * n11 * mu_im10;
255 interaction_matrices[i_][0][WY] =
256 -(i + 3 * delta) * mu_ip10 - (2 * i + 3 * delta) * Xg * mu_i0 + i * epsilon * n20 * mu_im10;
257 interaction_matrices[i_][0][VZ] =
258 -A * interaction_matrices[i_][0][WY] + B * interaction_matrices[i_][0][WX] + (i + 2 * delta) * C * mu_i0;
259 interaction_matrices[i_][0][WZ] = i * mu_im11;
260 }
261
262 for (int j = 1; j < static_cast<int>(order) - 1; j++) {
263 unsigned int j_ = static_cast<unsigned int>(j);
264 unsigned int jm1_ = j_ - 1;
265 unsigned int jp1_ = j_ + 1;
266
267 double mu_0jm1 = momentCentered.get(0, jm1_);
268 double mu_0jp1 = momentCentered.get(0, jp1_);
269 double mu_1jm1 = momentCentered.get(1, jm1_);
270 double mu_0j = momentCentered.get(0, j_);
271 double mu_1j = momentCentered.get(1, j_);
272
273 interaction_matrices[j_ * order][0][VX] = -(delta)*A * mu_0j;
274 interaction_matrices[j_ * order][0][VY] = -j * A * mu_1jm1 - (j + delta) * B * mu_0j;
275
276 interaction_matrices[j_ * order][0][WX] =
277 (j + 3 * delta) * mu_0jp1 + (2 * j + 3 * delta) * Yg * mu_0j - j * epsilon * n02 * mu_0jm1;
278 interaction_matrices[j_ * order][0][WY] =
279 -(j + 3 * delta) * mu_1j - (j + 3 * delta) * Xg * mu_0j - j * Yg * mu_1jm1 + j * epsilon * n11 * mu_0jm1;
280 interaction_matrices[j_ * order][0][VZ] = -A * interaction_matrices[j_ * order][0][WY] +
281 B * interaction_matrices[j_ * order][0][WX] + (j + 2 * delta) * C * mu_0j;
282 interaction_matrices[j_ * order][0][WZ] = -j * mu_1jm1;
283 }
284
285 for (int j = 1; j < static_cast<int>(order) - 1; j++) {
286 unsigned int j_ = static_cast<unsigned int>(j);
287 unsigned int jm1_ = j_ - 1;
288 unsigned int jp1_ = j_ + 1;
289 for (int i = 1; i < static_cast<int>(order) - j - 1; i++) {
290 unsigned int i_ = static_cast<unsigned int>(i);
291 unsigned int im1_ = i_ - 1;
292 unsigned int ip1_ = i_ + 1;
293
294 double mu_ijm1 = momentCentered.get(i_, jm1_);
295 double mu_ij = momentCentered.get(i_, j_);
296 double mu_ijp1 = momentCentered.get(i_, jp1_);
297 double mu_im1j = momentCentered.get(im1_, j_);
298 double mu_im1jp1 = momentCentered.get(im1_, jp1_);
299 double mu_ip1jm1 = momentCentered.get(ip1_, jm1_);
300 double mu_ip1j = momentCentered.get(ip1_, j_);
301
302 interaction_matrices[j_ * order + i_][0][VX] = -(i + delta) * A * mu_ij - i * B * mu_im1jp1;
303 interaction_matrices[j_ * order + i_][0][VY] = -j * A * mu_ip1jm1 - (j + delta) * B * mu_ij;
304
305 interaction_matrices[j_ * order + i_][0][WX] = (i + j + 3 * delta) * mu_ijp1 +
306 (i + 2 * j + 3 * delta) * Yg * mu_ij + i * Xg * mu_im1jp1 -
307 i * epsilon * n11 * mu_im1j - j * epsilon * n02 * mu_ijm1;
308 interaction_matrices[j_ * order + i_][0][WY] = -(i + j + 3 * delta) * mu_ip1j -
309 (2 * i + j + 3 * delta) * Xg * mu_ij - j * Yg * mu_ip1jm1 +
310 i * epsilon * n20 * mu_im1j + j * epsilon * n11 * mu_ijm1;
311 interaction_matrices[j_ * order + i_][0][VZ] = -A * interaction_matrices[j_ * order + i_][0][WY] +
312 B * interaction_matrices[j_ * order + i_][0][WX] +
313 (i + j + 2 * delta) * C * mu_ij;
314 interaction_matrices[j_ * order + i_][0][WZ] = i * mu_im1jp1 - j * mu_ip1jm1;
315 }
316 }
317#endif // #ifdef VISP_MOMENTS_COMBINE_MATRICES
318}
319
324std::ostream &operator<<(std::ostream &os, const vpFeatureMomentCentered &mu)
325{
326 vpTRACE(" << Ls - CENTRED MOMENTS >>");
327 unsigned int order_m_1 = static_cast<unsigned int>(mu.order - 1);
328 for (unsigned int i = 0; i < order_m_1; i++) {
329 for (unsigned int j = 0; j < order_m_1 - i; j++) {
330 os << "L_mu[" << i << "," << j << "] = ";
331 mu.interaction(i, j).matlabPrint(os);
332 }
333 }
334 return os;
335}
336END_VISP_NAMESPACE
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition vpException.h:73
@ notInitialized
Used to indicate that a parameter is not initialized.
Definition vpException.h:74
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=nullptr)
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
vpMomentDatabase & moments
vpMatrix interaction(unsigned int select=FEATURE_ALL) VP_OVERRIDE
const vpMoment * moment
vpFeatureMoment(const vpFeatureMoment &)=delete
static long double comb(unsigned int n, unsigned int p)
Definition vpMath.h:398
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
std::ostream & matlabPrint(std::ostream &os) const
Definition vpMatrix.cpp:959
This class defines the 2D basic moment . This class is a wrapper for vpMomentObject which allows to u...
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:450