40#include <visp3/core/vpConfig.h>
42#if defined(VISP_HAVE_POLOLU) && defined(VISP_HAVE_THREADS)
49#include <visp3/core/vpMath.h>
50#include <visp3/robot/vpPololu.h>
52#ifdef ENABLE_VISP_NAMESPACE
56void usage(
const char **argv,
int error,
const std::string &device,
int baudrate,
int channel,
57 unsigned short pwm_min,
unsigned short pwm_max,
float angle_min,
float angle_max);
59void usage(
const char **argv,
int error,
const std::string &device,
int baudrate,
int channel,
60 unsigned short pwm_min,
unsigned short pwm_max,
float angle_min,
float angle_max)
62 std::cout <<
"Synopsis" << std::endl
63 <<
" " << argv[0] <<
" [--device <name>] [--baud <rate>] [--channel <number>] [--calibrate]"
64 <<
" [--range-pwm <min max> ] [--verbose, -v] [--help, -h]" << std::endl
66 std::cout <<
"Description" << std::endl
67 <<
" --device <name> Device name." << std::endl
68 <<
" Default: " << device << std::endl
70 <<
" --baud <rate> Serial link baud rate." << std::endl
71 <<
" Default: " << baudrate << std::endl
73 <<
" --channel <number> Channel to dial with." << std::endl
74 <<
" Default: " << channel << std::endl
76 <<
" --range-pwm <min max> Set PWM min and max values." << std::endl
77 <<
" You can use \"--calibrate\" to retrieve min and max pwm values."
78 <<
" Default: " << pwm_min <<
" " << pwm_max << std::endl
80 <<
" --range-angles <min max> Set angle min and max values (deg)." << std::endl
83 <<
" --verbose, -v Enable verbosity." << std::endl
85 <<
" --calibrate Start pwm calibration determining min and max admissible values." << std::endl
86 <<
" Once calibration done you can use \"--range-pwm <min max>\" option to set" << std::endl
87 <<
" the corresponding values" << std::endl
89 <<
" --help, -h Print this helper message." << std::endl
92 std::cout <<
"Error" << std::endl
94 <<
"Unsupported parameter " << argv[
error] << std::endl;
98int main(
int argc,
const char **argv)
101 std::string opt_device =
"COM4";
103 std::string opt_device =
"/dev/ttyACM0";
108 int opt_baudrate = 38400;
109 bool opt_verbose =
false;
110 bool opt_calibrate =
false;
111 unsigned short opt_pwm_min = 4000;
112 unsigned short opt_pwm_max = 8000;
113 float opt_angle_min =
static_cast<float>(
vpMath::rad(-45));
114 float opt_angle_max =
static_cast<float>(
vpMath::rad(45));
115 float opt_positioning_velocity =
static_cast<float>(
vpMath::rad(10));
116 float last_angle = 0;
119 for (
int i = 1;
i < argc;
i++) {
120 if (std::string(argv[i]) ==
"--device" && i + 1 < argc) {
121 opt_device = std::string(argv[i + 1]);
124 else if (std::string(argv[i]) ==
"--baud" && i + 1 < argc) {
125 opt_baudrate = std::atoi(argv[i + 1]);
128 else if (std::string(argv[i]) ==
"--channel" && i + 1 < argc) {
129 opt_channel = std::atoi(argv[i + 1]);
132 else if (std::string(argv[i]) ==
"--range-pwm" && i + 2 < argc) {
133 opt_pwm_min =
static_cast<unsigned short>(
vpMath::rad(std::atoi(argv[i + 1])));
134 opt_pwm_max =
static_cast<unsigned short>(
vpMath::rad(std::atoi(argv[i + 2])));
137 else if (std::string(argv[i]) ==
"--range-angles" && i + 2 < argc) {
138 opt_angle_min =
static_cast<float>(std::atof(argv[i + 1]));
139 opt_angle_max =
static_cast<float>(std::atof(argv[i + 2]));
142 else if (std::string(argv[i]) ==
"--calibrate") {
143 opt_calibrate =
true;
145 else if (std::string(argv[i]) ==
"--verbose" || std::string(argv[i]) ==
"-v") {
148 else if (std::string(argv[i]) ==
"--help" || std::string(argv[i]) ==
"-h") {
149 usage(argv, 0, opt_device, opt_baudrate, opt_channel, opt_pwm_min, opt_pwm_max, opt_angle_min, opt_angle_max);
153 usage(argv, i, opt_device, opt_baudrate, opt_channel, opt_pwm_min, opt_pwm_max, opt_angle_min, opt_angle_max);
160 vpPololu servo(opt_device, opt_baudrate, opt_channel, opt_verbose);
162 std::cout <<
"Pololu board is " << (servo.connected() ?
"connected" :
"disconnected") << std::endl;
165 std::cout <<
"Proceed to calibration to determine pwm min and max values..." << std::endl;
166 std::cout <<
"WARNING: Calibration will move the servo at channel " << opt_channel <<
"!" << std::endl;
167 std::cout <<
"Press Enter to move to min and max pwm positions..." << std::endl;
170 unsigned short pwm_min, pwm_max;
171 servo.calibrate(pwm_min, pwm_max);
172 std::cout <<
"Servo on channel " << opt_channel <<
" has pwm range [" << pwm_min <<
", " << pwm_max <<
"]" << std::endl;
176 servo.setPwmRange(opt_pwm_min, opt_pwm_max);
177 servo.setAngularRange(opt_angle_min, opt_angle_max);
180 servo.getRangePwm(opt_pwm_min, opt_pwm_max);
181 std::cout <<
"Position range (pwm): " << opt_pwm_min <<
" " << opt_pwm_max << std::endl;
182 servo.getRangeAngles(opt_angle_min, opt_angle_max);
183 std::cout <<
"Position range (deg): " <<
vpMath::deg(opt_angle_min) <<
" " <<
vpMath::deg(opt_angle_max) << std::endl;
186 std::cout <<
"Move to min position (pwm): " << opt_pwm_min <<
" at max velocity" << std::endl;
187 servo.setPwmPosition(opt_pwm_min, 0);
188 std::this_thread::sleep_for(std::chrono::seconds(3));
189 std::cout <<
"Servo reached position (pwm): " << servo.getPwmPosition() << std::endl;
191 std::cout <<
"Move to max position (pwm): " << opt_pwm_max <<
" at max velocity" << std::endl;
192 servo.setPwmPosition(opt_pwm_max, 0);
193 std::this_thread::sleep_for(std::chrono::seconds(3));
194 std::cout <<
"Servo reached position (pwm): " << servo.getPwmPosition() << std::endl;
197 std::cout <<
"Move to min position (deg): " <<
vpMath::deg(opt_angle_min) <<
" at max velocity" << std::endl;
198 servo.setAngularPosition(opt_angle_min, 0);
199 std::this_thread::sleep_for(std::chrono::seconds(3));
200 std::cout <<
"Servo reached position (deg): " <<
vpMath::deg(servo.getAngularPosition()) << std::endl;
202 std::cout <<
"Move to max position (deg): " <<
vpMath::deg(opt_angle_max) <<
" at max velocity" << std::endl;
203 servo.setAngularPosition(opt_angle_max, 0);
204 std::this_thread::sleep_for(std::chrono::seconds(3));
205 std::cout <<
"Servo reached position (deg): " <<
vpMath::deg(servo.getAngularPosition()) << std::endl;
208 std::cout <<
"Move to zero position (deg): " <<
vpMath::deg(0) <<
" at max velocity" << std::endl;
209 servo.setAngularPosition(0, 0);
210 std::this_thread::sleep_for(std::chrono::seconds(3));
211 last_angle = servo.getAngularPosition();
212 std::cout <<
"Servo reached position (deg): " <<
vpMath::deg(last_angle) << std::endl;
215 std::cout <<
"Move to min position (deg): " <<
vpMath::deg(opt_angle_min) <<
" at " <<
vpMath::deg(opt_positioning_velocity) <<
" deg/s" << std::endl;
216 servo.setAngularPosition(opt_angle_min, opt_positioning_velocity);
218 time_s =
static_cast<int>(std::abs((opt_angle_min - last_angle) / opt_positioning_velocity) + 2);
220 std::this_thread::sleep_for(std::chrono::seconds(time_s));
221 last_angle = servo.getAngularPosition();
222 std::cout <<
"Servo reached position (deg): " <<
vpMath::deg(last_angle) << std::endl;
224 std::cout <<
"Move to max position (deg): " <<
vpMath::deg(opt_angle_max) <<
" at " <<
vpMath::deg(opt_positioning_velocity) <<
" deg/s" << std::endl;
225 servo.setAngularPosition(opt_angle_max, opt_positioning_velocity);
227 time_s =
static_cast<int>(std::abs((opt_angle_max - last_angle) / opt_positioning_velocity) + 2);
228 std::this_thread::sleep_for(std::chrono::seconds(time_s));
229 last_angle = servo.getAngularPosition();
230 std::cout <<
"Servo reached position (deg): " <<
vpMath::deg(last_angle) << std::endl;
235 std::cout <<
e.getMessage() << std::endl;
243 std::cout <<
"ViSP doesn't support Pololu 3rd party library" << std::endl;
error that can be emitted by ViSP classes.
static double rad(double deg)
static double deg(double rad)
Interface for the Pololu Maestro USB Servo Controllers.