Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpFeatureSegment.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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 * Segment visual feature.
32 */
33
38
39#include <cmath>
40#include <visp3/core/vpDisplay.h>
41#include <visp3/core/vpImagePoint.h>
42#include <visp3/core/vpMath.h>
43#include <visp3/core/vpMeterPixelConversion.h>
44#include <visp3/visual_features/vpBasicFeature.h>
45#include <visp3/visual_features/vpFeatureSegment.h>
46
47// Exception
48#include <visp3/core/vpException.h>
49
50// Debug trace
51#include <visp3/core/vpDebug.h>
52
54
59{
60 // feature dimension
61 dim_s = 4;
62 nbParameters = 6;
63
64 // memory allocation
65 s.resize(dim_s);
66 if (flags == nullptr)
67 flags = new bool[nbParameters];
68 for (unsigned int i = 0; i < nbParameters; i++)
69 flags[i] = false;
70}
71
79 : xc_(0), yc_(0), l_(0), alpha_(0), Z1_(0), Z2_(0), cos_a_(0), sin_a_(0), normalized_(normalized)
80{
81 init();
82}
83
183{
184 vpMatrix L;
185 L.resize(0, 6);
186
188 for (unsigned int i = 0; i < nbParameters; i++) {
189 if (flags[i] == false) {
190 switch (i) {
191 case 0:
192 vpTRACE("Warning !!! The interaction matrix is computed but xc "
193 "was not set yet");
194 break;
195 case 1:
196 vpTRACE("Warning !!! The interaction matrix is computed but Yc "
197 "was not set yet");
198 break;
199 case 2:
200 vpTRACE("Warning !!! The interaction matrix is computed but l was "
201 "not set yet");
202 break;
203 case 3:
204 vpTRACE("Warning !!! The interaction matrix is computed but alpha "
205 "was not set yet");
206 break;
207 case 4:
208 vpTRACE("Warning !!! The interaction matrix is computed but Z1 "
209 "was not set yet");
210 break;
211 case 5:
212 vpTRACE("Warning !!! The interaction matrix is computed but Z2 "
213 "was not set yet");
214 break;
215 default:
216 vpTRACE("Problem during the reading of the variable flags");
217 }
218 }
219 }
220 }
221
222 // This version is a simplification
223 double lambda1 = (Z1_ - Z2_) / (Z1_ * Z2_); // -l * lambda
224 double lambda2 = (Z1_ + Z2_) / (2 * Z1_ * Z2_); // 1/Zm
225
226 if (normalized_) {
227 // here var xc_ contains xc/l, yc_ contains yc/l and l_ contains 1/l
228 double xn = xc_;
229 double yn = yc_;
230 double ln = l_;
231 double lambda = -lambda1 * ln;
232 double Zn_inv = lambda2 * ln;
233 double lc = cos_a_ / ln;
234 double ls = sin_a_ / ln;
235 double xnalpha = xn * cos_a_ + yn * sin_a_;
236 double lnc = cos_a_ * ln;
237 double lns = sin_a_ * ln;
238
239 if (vpFeatureSegment::selectXc() & select) {
240 vpMatrix Lxn(1, 6);
241 Lxn[0][0] = -Zn_inv + lambda * xn * cos_a_;
242 Lxn[0][1] = lambda * xn * sin_a_;
243 Lxn[0][2] = lambda1 * (xn * xnalpha - cos_a_ / 4.);
244 Lxn[0][3] = sin_a_ * cos_a_ / 4 / ln - xn * xnalpha * sin_a_ / ln;
245 Lxn[0][4] = -ln * (1. + lc * lc / 4.) + xn * xnalpha * cos_a_ / ln;
246 Lxn[0][5] = yn;
247 L = vpMatrix::stack(L, Lxn);
248 }
249
250 if (vpFeatureSegment::selectYc() & select) {
251 vpMatrix Lyn(1, 6);
252 Lyn[0][0] = lambda * yn * cos_a_;
253 Lyn[0][1] = -Zn_inv + lambda * yn * sin_a_;
254 Lyn[0][2] = lambda1 * (yn * xnalpha - sin_a_ / 4.);
255 Lyn[0][3] = ln * (1 + ls * ls / 4.) - yn * xnalpha * sin_a_ / ln;
256 Lyn[0][4] = -sin_a_ * cos_a_ / 4 / ln + yn * xnalpha * cos_a_ / ln;
257 Lyn[0][5] = -xn;
258 L = vpMatrix::stack(L, Lyn);
259 }
260
261 if (vpFeatureSegment::selectL() & select) {
262 vpMatrix Lln(1, 6);
263 Lln[0][0] = lambda * lnc;
264 Lln[0][1] = lambda * lns;
265 Lln[0][2] = -(Zn_inv + lambda * xnalpha);
266 Lln[0][3] = -yn - xnalpha * sin_a_;
267 Lln[0][4] = xn + xnalpha * cos_a_;
268 Lln[0][5] = 0;
269 L = vpMatrix::stack(L, Lln);
270 }
271 if (vpFeatureSegment::selectAlpha() & select) {
272 // We recall that xc_ contains xc/l, yc_ contains yc/l and l_ contains
273 // 1/l
274 vpMatrix Lalpha(1, 6);
275 Lalpha[0][0] = -lambda1 * sin_a_ * l_;
276 Lalpha[0][1] = lambda1 * cos_a_ * l_;
277 Lalpha[0][2] = lambda1 * (xc_ * sin_a_ - yc_ * cos_a_);
278 Lalpha[0][3] = (-xc_ * sin_a_ * sin_a_ + yc_ * cos_a_ * sin_a_) / l_;
279 Lalpha[0][4] = (xc_ * cos_a_ * sin_a_ - yc_ * cos_a_ * cos_a_) / l_;
280 Lalpha[0][5] = -1;
281 L = vpMatrix::stack(L, Lalpha);
282 }
283 }
284 else {
285 if (vpFeatureSegment::selectXc() & select) {
286 vpMatrix Lxc(1, 6);
287 Lxc[0][0] = -lambda2;
288 Lxc[0][1] = 0.;
289 Lxc[0][2] = lambda2 * xc_ - lambda1 * l_ * cos_a_ / 4.;
290 Lxc[0][3] = xc_ * yc_ + l_ * l_ * cos_a_ * sin_a_ / 4.;
291 Lxc[0][4] = -(1 + xc_ * xc_ + l_ * l_ * cos_a_ * cos_a_ / 4.);
292 Lxc[0][5] = yc_;
293 L = vpMatrix::stack(L, Lxc);
294 }
295
296 if (vpFeatureSegment::selectYc() & select) {
297 vpMatrix Lyc(1, 6);
298 Lyc[0][0] = 0.;
299 Lyc[0][1] = -lambda2;
300 Lyc[0][2] = lambda2 * yc_ - lambda1 * l_ * sin_a_ / 4.;
301 Lyc[0][3] = 1 + yc_ * yc_ + l_ * l_ * sin_a_ * sin_a_ / 4.;
302 Lyc[0][4] = -xc_ * yc_ - l_ * l_ * cos_a_ * sin_a_ / 4.;
303 Lyc[0][5] = -xc_;
304 L = vpMatrix::stack(L, Lyc);
305 }
306
307 if (vpFeatureSegment::selectL() & select) {
308 vpMatrix Ll(1, 6);
309 Ll[0][0] = lambda1 * cos_a_;
310 Ll[0][1] = lambda1 * sin_a_;
311 Ll[0][2] = lambda2 * l_ - lambda1 * (xc_ * cos_a_ + yc_ * sin_a_);
312 Ll[0][3] = l_ * (xc_ * cos_a_ * sin_a_ + yc_ * (1 + sin_a_ * sin_a_));
313 Ll[0][4] = -l_ * (xc_ * (1 + cos_a_ * cos_a_) + yc_ * cos_a_ * sin_a_);
314 Ll[0][5] = 0;
315 L = vpMatrix::stack(L, Ll);
316 }
317 if (vpFeatureSegment::selectAlpha() & select) {
318 vpMatrix Lalpha(1, 6);
319 Lalpha[0][0] = -lambda1 * sin_a_ / l_;
320 Lalpha[0][1] = lambda1 * cos_a_ / l_;
321 Lalpha[0][2] = lambda1 * (xc_ * sin_a_ - yc_ * cos_a_) / l_;
322 Lalpha[0][3] = -xc_ * sin_a_ * sin_a_ + yc_ * cos_a_ * sin_a_;
323 Lalpha[0][4] = xc_ * cos_a_ * sin_a_ - yc_ * cos_a_ * cos_a_;
324 Lalpha[0][5] = -1;
325 L = vpMatrix::stack(L, Lalpha);
326 }
327 }
328
329 return L;
330}
331
355vpColVector vpFeatureSegment::error(const vpBasicFeature &s_star, unsigned int select)
356{
357 vpColVector e(0);
358
359 if (vpFeatureSegment::selectXc() & select) {
360 vpColVector exc(1);
361 exc[0] = xc_ - s_star[0];
362 e = vpColVector::stack(e, exc);
363 }
364
365 if (vpFeatureSegment::selectYc() & select) {
366 vpColVector eyc(1);
367 eyc[0] = yc_ - s_star[1];
368 e = vpColVector::stack(e, eyc);
369 }
370
371 if (vpFeatureSegment::selectL() & select) {
372 vpColVector eL(1);
373 eL[0] = l_ - s_star[2];
374 e = vpColVector::stack(e, eL);
375 }
376
377 if (vpFeatureSegment::selectAlpha() & select) {
378 vpColVector eAlpha(1);
379 eAlpha[0] = alpha_ - s_star[3];
380 while (eAlpha[0] < -M_PI)
381 eAlpha[0] += 2 * M_PI;
382 while (eAlpha[0] > M_PI)
383 eAlpha[0] -= 2 * M_PI;
384 e = vpColVector::stack(e, eAlpha);
385 }
386 return e;
387}
388
416void vpFeatureSegment::print(unsigned int select) const
417{
418 std::cout << "vpFeatureSegment: (";
419 if (vpFeatureSegment::selectXc() & select) {
420 if (normalized_)
421 std::cout << "xn = ";
422 else
423 std::cout << "xc = ";
424 std::cout << s[0] << "; ";
425 }
426 if (vpFeatureSegment::selectYc() & select) {
427 if (normalized_)
428 std::cout << "yn = ";
429 else
430 std::cout << "yc = ";
431 std::cout << s[1] << "; ";
432 }
433 if (vpFeatureSegment::selectL() & select) {
434 if (normalized_)
435 std::cout << "ln = ";
436 else
437 std::cout << "l = ";
438 std::cout << s[2] << "; ";
439 }
440 if (vpFeatureSegment::selectAlpha() & select) {
441 std::cout << "alpha = " << vpMath::deg(s[3]) << " deg";
442 }
443 std::cout << ")" << std::endl;
444}
445
456{
457 vpFeatureSegment *feature;
458
459 feature = new vpFeatureSegment(*this);
460 return feature;
461}
462
473 unsigned int thickness) const
474{
475 double l, x, y;
476 if (normalized_) {
477 l = 1. / l_;
478 x = xc_ * l;
479 y = yc_ * l;
480 }
481 else {
482 l = l_;
483 x = xc_;
484 y = yc_;
485 }
486
487 double x1 = x - (l / 2.) * cos_a_;
488 double x2 = x + (l / 2.) * cos_a_;
489
490 double y1 = y - (l / 2.) * sin_a_;
491 double y2 = y + (l / 2.) * sin_a_;
492 vpImagePoint ip1, ip2;
493
494 vpMeterPixelConversion::convertPoint(cam, x1, y1, ip1);
495 vpMeterPixelConversion::convertPoint(cam, x2, y2, ip2);
496 vpDisplay::displayLine(I, ip1, ip2, color, thickness);
497 vpDisplay::displayCircle(I, ip1, 5, color, true);
499}
500
511 unsigned int thickness) const
512{
513 double l, x, y;
514 if (normalized_) {
515 l = 1. / l_;
516 x = xc_ * l;
517 y = yc_ * l;
518 }
519 else {
520 l = l_;
521 x = xc_;
522 y = yc_;
523 }
524
525 double x1 = x - (l / 2.) * cos_a_;
526 double x2 = x + (l / 2.) * cos_a_;
527
528 double y1 = y - (l / 2.) * sin_a_;
529 double y2 = y + (l / 2.) * sin_a_;
530 vpImagePoint ip1, ip2;
531
532 vpMeterPixelConversion::convertPoint(cam, x1, y1, ip1);
533 vpMeterPixelConversion::convertPoint(cam, x2, y2, ip2);
534 vpDisplay::displayLine(I, ip1, ip2, color, thickness);
535 vpDisplay::displayCircle(I, ip1, 5, vpColor::cyan, true);
537}
538
555vpFeatureSegment &vpFeatureSegment::buildFrom(const double &x1, const double &y1, const double &Z1, const double &x2, const double &y2, const double &Z2)
556{
557 double l = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
558 double x_c = (x1 + x2) / 2.;
559 double y_c = (y1 + y2) / 2.;
560 double alpha = atan2(y1 - y2, x1 - x2);
561
562 if (normalized_) {
563 setXc(x_c / l);
564 setYc(y_c / l);
565 setL(1 / l);
566 setAlpha(alpha);
567
568 setZ1(Z1);
569 setZ2(Z2);
570 }
571 else {
572 setXc(x_c);
573 setYc(y_c);
574 setL(l);
575 setAlpha(alpha);
576
577 setZ1(Z1);
578 setZ2(Z2);
579 }
580 return *this;
581}
582
606{
607 return FEATURE_LINE[0];
608}
609
633{
634 return FEATURE_LINE[1];
635}
636
660{
661 return FEATURE_LINE[2];
662}
663
686{
687 return FEATURE_LINE[3];
688}
689
690END_VISP_NAMESPACE
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
Definition vpArray2D.h:448
vpColVector s
State of the visual feature.
unsigned int nbParameters
Number of parameters needed to compute the interaction matrix.
unsigned int dim_s
Dimension of the visual feature.
static const unsigned int FEATURE_LINE[32]
vpBasicFeatureDeallocatorType deallocate
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
void stack(double d)
Class to define RGB colors available for display functionalities.
Definition vpColor.h:157
static const vpColor cyan
Definition vpColor.h:207
static const vpColor yellow
Definition vpColor.h:206
static void displayCircle(const vpImage< unsigned char > &I, const vpImageCircle &circle, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
void display(const vpCameraParameters &cam, const vpImage< unsigned char > &I, const vpColor &color=vpColor::green, unsigned int thickness=1) const VP_OVERRIDE
vpColVector error(const vpBasicFeature &s_star, unsigned int select=FEATURE_ALL) VP_OVERRIDE
void init() VP_OVERRIDE
static unsigned int selectAlpha()
void print(unsigned int select=FEATURE_ALL) const VP_OVERRIDE
static unsigned int selectXc()
void setAlpha(double val)
static unsigned int selectYc()
vpFeatureSegment * duplicate() const VP_OVERRIDE
Feature duplication.
void setL(double val)
void setZ2(double val)
VP_EXPLICIT vpFeatureSegment(bool normalized=false)
vpFeatureSegment & buildFrom(const double &x1, const double &y1, const double &Z1, const double &x2, const double &y2, const double &Z2)
void setZ1(double val)
vpMatrix interaction(unsigned int select=FEATURE_ALL) VP_OVERRIDE
void setXc(double val)
static unsigned int selectL()
void setYc(double val)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
Definition vpImage.h:131
static double deg(double rad)
Definition vpMath.h:119
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
void stack(const vpMatrix &A)
static void convertPoint(const vpCameraParameters &cam, const double &x, const double &y, double &u, double &v)
#define vpTRACE
Definition vpDebug.h:450