5 #include <visp3/core/vpImageConvert.h>
6 #include <visp3/core/vpMutex.h>
7 #include <visp3/core/vpThread.h>
8 #include <visp3/core/vpTime.h>
9 #include <visp3/gui/vpDisplayX.h>
10 #include <visp3/gui/vpPlot.h>
11 #include <visp3/robot/vpRobotViper850.h>
12 #include <visp3/sensor/vpV4l2Grabber.h>
14 #include <visp3/ustk_core/usImagePostScan2D.h>
15 #include <visp3/ustk_core/usImagePreScan2D.h>
16 #include <visp3/ustk_core/usPixelMeterConversion.h>
17 #include <visp3/ustk_core/usPostScanToPreScan2DConverter.h>
18 #include <visp3/ustk_core/usPreScanToPostScan2DConverter.h>
20 #include <visp3/ustk_confidence_map/usScanlineConfidence2D.h>
22 #include <visp3/ustk_template_tracking/usDenseTracker2D.h>
24 #if defined(VISP_HAVE_V4L2) && defined(VISP_HAVE_PTHREAD) && defined(VISP_HAVE_VIPER850)
27 typedef enum { capture_waiting, capture_started, capture_stopped } t_CaptureState;
28 t_CaptureState s_capture_state = capture_waiting;
29 vpImage<unsigned char> s_frame;
30 vpMutex s_mutex_capture;
32 typedef enum { ROI_waiting, ROI_started } t_stateInitROI;
33 t_stateInitROI s_ROI_state = ROI_waiting;
34 vpMutex s_mutex_ROI_state;
36 bool s_robotIsRunning;
37 vpMutex s_mutex_control_velocity;
38 vpColVector s_controlVelocity(6, 0.);
43 vpThread::Return captureFunction(vpThread::Args args)
45 vpV4l2Grabber cap = *((vpV4l2Grabber *)args);
46 vpImage<unsigned char> frame_;
47 bool stop_capture_ =
false;
51 vpRect roi(vpImagePoint(55, 70), vpImagePoint(410, 555));
53 while (!stop_capture_) {
55 cap.acquire(frame_, roi);
59 vpMutex::vpScopedLock lock(s_mutex_capture);
60 if (s_capture_state == capture_stopped)
63 s_capture_state = capture_started;
70 vpMutex::vpScopedLock lock(s_mutex_capture);
71 s_capture_state = capture_stopped;
73 std::cout <<
"End of capture thread" << std::endl;
79 vpThread::Return displayFunction(vpThread::Args args)
90 vpRectOriented rectangle;
91 bool rectangleRoiDefined =
false;
92 t_stateInitROI stateROI = ROI_waiting;
101 t_CaptureState capture_state_;
102 bool display_initialized_ =
false;
104 #if defined(VISP_HAVE_X11)
105 vpDisplayX *dpost_scan_ = NULL;
106 vpDisplayX *dpost_scan_confidence_ = NULL;
110 plot.initGraph(0, 1);
111 plot.setTitle(0,
"X target error");
112 plot.setUnitY(0,
"error");
113 plot.setLegend(0, 0,
"time");
115 plot.initGraph(1, 1);
116 plot.setTitle(1,
"confidence barycenter error");
117 plot.setUnitY(1,
"error");
118 plot.setLegend(1, 0,
"time");
127 vpImagePoint ROI_centralPoint;
129 double startTime = vpTime::measureTimeMs();
132 s_mutex_capture.lock();
133 capture_state_ = s_capture_state;
134 s_mutex_capture.unlock();
137 if (capture_state_ == capture_started) {
140 vpMutex::vpScopedLock lock(s_mutex_capture);
144 postScan_.getHeight());
147 postScan_.getHeight());
151 if (rectangleRoiDefined && stateROI == ROI_waiting) {
152 tracker.
init(postScan_, rectangle);
153 s_mutex_ROI_state.lock();
154 s_ROI_state = ROI_started;
155 s_mutex_ROI_state.unlock();
156 stateROI = ROI_started;
160 backConverter_.
convert(postScan_, preScan_, 480);
162 confidenceMapProcessor_.
run(confidencePreScan_, preScan_);
164 converter_.
convert(confidencePreScan_, confidencePostScan_);
167 if (stateROI == ROI_started) {
168 tracker.
update(postScan_);
174 double ttarget = atan2(xtarget, ytarget);
176 double time = (vpTime::measureTimeMs() - startTime) / 1000.0;
178 unsigned int height(confidencePreScan_.getHeight()), width(confidencePreScan_.getWidth());
181 for (
unsigned int i = 0; i < height; ++i)
182 for (
unsigned int j = 0; j < width; ++j)
183 I_sum +=
static_cast<double>(confidencePreScan_[i][j]);
186 for (
unsigned int x = 0; x < height; ++x)
187 for (
unsigned int y = 0; y < width; ++y) {
188 yc += y * confidencePreScan_[x][y];
194 plot.plot(0, 0, time, xtarget);
195 plot.plot(1, 0, time, vpMath::deg(tc));
198 vpMutex::vpScopedLock lock(s_mutex_capture);
200 double lambda_t = 0.8;
201 double lambda_c = 0.8;
203 s_controlVelocity = 0.0;
204 s_controlVelocity[1] = -lambda_t * xtarget + lambda_c * (tc - ttarget) * ytarget;
205 s_controlVelocity[3] = lambda_c * (tc - ttarget);
209 if (!display_initialized_) {
211 #if defined(VISP_HAVE_X11)
212 unsigned int xpos = 10;
213 dpost_scan_ =
new vpDisplayX(postScan_, xpos, 10,
"post-scan");
215 dpost_scan_confidence_ =
new vpDisplayX(confidencePostScan_, xpos, 10,
"post-scan confidence");
216 display_initialized_ =
true;
221 vpDisplay::display(postScan_);
223 if (rectangleRoiDefined) {
224 vpDisplay::displayLine(postScan_,
static_cast<int>(rectangle.getTopLeft().get_i()),
225 static_cast<int>(rectangle.getTopLeft().get_j()),
226 static_cast<int>(rectangle.getBottomLeft().get_i()),
227 static_cast<int>(rectangle.getBottomLeft().get_j()), vpColor::red);
228 vpDisplay::displayLine(postScan_,
static_cast<int>(rectangle.getBottomLeft().get_i()),
229 static_cast<int>(rectangle.getBottomLeft().get_j()),
230 static_cast<int>(rectangle.getBottomRight().get_i()),
231 static_cast<int>(rectangle.getBottomRight().get_j()), vpColor::red);
232 vpDisplay::displayLine(postScan_,
static_cast<int>(rectangle.getBottomRight().get_i()),
233 static_cast<int>(rectangle.getBottomRight().get_j()),
234 static_cast<int>(rectangle.getTopRight().get_i()),
235 static_cast<int>(rectangle.getTopRight().get_j()), vpColor::red);
236 vpDisplay::displayLine(postScan_,
static_cast<int>(rectangle.getTopRight().get_i()),
237 static_cast<int>(rectangle.getTopRight().get_j()),
238 static_cast<int>(rectangle.getTopLeft().get_i()),
239 static_cast<int>(rectangle.getTopLeft().get_j()), vpColor::red);
243 vpDisplay::display(confidencePostScan_);
246 vpDisplay::displayText(postScan_, 10, 10,
"Click to define ROI...", vpColor::red);
247 if (vpDisplay::getClick(postScan_, ROI_centralPoint,
false)) {
249 if (stateROI == ROI_waiting) {
250 rectangle.setCenter(vpImagePoint(ROI_centralPoint.get_v(), ROI_centralPoint.get_u()));
251 rectangle.setSize(80, 50);
252 rectangle.setOrientation(0);
253 rectangleRoiDefined =
true;
258 vpDisplay::displayText(confidencePostScan_, 10, 10,
"Click to exit...", vpColor::red);
259 if (vpDisplay::getClick(confidencePostScan_,
false)) {
260 vpMutex::vpScopedLock lock(s_mutex_capture);
261 s_capture_state = capture_stopped;
265 vpDisplay::flush(postScan_);
266 vpDisplay::flush(confidencePostScan_);
270 }
while (capture_state_ != capture_stopped);
272 #if defined(VISP_HAVE_X11)
274 delete dpost_scan_confidence_;
277 std::cout <<
"End of display thread" << std::endl;
282 vpThread::Return controlFunction(vpThread::Args args)
285 vpRobotViper850 robot;
292 vpHomogeneousMatrix eMs;
297 vpHomogeneousMatrix sMp;
300 vpHomogeneousMatrix sMe;
305 vpVelocityTwistMatrix sVe;
309 vpColVector sHs_star(6);
310 vpColVector pHp_star(6);
312 vpMatrix lambda(6, 6);
314 vpTranslationVector stg;
315 vpColVector sHs_bias(6);
321 vpColVector q_dot(6);
325 for (
int i = 0; i < 3; i++)
326 lambda[i][i] = 0.02 / 6;
328 for (
int i = 3; i < 6; i++)
329 lambda[i][i] = 1. / 2;
341 gHg[2] = -(0.696 + 0.476) * 9.81;
348 vpRotationMatrix sRp;
350 vpTranslationVector stp;
353 vpHomogeneousMatrix eMp = eMs * sMp;
354 vpVelocityTwistMatrix eVp(eMp);
358 vpHomogeneousMatrix fMe;
359 vpHomogeneousMatrix fMs;
360 vpRotationMatrix sRf;
361 robot.getPosition(vpRobot::ARTICULAR_FRAME, q);
362 robot.get_fMe(q, fMe);
365 vpHomogeneousMatrix sMf;
371 vpForceTwistMatrix sFg(sMf);
373 for (
int i = 0; i < 3; i++)
374 for (
int j = 0; j < 3; j++)
375 sFg[i + 3][j] = (stg.skew() * sRf)[i][j];
379 vpForceTwistMatrix sFp(sMp);
382 std::cout <<
"\nBias the force/torque sensor...\n " << std::endl;
383 robot.biasForceTorqueSensor();
386 robot.setRobotState(vpRobot::STATE_VELOCITY_CONTROL);
389 t_CaptureState capture_state_;
390 t_stateInitROI ROI_state = ROI_waiting;
392 std::cout <<
"Waiting ROI definition to start control loop..." << std::endl;
393 while (ROI_state == ROI_waiting) {
394 vpMutex::vpScopedLock lock(s_mutex_ROI_state);
395 ROI_state = s_ROI_state;
398 s_mutex_capture.lock();
399 capture_state_ = s_capture_state;
400 s_mutex_capture.unlock();
401 if (capture_state_ == capture_stopped) {
402 std::cout <<
"end of control thread" << std::endl;
407 std::cout <<
"Starting control loop..." << std::endl;
409 s_mutex_capture.lock();
410 capture_state_ = s_capture_state;
411 s_mutex_capture.unlock();
414 if (capture_state_ == capture_started) {
417 sHs = robot.getForceTorque();
424 robot.getPosition(vpRobot::ARTICULAR_FRAME, q);
425 robot.get_fMe(q, fMe);
435 for (
int i = 0; i < 3; i++)
436 for (
int j = 0; j < 3; j++)
437 sFg[i + 3][j] = (stg.skew() * sRf)[i][j];
440 sHs_bias = sHs - sFg * gHg;
446 vpMutex::vpScopedLock lock(s_mutex_capture);
447 v_p = s_controlVelocity;
456 v_s = lambda * (sFp * pHp_star - (sHs - sFg * gHg - sHs_bias));
464 vpVelocityTwistMatrix eVs;
467 vpColVector v_e = eVs * v_s + eVp * v_p;
469 std::cout << v_e.t() << std::endl;
475 q_dot = eJe.pseudoInverse() * v_e;
478 robot.setVelocity(vpRobot::ARTICULAR_FRAME, q_dot);
483 }
while (capture_state_ != capture_stopped);
485 std::cout <<
"End of control thread" << std::endl;
490 int main(
int argc,
const char *argv[])
492 unsigned int opt_input = 1;
495 for (
int i = 0; i < argc; i++) {
496 if (std::string(argv[i]) ==
"--input")
497 opt_input = (
unsigned int)atoi(argv[i + 1]);
498 else if (std::string(argv[i]) ==
"--help") {
499 std::cout <<
"Usage: " << argv[0] <<
" [--input <number>] [--help]" << std::endl;
507 g.setInput(opt_input);
511 s_robotIsRunning =
false;
512 s_controlVelocity = vpColVector(6, 0);
515 vpThread thread_capture((vpThread::Fn)captureFunction, (vpThread::Args)&g);
516 vpThread thread_display((vpThread::Fn)displayFunction);
517 vpThread thread_control((vpThread::Fn)controlFunction);
520 thread_capture.join();
521 thread_display.join();
522 thread_control.join();
531 #ifndef VISP_HAVE_V4L2
532 std::cout <<
"You should enable V4L2 to make this example working..." << std::endl;
533 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
534 std::cout <<
"You should enable pthread usage and rebuild ViSP..." << std::endl;
536 std::cout <<
"Multi-threading seems not supported on this platform" << std::endl;
538 #ifndef VISP_HAVE_VIPER850
539 std::cout <<
"You need viper 850 robot to run this example" << std::endl;
void update(const vpImage< unsigned char > &I)
Tracking method, to call at every new frame to track.
void init(const vpImage< unsigned char > &I, const vpRectOriented &R)
Initialisation of the tracker : to call to set the region to track (R) in the image (I) before starti...
vpRectOriented getTarget() const
To call after update() at each new frame, to get the position of the ROI in the last acquired frame.
void setHeightResolution(double heightResolution)
void setData(const vpImage< Type > &image)
void setWidthResolution(double widthResolution)
static void convert(const usImagePostScan2D< unsigned char > &image, const double &u, const double &v, double &x, double &y)
Conversion for 2D post-scan images.
void convert(const usImagePostScan2D< unsigned char > &imageToConvert, usImagePreScan2D< unsigned char > &imageConverted, int preScanSamples)
void convert(const usImagePreScan2D< unsigned char > &preScanImage, usImagePostScan2D< unsigned char > &postScanImage, double xResolution=0., double yResolution=0.)
Process a pre-scan image to determine the confidence map.
void run(usImagePreScan2D< unsigned char > &preScanConfidence, const usImagePreScan2D< unsigned char > &preScanImage)
void setFieldOfView(double fieldOfView)
void setTransducerConvexity(const bool isTransducerConvex)
double getFieldOfView() const
void setDepth(double depth)
double getScanLinePitch() const
void setProbeName(std::string probeName)
void setTransducerRadius(const double transducerRadius)
double getTransducerRadius() const
void setScanLineNumber(unsigned int scanLineNumber)