Visual Servoing Platform  version 3.6.1 under development (2024-12-12)
simulateFourPoints2DCartesianCamVelocity.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  * Simulation of a visual servoing with visualization.
33  *
34 *****************************************************************************/
35 
48 #include <visp3/core/vpConfig.h>
49 #include <visp3/core/vpDebug.h>
50 
51 #ifdef VISP_HAVE_COIN3D_AND_GUI
52 
53 #include <visp3/ar/vpSimulator.h>
54 #include <visp3/core/vpCameraParameters.h>
55 #include <visp3/core/vpHomogeneousMatrix.h>
56 #include <visp3/core/vpImage.h>
57 #include <visp3/core/vpIoTools.h>
58 #include <visp3/core/vpMath.h>
59 #include <visp3/core/vpTime.h>
60 #include <visp3/io/vpParseArgv.h>
61 #include <visp3/robot/vpSimulatorCamera.h>
62 #include <visp3/visual_features/vpFeatureBuilder.h>
63 #include <visp3/visual_features/vpFeaturePoint.h>
64 #include <visp3/vs/vpServo.h>
65 
66 #define GETOPTARGS "di:h"
67 #define SAVE 0
68 
69 #ifdef ENABLE_VISP_NAMESPACE
70 using namespace VISP_NAMESPACE_NAME;
71 #endif
72 
82 void usage(const char *name, const char *badparam, std::string ipath)
83 {
84  fprintf(stdout, "\n\
85 Simulation Servo 4points.\n\
86  \n\
87 SYNOPSIS\n\
88  %s [-i <input image path>] [-d] [-h]\n",
89  name);
90 
91  fprintf(stdout, "\n\
92 OPTIONS: Default\n\
93  -i <input image path> %s\n\
94  Set image input path.\n\
95  From this path read \"iv/4points.iv\"\n\
96  cad model.\n\
97  Setting the VISP_INPUT_IMAGE_PATH environment\n\
98  variable produces the same behaviour than using\n\
99  this option.\n\
100  \n\
101  -d \n\
102  Disable the image display. This can be useful \n\
103  for automatic tests using crontab under Unix or \n\
104  using the task manager under Windows.\n\
105  \n\
106  -h\n\
107  Print the help.\n\n",
108  ipath.c_str());
109 
110  if (badparam)
111  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
112 }
113 
129 bool getOptions(int argc, const char **argv, std::string &ipath, bool &display)
130 {
131  const char *optarg;
132  int c;
133  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg)) > 1) {
134 
135  switch (c) {
136  case 'i':
137  ipath = optarg;
138  break;
139  case 'd':
140  display = false;
141  break;
142  case 'h':
143  usage(argv[0], nullptr, ipath);
144  return false;
145  break;
146 
147  default:
148  usage(argv[0], optarg, ipath);
149  return false;
150  break;
151  }
152  }
153 
154  if ((c == 1) || (c == -1)) {
155  // standalone param or error
156  usage(argv[0], nullptr, ipath);
157  std::cerr << "ERROR: " << std::endl;
158  std::cerr << " Bad argument " << optarg << std::endl << std::endl;
159  return false;
160  }
161 
162  return true;
163 }
164 
165 static void *mainLoop(void *_simu)
166 {
167  vpSimulator *simu = static_cast<vpSimulator *>(_simu);
168  simu->initMainApplication();
169 
170  vpServo task;
171  vpSimulatorCamera robot;
172 
173  float sampling_time = 0.040f; // Sampling period in second
174  robot.setSamplingTime(sampling_time);
175 
176  std::cout << std::endl;
177  std::cout << "-------------------------------------------------------" << std::endl;
178  std::cout << " Test program for vpServo " << std::endl;
179  std::cout << " Eye-in-hand task control, articular velocities are computed" << std::endl;
180  std::cout << " Simulation " << std::endl;
181  std::cout << " task : servo 4 points " << std::endl;
182  std::cout << "-------------------------------------------------------" << std::endl;
183  std::cout << std::endl;
184 
185  // Sets the initial camera location
186  vpPoseVector vcMo;
187 
188  vcMo[0] = 0.3;
189  vcMo[1] = 0.2;
190  vcMo[2] = 3;
191  vcMo[3] = 0;
192  vcMo[4] = vpMath::rad(0);
193  vcMo[5] = vpMath::rad(40);
194 
195  vpHomogeneousMatrix cMo(vcMo);
196  vpHomogeneousMatrix wMo; // Set to identity
197  vpHomogeneousMatrix wMc; // Camera location in world frame
198  wMc = wMo * cMo.inverse();
199  robot.setPosition(wMc);
200  simu->setCameraPosition(cMo);
201 
202  simu->getCameraPosition(cMo);
203  wMc = wMo * cMo.inverse();
204  robot.setPosition(wMc);
205  robot.setMaxTranslationVelocity(4.);
206 
207  vpCameraParameters cam;
208 
209  // Sets the point coordinates in the world frame
210  vpPoint point[4];
211  point[0].setWorldCoordinates(-0.1, -0.1, 0);
212  point[1].setWorldCoordinates(0.1, -0.1, 0);
213  point[2].setWorldCoordinates(0.1, 0.1, 0);
214  point[3].setWorldCoordinates(-0.1, 0.1, 0);
215 
216  // Project : computes the point coordinates in the camera frame and its 2D
217  // coordinates
218  for (int i = 0; i < 4; i++)
219  point[i].track(cMo);
220 
221  // Sets the desired position of the point
222  vpFeaturePoint p[4];
223  for (int i = 0; i < 4; i++)
224  vpFeatureBuilder::create(p[i], point[i]); // retrieve x,y and Z of the vpPoint structure
225 
226  // Sets the desired position of the point
227  vpFeaturePoint pd[4];
228 
229  pd[0].buildFrom(-0.1, -0.1, 1);
230  pd[1].buildFrom(0.1, -0.1, 1);
231  pd[2].buildFrom(0.1, 0.1, 1);
232  pd[3].buildFrom(-0.1, 0.1, 1);
233 
234  // Define the task
235  // We want an eye-in-hand control law
236  // Articular velocity are computed
239 
240  // Set the position of the end-effector frame in the camera frame as identity
242  vpVelocityTwistMatrix cVe(cMe);
243  task.set_cVe(cVe);
244 
245  // Set the Jacobian (expressed in the end-effector frame)
246  vpMatrix eJe;
247  robot.get_eJe(eJe);
248  task.set_eJe(eJe);
249 
250  // We want to see a point on a point
251  for (int i = 0; i < 4; i++)
252  task.addFeature(p[i], pd[i]);
253 
254  // Set the gain
255  task.setLambda(1.0);
256 
257  std::cout << "Display task information" << std::endl;
258  task.print();
259 
260  vpTime::wait(1000); // Sleep 1s to ensure that all the thread are initialized
261 
262  unsigned int iter = 0;
263  // visual servo loop
264  while (iter++ < 100) {
265  double t = vpTime::measureTimeMs();
266 
267  vpColVector v;
268 
269  robot.get_eJe(eJe);
270  task.set_eJe(eJe);
271 
272  wMc = robot.getPosition();
273  cMo = wMc.inverse() * wMo;
274  for (int i = 0; i < 4; i++) {
275  point[i].track(cMo);
276  vpFeatureBuilder::create(p[i], point[i]);
277  }
278 
279  v = task.computeControlLaw();
281 
282  simu->setCameraPosition(cMo);
283 
284  if (SAVE == 1) {
285  char name[FILENAME_MAX];
286  snprintf(name, FILENAME_MAX, "/tmp/image.%04u.external.png", iter);
287  std::cout << name << std::endl;
288  simu->write(name);
289  snprintf(name, FILENAME_MAX, "/tmp/image.%04u.internal.png", iter);
290  simu->write(name);
291  }
292 
293  vpTime::wait(t, sampling_time * 1000); // Wait 40 ms
294  }
295  std::cout << "\nDisplay task information" << std::endl;
296  task.print();
297 
298  simu->closeMainApplication();
299 
300  void *a = nullptr;
301  return a;
302 }
303 
304 int main(int argc, const char **argv)
305 {
306  try {
307  std::string env_ipath;
308  std::string opt_ipath;
309  std::string ipath;
310  std::string filename;
311  bool opt_display = true;
312 
313  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
314  // environment variable value
315  env_ipath = vpIoTools::getViSPImagesDataPath();
316 
317  // Set the default input path
318  if (!env_ipath.empty())
319  ipath = env_ipath;
320 
321  // Read the command line options
322  if (getOptions(argc, argv, opt_ipath, opt_display) == false) {
323  return EXIT_FAILURE;
324  }
325 
326  // Get the option values
327  if (!opt_ipath.empty())
328  ipath = opt_ipath;
329 
330  // Compare ipath and env_ipath. If they differ, we take into account
331  // the input path coming from the command line option
332  if (!opt_ipath.empty() && !env_ipath.empty()) {
333  if (ipath != env_ipath) {
334  std::cout << std::endl << "WARNING: " << std::endl;
335  std::cout << " Since -i <visp image path=" << ipath << "> "
336  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
337  << " we skip the environment variable." << std::endl;
338  }
339  }
340 
341  // Test if an input path is set
342  if (opt_ipath.empty() && env_ipath.empty()) {
343  usage(argv[0], nullptr, ipath);
344  std::cerr << std::endl << "ERROR:" << std::endl;
345  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
346  << " environment variable to specify the location of the " << std::endl
347  << " image path where test images are located." << std::endl
348  << std::endl;
349  return EXIT_FAILURE;
350  }
351 
352  vpCameraParameters cam;
354  fMo[2][3] = 0;
355 
356  if (opt_display) {
357  vpSimulator simu;
358  simu.initInternalViewer(300, 300);
359  simu.initExternalViewer(300, 300);
360 
361  vpTime::wait(1000);
362  simu.setZoomFactor(1.0f);
363 
364  // Load the cad model
365  filename = vpIoTools::createFilePath(ipath, "iv/4points.iv");
366  simu.load(filename.c_str());
367 
368  simu.setInternalCameraParameters(cam);
369  simu.setExternalCameraParameters(cam);
370  simu.initApplication(&mainLoop);
371 
372  simu.mainLoop();
373  }
374  return EXIT_SUCCESS;
375  }
376  catch (const vpException &e) {
377  std::cout << "Catch an exception: " << e << std::endl;
378  return EXIT_FAILURE;
379  }
380 }
381 
382 #else
383 int main()
384 {
385  std::cout << "You do not have Coin3D and SoQT or SoWin or SoXt functionalities enabled..." << std::endl;
386  std::cout << "Tip:" << std::endl;
387  std::cout
388  << "- Install Coin3D and SoQT or SoWin or SoXt, configure ViSP again using cmake and build again this example"
389  << std::endl;
390  return EXIT_SUCCESS;
391 }
392 #endif
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
error that can be emitted by ViSP classes.
Definition: vpException.h:60
static void create(vpFeaturePoint &s, const vpCameraParameters &cam, const vpImagePoint &t)
Class that defines a 2D point visual feature which is composed by two parameters that are the cartes...
vpFeaturePoint & buildFrom(const double &x, const double &y, const double &Z)
void track(const vpHomogeneousMatrix &cMo)
Implementation of an homogeneous matrix and operations on such kind of matrices.
vpHomogeneousMatrix inverse() const
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1053
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1427
static double rad(double deg)
Definition: vpMath.h:129
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:70
Class that defines a 3D point in the object frame and allows forward projection of a 3D point in the ...
Definition: vpPoint.h:79
void setWorldCoordinates(double oX, double oY, double oZ)
Definition: vpPoint.cpp:113
Implementation of a pose vector and operations on poses.
Definition: vpPoseVector.h:203
void get_eJe(vpMatrix &eJe) VP_OVERRIDE
void setVelocity(const vpRobot::vpControlFrameType frame, const vpColVector &vel) VP_OVERRIDE
@ CAMERA_FRAME
Definition: vpRobot.h:84
void setMaxTranslationVelocity(double maxVt)
Definition: vpRobot.cpp:240
void setInteractionMatrixType(const vpServoIteractionMatrixType &interactionMatrixType, const vpServoInversionType &interactionMatrixInversion=PSEUDO_INVERSE)
Definition: vpServo.cpp:380
@ EYEINHAND_L_cVe_eJe
Definition: vpServo.h:168
void addFeature(vpBasicFeature &s_cur, vpBasicFeature &s_star, unsigned int select=vpBasicFeature::FEATURE_ALL)
Definition: vpServo.cpp:331
void set_cVe(const vpVelocityTwistMatrix &cVe_)
Definition: vpServo.h:1038
void print(const vpServo::vpServoPrintType display_level=ALL, std::ostream &os=std::cout)
Definition: vpServo.cpp:171
void setLambda(double c)
Definition: vpServo.h:986
void set_eJe(const vpMatrix &eJe_)
Definition: vpServo.h:1101
void setServo(const vpServoType &servo_type)
Definition: vpServo.cpp:134
vpColVector computeControlLaw()
Definition: vpServo.cpp:705
@ CURRENT
Definition: vpServo.h:202
Class that defines the simplest robot: a free flying camera.
Implementation of a simulator based on Coin3d (www.coin3d.org).
Definition: vpSimulator.h:95
void load(const char *file_name)
load an iv file
void setInternalCameraParameters(vpCameraParameters &cam)
set internal camera parameters
virtual void mainLoop()
activate the mainloop
void setExternalCameraParameters(vpCameraParameters &cam)
set external camera parameters
void initMainApplication()
perform some initialization in the main program thread
void initApplication(void *(*start_routine)(void *))
begin the main program
void getCameraPosition(vpHomogeneousMatrix &_cMf)
get the camera position (from an homogeneous matrix)
Definition: vpSimulator.h:244
void setZoomFactor(float zoom)
set the size of the camera/frame
void setCameraPosition(vpHomogeneousMatrix &cMf)
set the camera position (from an homogeneous matrix)
void initExternalViewer(unsigned int nlig, unsigned int ncol)
initialize the external view
virtual void initInternalViewer(unsigned int nlig, unsigned int ncol)
initialize the camera view
void closeMainApplication()
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeMs()