5 #include <visp3/ustk_core/usConfig.h>
7 #include <visp3/core/vpImageConvert.h>
8 #include <visp3/core/vpMutex.h>
9 #include <visp3/core/vpThread.h>
10 #include <visp3/core/vpTime.h>
11 #include <visp3/gui/vpPlot.h>
12 #include <visp3/robot/vpRobotViper850.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_grabber/usNetworkGrabberPreScan2D.h>
22 #include <visp3/ustk_confidence_map/usScanlineConfidence2D.h>
24 #include <visp3/ustk_template_tracking/usDenseTracker2D.h>
26 #if defined(VISP_HAVE_V4L2) && defined(VISP_HAVE_PTHREAD) && defined(VISP_HAVE_VIPER850) && \
27 defined(VISP_HAVE_MODULE_USTK_GRABBER)
29 #include <QApplication>
31 #include <visp3/gui/vpDisplayX.h>
33 typedef enum { capture_waiting, capture_started, capture_stopped } t_CaptureState;
34 t_CaptureState s_capture_state = capture_waiting;
35 vpMutex s_mutex_capture;
37 typedef enum { ROI_waiting, ROI_started } t_stateInitROI;
38 t_stateInitROI s_ROI_state = ROI_waiting;
39 vpMutex s_mutex_image;
41 vpMutex s_mutex_ROI_state;
43 bool s_robotIsRunning;
44 vpMutex s_mutex_control_velocity;
45 vpColVector s_controlVelocity(6, 0.);
50 vpThread::Return displayFunction(vpThread::Args args)
62 vpRectOriented rectangle;
63 bool rectangleRoiDefined =
false;
64 t_stateInitROI stateROI = ROI_waiting;
66 t_CaptureState capture_state_;
67 bool display_initialized_ =
false;
69 #if defined(VISP_HAVE_X11)
70 vpDisplayX *dpost_scan_ = NULL;
71 vpDisplayX *dpost_scan_confidence_ = NULL;
76 plot.setTitle(0,
"X target error");
77 plot.setUnitY(0,
"error");
78 plot.setLegend(0, 0,
"time");
81 plot.setTitle(1,
"confidence barycenter error");
82 plot.setUnitY(1,
"error");
83 plot.setLegend(1, 0,
"time");
92 vpImagePoint ROI_centralPoint;
94 double startTime = vpTime::measureTimeMs();
97 s_mutex_capture.lock();
98 capture_state_ = s_capture_state;
99 s_mutex_capture.unlock();
102 if (capture_state_ == capture_started) {
105 vpMutex::vpScopedLock lock(s_mutex_image);
110 if (rectangleRoiDefined && stateROI == ROI_waiting) {
111 tracker.
init(postScan_, rectangle);
112 s_mutex_ROI_state.lock();
113 s_ROI_state = ROI_started;
114 s_mutex_ROI_state.unlock();
115 stateROI = ROI_started;
119 backConverter_.
convert(postScan_, preScan_, 480);
121 confidenceMapProcessor_.
run(confidencePreScan_, preScan_);
123 converter_.
convert(confidencePreScan_, confidencePostScan_);
126 if (stateROI == ROI_started) {
127 tracker.
update(postScan_);
133 double ttarget = atan2(xtarget, ytarget);
135 double time = (vpTime::measureTimeMs() - startTime) / 1000.0;
137 unsigned int height(confidencePreScan_.getHeight()), width(confidencePreScan_.getWidth());
140 for (
unsigned int i = 0; i < height; ++i)
141 for (
unsigned int j = 0; j < width; ++j)
142 I_sum +=
static_cast<double>(confidencePreScan_[i][j]);
145 for (
unsigned int x = 0; x < height; ++x)
146 for (
unsigned int y = 0; y < width; ++y) {
147 yc += y * confidencePreScan_[x][y];
153 plot.plot(0, 0, time, xtarget);
154 plot.plot(1, 0, time, vpMath::deg(tc));
157 vpMutex::vpScopedLock lock(s_mutex_control_velocity);
159 double lambda_t = 0.8;
160 double lambda_c = 0.8;
162 s_controlVelocity = 0.0;
163 s_controlVelocity[1] = -lambda_t * xtarget + lambda_c * (tc - ttarget) * ytarget;
164 s_controlVelocity[3] = lambda_c * (tc - ttarget);
168 if (!display_initialized_) {
170 #if defined(VISP_HAVE_X11)
171 unsigned int xpos = 10;
172 dpost_scan_ =
new vpDisplayX(postScan_, xpos, 10,
"post-scan");
174 dpost_scan_confidence_ =
new vpDisplayX(confidencePostScan_, xpos, 10,
"post-scan confidence");
175 display_initialized_ =
true;
180 vpDisplay::display(postScan_);
182 if (rectangleRoiDefined) {
183 vpDisplay::displayLine(postScan_,
static_cast<int>(rectangle.getTopLeft().get_i()),
184 static_cast<int>(rectangle.getTopLeft().get_j()),
185 static_cast<int>(rectangle.getBottomLeft().get_i()),
186 static_cast<int>(rectangle.getBottomLeft().get_j()), vpColor::red);
187 vpDisplay::displayLine(postScan_,
static_cast<int>(rectangle.getBottomLeft().get_i()),
188 static_cast<int>(rectangle.getBottomLeft().get_j()),
189 static_cast<int>(rectangle.getBottomRight().get_i()),
190 static_cast<int>(rectangle.getBottomRight().get_j()), vpColor::red);
191 vpDisplay::displayLine(postScan_,
static_cast<int>(rectangle.getBottomRight().get_i()),
192 static_cast<int>(rectangle.getBottomRight().get_j()),
193 static_cast<int>(rectangle.getTopRight().get_i()),
194 static_cast<int>(rectangle.getTopRight().get_j()), vpColor::red);
195 vpDisplay::displayLine(postScan_,
static_cast<int>(rectangle.getTopRight().get_i()),
196 static_cast<int>(rectangle.getTopRight().get_j()),
197 static_cast<int>(rectangle.getTopLeft().get_i()),
198 static_cast<int>(rectangle.getTopLeft().get_j()), vpColor::red);
202 vpDisplay::display(confidencePostScan_);
205 vpDisplay::displayText(postScan_, 10, 10,
"Click to define ROI...", vpColor::red);
206 if (vpDisplay::getClick(postScan_, ROI_centralPoint,
false)) {
208 if (stateROI == ROI_waiting) {
209 rectangle.setCenter(vpImagePoint(ROI_centralPoint.get_v(), ROI_centralPoint.get_u()));
210 rectangle.setSize(80, 50);
211 rectangle.setOrientation(0);
212 rectangleRoiDefined =
true;
217 vpDisplay::displayText(confidencePostScan_, 10, 10,
"Click to exit...", vpColor::red);
218 if (vpDisplay::getClick(confidencePostScan_,
false)) {
219 vpMutex::vpScopedLock lock(s_mutex_capture);
220 s_capture_state = capture_stopped;
224 vpDisplay::flush(postScan_);
225 vpDisplay::flush(confidencePostScan_);
229 }
while (capture_state_ != capture_stopped);
231 #if defined(VISP_HAVE_X11)
233 delete dpost_scan_confidence_;
236 std::cout <<
"End of display thread" << std::endl;
241 vpThread::Return controlFunction(vpThread::Args args)
244 vpRobotViper850 robot;
251 vpHomogeneousMatrix eMs;
256 vpHomogeneousMatrix sMp;
259 vpHomogeneousMatrix sMe;
264 vpVelocityTwistMatrix sVe;
268 vpColVector sHs_star(6);
269 vpColVector pHp_star(6);
271 vpMatrix lambda(6, 6);
273 vpTranslationVector stg;
274 vpColVector sHs_bias(6);
280 vpColVector q_dot(6);
284 for (
int i = 0; i < 3; i++)
285 lambda[i][i] = 0.001;
287 for (
int i = 3; i < 6; i++)
288 lambda[i][i] = 0.005;
300 gHg[2] = -(0.696 + 0.476) * 9.81;
307 vpRotationMatrix sRp;
309 vpTranslationVector stp;
312 vpHomogeneousMatrix eMp = eMs * sMp;
313 vpVelocityTwistMatrix eVp(eMp);
317 vpHomogeneousMatrix fMe;
318 vpHomogeneousMatrix fMs;
319 vpRotationMatrix sRf;
320 robot.getPosition(vpRobot::ARTICULAR_FRAME, q);
321 robot.get_fMe(q, fMe);
324 vpHomogeneousMatrix sMf;
330 vpForceTwistMatrix sFg(sMf);
332 for (
int i = 0; i < 3; i++)
333 for (
int j = 0; j < 3; j++)
334 sFg[i + 3][j] = (stg.skew() * sRf)[i][j];
338 vpForceTwistMatrix sFp(sMp);
341 std::cout <<
"\nBias the force/torque sensor...\n " << std::endl;
342 robot.biasForceTorqueSensor();
345 robot.setRobotState(vpRobot::STATE_VELOCITY_CONTROL);
348 t_CaptureState capture_state_;
349 t_stateInitROI ROI_state = ROI_waiting;
351 std::cout <<
"Waiting ROI definition to start control loop..." << std::endl;
352 while (ROI_state == ROI_waiting) {
353 vpMutex::vpScopedLock lock(s_mutex_ROI_state);
354 ROI_state = s_ROI_state;
357 s_mutex_capture.lock();
358 capture_state_ = s_capture_state;
359 s_mutex_capture.unlock();
360 if (capture_state_ == capture_stopped) {
361 std::cout <<
"end of control thread" << std::endl;
366 std::cout <<
"Starting control loop..." << std::endl;
368 s_mutex_capture.lock();
369 capture_state_ = s_capture_state;
370 s_mutex_capture.unlock();
373 if (capture_state_ == capture_started) {
376 sHs = robot.getForceTorque();
383 robot.getPosition(vpRobot::ARTICULAR_FRAME, q);
384 robot.get_fMe(q, fMe);
394 for (
int i = 0; i < 3; i++)
395 for (
int j = 0; j < 3; j++)
396 sFg[i + 3][j] = (stg.skew() * sRf)[i][j];
399 sHs_bias = sHs - sFg * gHg;
405 vpMutex::vpScopedLock lock(s_mutex_control_velocity);
406 v_p = s_controlVelocity;
415 v_s = lambda * (sFp * pHp_star - (sHs - sFg * gHg - sHs_bias));
423 vpVelocityTwistMatrix eVs;
426 vpColVector v_e = eVs * v_s + eVp * v_p;
434 q_dot = eJe.pseudoInverse() * v_e;
437 robot.setVelocity(vpRobot::ARTICULAR_FRAME, q_dot);
442 }
while (capture_state_ != capture_stopped);
444 std::cout <<
"End of control thread" << std::endl;
449 int main(
int argc,
char **argv)
451 QApplication app(argc, argv);
454 s_robotIsRunning =
false;
455 s_controlVelocity = vpColVector(6, 0);
458 vpThread thread_display((vpThread::Fn)displayFunction);
459 vpThread thread_control((vpThread::Fn)controlFunction);
482 bool stop_capture_ =
false;
484 t_CaptureState capture_state_local = capture_waiting;
488 while (!stop_capture_) {
489 s_mutex_capture.lock();
490 capture_state_local = s_capture_state;
491 s_mutex_capture.unlock();
492 if (capture_state_local == capture_stopped)
493 stop_capture_ =
true;
495 grabbedImage = qtGrabber->
acquire();
497 converter.
convert(*(grabbedImage), postScan_local);
499 s_mutex_image.lock();
500 s_frame = postScan_local;
501 s_mutex_image.unlock();
503 s_mutex_capture.lock();
504 s_capture_state = capture_started;
505 s_mutex_capture.unlock();
510 thread_display.join();
511 thread_control.join();
521 #ifndef VISP_HAVE_V4L2
522 std::cout <<
"You should enable V4L2 to make this example working..." << std::endl;
523 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
524 std::cout <<
"You should enable pthread usage and rebuild ViSP..." << std::endl;
526 std::cout <<
"Multi-threading seems not supported on this platform" << std::endl;
528 #ifndef VISP_HAVE_VIPER850
529 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.
Specific class to grab pre-scan frames from the ultrasound station on the network.
bool isFirstFrameAvailable()
usFrameGrabbedInfo< usImagePreScan2D< unsigned char > > * acquire()
bool initAcquisition(const usNetworkGrabber::usInitHeaderSent &header)
bool sendAcquisitionParameters()
void setMotorPosition(int motorPosition)
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)
double getFieldOfView() const
double getScanLinePitch() const