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_confidence_map/usScanlineConfidence2D.h>
15 #include <visp3/ustk_core/usImagePostScan2D.h>
16 #include <visp3/ustk_core/usImagePreScan2D.h>
17 #include <visp3/ustk_core/usPostScanToPreScan2DConverter.h>
18 #include <visp3/ustk_core/usPreScanToPostScan2DConverter.h>
20 #if defined(VISP_HAVE_V4L2) && defined(VISP_HAVE_PTHREAD) && defined(VISP_HAVE_VIPER850)
23 typedef enum { capture_waiting, capture_started, capture_stopped } t_CaptureState;
24 t_CaptureState s_capture_state = capture_waiting;
25 vpImage<unsigned char> s_frame;
26 vpMutex s_mutex_capture;
28 bool s_robotIsRunning;
29 vpMutex s_mutex_control_velocity;
30 vpColVector s_controlVelocity(6, 0.);
35 vpThread::Return captureFunction(vpThread::Args args)
37 vpV4l2Grabber cap = *((vpV4l2Grabber *)args);
38 vpImage<unsigned char> frame_;
39 bool stop_capture_ =
false;
43 vpRect roi(vpImagePoint(55, 70), vpImagePoint(410, 555));
45 while (!stop_capture_) {
47 cap.acquire(frame_, roi);
51 vpMutex::vpScopedLock lock(s_mutex_capture);
52 if (s_capture_state == capture_stopped)
55 s_capture_state = capture_started;
61 vpMutex::vpScopedLock lock(s_mutex_capture);
62 s_capture_state = capture_stopped;
64 std::cout <<
"End of capture thread" << std::endl;
70 vpThread::Return displayFunction(vpThread::Args args)
73 vpImage<unsigned char> I_;
89 t_CaptureState capture_state_;
90 bool display_initialized_ =
false;
92 #if defined(VISP_HAVE_X11)
93 vpDisplayX *dpost_scan_ = NULL;
94 vpDisplayX *dpre_scan_ = NULL;
95 vpDisplayX *dpost_scan_confidence_ = NULL;
96 vpDisplayX *dpre_scan_confidence_ = NULL;
101 plot.initGraph(0, 1);
102 plot.initRange(0, 0, 10, -10, 10);
103 plot.setTitle(0,
"confidence barycenter error");
104 plot.setUnitY(0,
"error(degrees)");
105 plot.setLegend(0, 0,
"time");
107 double startTime = vpTime::measureTimeMs();
110 s_mutex_capture.lock();
111 capture_state_ = s_capture_state;
112 s_mutex_capture.unlock();
115 if (capture_state_ == capture_started) {
118 vpMutex::vpScopedLock lock(s_mutex_capture);
134 postScan_.getHeight());
138 postScan_.getWidth());
140 backConverter_.
convert(postScan_, preScan_, 480);
142 confidenceMapProcessor_.
run(confidencePreScan_, preScan_);
145 converter_.
convert(confidencePreScan_, confidencePostScan_);
147 unsigned int height(confidencePreScan_.getHeight()), width(confidencePreScan_.getWidth());
150 for (
unsigned int i = 0; i < height; ++i)
151 for (
unsigned int j = 0; j < width; ++j)
152 I_sum +=
static_cast<double>(confidencePreScan_[i][j]);
155 for (
unsigned int x = 0; x < height; ++x)
156 for (
unsigned int y = 0; y < width; ++y) {
157 yc += y * confidencePreScan_[x][y];
163 double time = (vpTime::measureTimeMs() - startTime) / 1000.0;
165 plot.plot(0, 0, time, vpMath::deg(tc));
168 vpMutex::vpScopedLock lock(s_mutex_capture);
169 s_controlVelocity = 0.0;
170 s_controlVelocity[3] = 0.5 * tc;
173 if (!display_initialized_) {
175 #if defined(VISP_HAVE_X11)
176 unsigned int xpos = 10;
177 dpost_scan_ =
new vpDisplayX(postScan_, xpos, 10,
"post-scan");
178 xpos += 80 + postScan_.getWidth();
179 dpre_scan_ =
new vpDisplayX(preScan_, xpos, 10,
"pre-scan");
180 xpos += 40 + preScan_.getWidth();
181 dpre_scan_confidence_ =
new vpDisplayX(confidencePreScan_, xpos, 10,
"pre-scan confidence");
182 xpos += 40 + confidencePreScan_.getWidth();
183 dpost_scan_confidence_ =
new vpDisplayX(confidencePostScan_, xpos, 10,
"post-scan confidence");
184 display_initialized_ =
true;
189 vpDisplay::display(postScan_);
190 vpDisplay::display(preScan_);
191 vpDisplay::display(confidencePreScan_);
192 vpDisplay::display(confidencePostScan_);
195 vpDisplay::displayText(postScan_, 10, 10,
"Click to exit...", vpColor::red);
196 if (vpDisplay::getClick(postScan_,
false)) {
197 vpMutex::vpScopedLock lock(s_mutex_capture);
198 s_capture_state = capture_stopped;
200 vpDisplay::displayText(preScan_, 10, 10,
"Click to exit...", vpColor::red);
201 if (vpDisplay::getClick(preScan_,
false)) {
202 vpMutex::vpScopedLock lock(s_mutex_capture);
203 s_capture_state = capture_stopped;
205 vpDisplay::displayText(confidencePreScan_, 10, 10,
"Click to exit...", vpColor::red);
206 if (vpDisplay::getClick(confidencePreScan_,
false)) {
207 vpMutex::vpScopedLock lock(s_mutex_capture);
208 s_capture_state = capture_stopped;
210 vpDisplay::displayText(confidencePostScan_, 10, 10,
"Click to exit...", vpColor::red);
211 if (vpDisplay::getClick(confidencePostScan_,
false)) {
212 vpMutex::vpScopedLock lock(s_mutex_capture);
213 s_capture_state = capture_stopped;
217 vpDisplay::flush(postScan_);
218 vpDisplay::flush(preScan_);
219 vpDisplay::flush(confidencePostScan_);
220 vpDisplay::flush(confidencePreScan_);
224 }
while (capture_state_ != capture_stopped);
226 #if defined(VISP_HAVE_X11)
229 delete dpre_scan_confidence_;
230 delete dpost_scan_confidence_;
233 std::cout <<
"End of display thread" << std::endl;
238 vpThread::Return controlFunction(vpThread::Args args)
241 vpRobotViper850 robot;
248 vpHomogeneousMatrix eMs;
253 vpHomogeneousMatrix sMp;
256 vpHomogeneousMatrix sMe;
261 vpVelocityTwistMatrix sVe;
265 vpColVector sHs_star(6);
266 vpColVector pHp_star(6);
268 vpMatrix lambda(6, 6);
270 vpTranslationVector stg;
271 vpColVector sHs_bias(6);
277 vpColVector q_dot(6);
281 for (
int i = 0; i < 3; i++)
282 lambda[i][i] = 0.02 / 6;
284 for (
int i = 3; i < 6; i++)
285 lambda[i][i] = 1. / 2;
297 gHg[2] = -(0.696 + 0.476) * 9.81;
304 vpRotationMatrix sRp;
306 vpTranslationVector stp;
309 vpHomogeneousMatrix eMp = eMs * sMp;
310 vpVelocityTwistMatrix eVp(eMp);
314 vpHomogeneousMatrix fMe;
315 vpHomogeneousMatrix fMs;
316 vpRotationMatrix sRf;
317 robot.getPosition(vpRobot::ARTICULAR_FRAME, q);
318 robot.get_fMe(q, fMe);
321 vpHomogeneousMatrix sMf;
327 vpForceTwistMatrix sFg(sMf);
329 for (
int i = 0; i < 3; i++)
330 for (
int j = 0; j < 3; j++)
331 sFg[i + 3][j] = (stg.skew() * sRf)[i][j];
335 vpForceTwistMatrix sFp(sMp);
338 std::cout <<
"\nBias the force/torque sensor...\n " << std::endl;
339 robot.biasForceTorqueSensor();
342 robot.setRobotState(vpRobot::STATE_VELOCITY_CONTROL);
345 t_CaptureState capture_state_;
347 std::cout <<
"Starting control loop..." << std::endl;
349 s_mutex_capture.lock();
350 capture_state_ = s_capture_state;
351 s_mutex_capture.unlock();
354 if (capture_state_ == capture_started) {
357 sHs = robot.getForceTorque();
364 robot.getPosition(vpRobot::ARTICULAR_FRAME, q);
365 robot.get_fMe(q, fMe);
375 for (
int i = 0; i < 3; i++)
376 for (
int j = 0; j < 3; j++)
377 sFg[i + 3][j] = (stg.skew() * sRf)[i][j];
380 sHs_bias = sHs - sFg * gHg;
386 vpMutex::vpScopedLock lock(s_mutex_capture);
387 v_p = s_controlVelocity;
397 v_s = lambda * (sFp * pHp_star - (sHs - sFg * gHg - sHs_bias));
405 vpVelocityTwistMatrix eVs;
408 vpColVector v_e = eVs * v_s + eVp * v_p;
414 q_dot = eJe.pseudoInverse() * v_e;
417 robot.setVelocity(vpRobot::ARTICULAR_FRAME, q_dot);
422 }
while (capture_state_ != capture_stopped);
424 std::cout <<
"End of control thread" << std::endl;
429 int main(
int argc,
const char *argv[])
431 unsigned int opt_input = 1;
434 for (
int i = 0; i < argc; i++) {
435 if (std::string(argv[i]) ==
"--input")
436 opt_input = (
unsigned int)atoi(argv[i + 1]);
437 else if (std::string(argv[i]) ==
"--help") {
438 std::cout <<
"Usage: " << argv[0] <<
" [--input <number>] [--help]" << std::endl;
446 g.setInput(opt_input);
450 s_robotIsRunning =
false;
451 s_controlVelocity = vpColVector(6, 0);
454 vpThread thread_capture((vpThread::Fn)captureFunction, (vpThread::Args)&g);
455 vpThread thread_display((vpThread::Fn)displayFunction);
456 vpThread thread_control((vpThread::Fn)controlFunction);
459 thread_capture.join();
460 thread_display.join();
461 thread_control.join();
470 #ifndef VISP_HAVE_V4L2
471 std::cout <<
"You should enable V4L2 to make this example working..." << std::endl;
472 #elif !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
473 std::cout <<
"You should enable pthread usage and rebuild ViSP..." << std::endl;
475 std::cout <<
"Multi-threading seems not supported on this platform" << std::endl;
477 #ifndef VISP_HAVE_VIPER850
478 std::cout <<
"You need viper 850 robot to run this example" << std::endl;
void setHeightResolution(double heightResolution)
void setData(const vpImage< Type > &image)
void setWidthResolution(double widthResolution)
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)
Generic class for 2D ultrasound data common settings associated to the type of probe transducer used ...
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)