Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
sonarPioneerReader.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 * Example that shows how to control a Pioneer mobile robot in ViSP.
32 */
33
34#include <iostream>
35
36#include <visp3/core/vpConfig.h>
37#include <visp3/robot/vpRobotPioneer.h> // Include first to avoid build issues with Status, None, isfinite
38#include <visp3/core/vpDisplay.h>
39#include <visp3/core/vpImage.h>
40#include <visp3/core/vpIoTools.h>
41#include <visp3/core/vpTime.h>
42#include <visp3/gui/vpDisplayFactory.h>
43#include <visp3/io/vpImageIo.h>
44
45#ifndef VISP_HAVE_PIONEER
46int main()
47{
48 std::cout << "\nThis example requires Aria 3rd party library. You should "
49 "install it.\n"
50 << std::endl;
51 return EXIT_SUCCESS;
52}
53
54#else
55
56#ifdef ENABLE_VISP_NAMESPACE
57using namespace VISP_NAMESPACE_NAME;
58#endif
59
60ArSonarDevice sonar;
61vpRobotPioneer *robot;
62#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
63std::shared_ptr<vpDisplay> display;
64#else
65vpDisplay *display = nullptr;
66#endif
68static bool isInitialized = false;
69static int half_size = 256 * 2;
70
71void sonarPrinter(void)
72{
73 fprintf(stdout, "in sonarPrinter()\n");
74 fflush(stdout);
75 double scale = static_cast<double>(half_size) / static_cast<double>(sonar.getMaxRange());
76
77 /*
78 ArSonarDevice *sd;
79
80 std::list<ArPoseWithTime *>::iterator it;
81 std::list<ArPoseWithTime *> *readings;
82 ArPose *pose;
83
84 sd = (ArSonarDevice *)robot->findRangeDevice("sonar");
85 if (sd != nullptr)
86 {
87 sd->lockDevice();
88 readings = sd->getCurrentBuffer();
89 if (readings != nullptr)
90 {
91 for (it = readings->begin(); it != readings->end(); ++it)
92 {
93 pose = (*it);
94 //pose->log();
95 }
96 }
97 sd->unlockDevice();
98 }
99*/
100 double range;
101 double angle;
102
103 /*
104 * example to show how to find closest readings within polar sections
105 */
106 printf("Closest readings within polar sections:\n");
107
108 double start_angle = -45;
109 double end_angle = 45;
110 range = sonar.currentReadingPolar(start_angle, end_angle, &angle);
111 printf(" front quadrant: %5.0f ", range);
112 // if (range != sonar.getMaxRange())
113 if (std::fabs(range - sonar.getMaxRange()) > std::numeric_limits<double>::epsilon())
114 printf("%3.0f ", angle);
115 printf("\n");
116#if defined(VISP_HAVE_DISPLAY)
117 // if (isInitialized && range != sonar.getMaxRange())
118 if (isInitialized && std::fabs(range - sonar.getMaxRange()) > std::numeric_limits<double>::epsilon()) {
119 double x = range * cos(vpMath::rad(angle)); // position of the obstacle in the sensor frame
120 double y = range * sin(vpMath::rad(angle));
121
122 // Conversion in pixels so that the robot frame is in the middle of the
123 // image
124 double j = -y * scale + half_size; // obstacle position
125 double i = -x * scale + half_size;
126
128 vpDisplay::displayLine(I, half_size, half_size, 0, 0, vpColor::red, 5);
129 vpDisplay::displayLine(I, half_size, half_size, 0, 2 * half_size - 1, vpColor::red, 5);
130 vpDisplay::displayLine(I, half_size, half_size, i, j, vpColor::green, 3);
132 }
133#endif
134
135 range = sonar.currentReadingPolar(-135, -45, &angle);
136 printf(" right quadrant: %5.0f ", range);
137 // if (range != sonar.getMaxRange())
138 if (std::fabs(range - sonar.getMaxRange()) > std::numeric_limits<double>::epsilon())
139 printf("%3.0f ", angle);
140 printf("\n");
141
142 range = sonar.currentReadingPolar(45, 135, &angle);
143 printf(" left quadrant: %5.0f ", range);
144 // if (range != sonar.getMaxRange())
145 if (std::fabs(range - sonar.getMaxRange()) > std::numeric_limits<double>::epsilon())
146 printf("%3.0f ", angle);
147 printf("\n");
148
149 range = sonar.currentReadingPolar(-135, 135, &angle);
150 printf(" back quadrant: %5.0f ", range);
151 // if (range != sonar.getMaxRange())
152 if (std::fabs(range - sonar.getMaxRange()) > std::numeric_limits<double>::epsilon())
153 printf("%3.0f ", angle);
154 printf("\n");
155
156 /*
157 * example to show how get all sonar sensor data
158 */
159 ArSensorReading *reading;
160 for (int sensor = 0; sensor < robot->getNumSonar(); sensor++) {
161 reading = robot->getSonarReading(sensor);
162 if (reading != nullptr) {
163 angle = reading->getSensorTh();
164 range = reading->getRange();
165 double sx = reading->getSensorX(); // position of the sensor in the robot frame
166 double sy = reading->getSensorY();
167 double ox = range * cos(vpMath::rad(angle)); // position of the obstacle in the sensor frame
168 double oy = range * sin(vpMath::rad(angle));
169 double x = sx + ox; // position of the obstacle in the robot frame
170 double y = sy + oy;
171
172 // Conversion in pixels so that the robot frame is in the middle of the
173 // image
174 double sj = -sy * scale + half_size; // sensor position
175 double si = -sx * scale + half_size;
176 double j = -y * scale + half_size; // obstacle position
177 double i = -x * scale + half_size;
178
179 // printf("%d x: %.1f y: %.1f th: %.1f d: %d\n", sensor,
180 // reading->getSensorX(),
181 // reading->getSensorY(), reading->getSensorTh(),
182 // reading->getRange());
183
184#if defined(VISP_HAVE_DISPLAY)
185 // if (isInitialized && range != sonar.getMaxRange())
186 if (isInitialized && std::fabs(range - sonar.getMaxRange()) > std::numeric_limits<double>::epsilon()) {
187 vpDisplay::displayLine(I, si, sj, i, j, vpColor::blue, 2);
189 std::stringstream legend;
190 legend << sensor << ": " << std::setprecision(2) << float(range) / 1000.;
191 vpDisplay::displayText(I, i - 7, j + 7, legend.str(), vpColor::blue);
192 }
193#endif
194 }
195 }
196
197#if defined(VISP_HAVE_DISPLAY)
198 if (isInitialized)
200#endif
201
202 fflush(stdout);
203}
204
210int main(int argc, char **argv)
211{
212 try {
213 ArArgumentParser parser(&argc, argv);
214 parser.loadDefaultArguments();
215
216 robot = new vpRobotPioneer;
217
218 // ArRobotConnector connects to the robot, get some initial data from it
219 // such as type and name, and then loads parameter files for this robot.
220 ArRobotConnector robotConnector(&parser, robot);
221 if (!robotConnector.connectRobot()) {
222 ArLog::log(ArLog::Terse, "Could not connect to the robot");
223 if (parser.checkHelpAndWarnUnparsed()) {
224 Aria::logOptions();
225 Aria::exit(1);
226 }
227 }
228 if (!Aria::parseArgs()) {
229 Aria::logOptions();
230 Aria::shutdown();
231 return false;
232 }
233
234 std::cout << "Robot connected" << std::endl;
235
236#if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)
237 // Create a display to show sensor data
238 if (isInitialized == false) {
239 I.resize(static_cast<unsigned int>(half_size * 2), static_cast<unsigned int>(half_size * 2));
240 I = 255u;
241
242#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
243 display = vpDisplayFactory::createDisplay(I, -1, -1, "Sonar range data");
244#else
245 display = vpDisplayFactory::allocateDisplay(I, -1, -1, "Sonar range data");
246#endif
247 isInitialized = true;
248 }
249#endif
250
251 // Activates the sonar
252 ArGlobalFunctor sonarPrinterCB(&sonarPrinter);
253 robot->addRangeDevice(&sonar);
254 robot->addUserTask("Sonar printer", 50, &sonarPrinterCB);
255
256 robot->useSonar(true); // activates the sonar device usage
257
258 // Robot velocities
259 vpColVector v_mes(2);
260
261 for (int i = 0; i < 1000; i++) {
262 double t = vpTime::measureTimeMs();
263
264 v_mes = robot->getVelocity(vpRobot::REFERENCE_FRAME);
265 std::cout << "Trans. vel= " << v_mes[0] << " m/s, Rot. vel=" << vpMath::deg(v_mes[1]) << " deg/s" << std::endl;
266 v_mes = robot->getVelocity(vpRobot::ARTICULAR_FRAME);
267 std::cout << "Left wheel vel= " << v_mes[0] << " m/s, Right wheel vel=" << v_mes[1] << " m/s" << std::endl;
268 std::cout << "Battery=" << robot->getBatteryVoltage() << std::endl;
269
270#if defined(VISP_HAVE_X11) || defined(VISP_HAVE_GDI)
271 if (isInitialized) {
272 // A mouse click to exit
273 // Before exiting save the last sonar image
274 if (vpDisplay::getClick(I, false) == true) {
275 {
276 // Set the default output path
277 std::string opath;
278#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
279 opath = "/tmp";
280#elif defined(_WIN32)
281 opath = "C:\\temp";
282#endif
283 std::string username = vpIoTools::getUserName();
284
285 // Append to the output path string, the login name of the user
286 opath = vpIoTools::createFilePath(opath, username);
287
288 // Test if the output path exist. If no try to create it
289 if (vpIoTools::checkDirectory(opath) == false) {
290 try {
291 // Create the dirname
293 }
294 catch (...) {
295 std::cerr << std::endl << "ERROR:" << std::endl;
296 std::cerr << " Cannot create " << opath << std::endl;
297 return EXIT_FAILURE;
298 }
299 }
300 std::string filename = opath + "/sonar.png";
303 vpImageIo::write(C, filename);
304 }
305 break;
306 }
307 }
308#endif
309
310 vpTime::wait(t, 40);
311 }
312
313 ArLog::log(ArLog::Normal, "simpleMotionCommands: Stopping.");
314 robot->lock();
315 robot->stop();
316 robot->unlock();
317 ArUtil::sleep(1000);
318
319 robot->lock();
320 ArLog::log(ArLog::Normal,
321 "simpleMotionCommands: Pose=(%.2f,%.2f,%.2f), Trans. "
322 "Vel=%.2f, Rot. Vel=%.2f, Battery=%.2fV",
323 robot->getX(), robot->getY(), robot->getTh(), robot->getVel(), robot->getRotVel(),
324 robot->getBatteryVoltage());
325 robot->unlock();
326
327 std::cout << "Ending robot thread..." << std::endl;
328 robot->stopRunning();
329
330#if defined(VISP_HAVE_DISPLAY) && (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
331 if (isInitialized && (display != nullptr)) {
332 delete display;
333 }
334#endif
335
336 // wait for the thread to stop
337 robot->waitForRunExit();
338
339 delete robot;
340
341 // exit
342 ArLog::log(ArLog::Normal, "simpleMotionCommands: Exiting.");
343 return EXIT_SUCCESS;
344 }
345 catch (const vpException &e) {
346 std::cout << "Catch an exception: " << e << std::endl;
347#if defined(VISP_HAVE_DISPLAY) && (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
348 if (display != nullptr) {
349 delete display;
350 }
351#endif
352 return EXIT_FAILURE;
353 }
354}
355
356#endif
Implementation of column vector and the associated operations.
static const vpColor red
Definition vpColor.h:198
static const vpColor blue
Definition vpColor.h:204
static const vpColor green
Definition vpColor.h:201
Class that defines generic functionalities for display.
Definition vpDisplay.h:171
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void flush(const vpImage< unsigned char > &I)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition vpException.h:60
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition of the vpImage class member functions.
Definition vpImage.h:131
static bool checkDirectory(const std::string &dirname)
static std::string getUserName()
static std::string createFilePath(const std::string &parent, const std::string &child)
static void makeDirectory(const std::string &dirname)
static double rad(double deg)
Definition vpMath.h:129
static double deg(double rad)
Definition vpMath.h:119
Interface for Pioneer mobile robots based on Aria 3rd party library.
@ REFERENCE_FRAME
Definition vpRobot.h:75
@ ARTICULAR_FRAME
Definition vpRobot.h:77
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT double measureTimeMs()
VISP_EXPORT int wait(double t0, double t)