Loading [MathJax]/extensions/tex2jax.js
yarp-devices
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Modules Pages
exampleOfflineTrajectorySync.cpp

A constant-velocity, single-joint trajectory is generated with configurable final target, motion speed and period between consecutive points. The yarp::dev::IRemoteVariables interface is used to configure and switch to interpolated position (pi) mode on the real robot. Although prepared for remote execution, this application could be rewritten to connect to a local instance of CanBusBroker. The techniques showcased here are best aimed at trajectories fully available offline (e.g. loaded from file) that assume a constant period between points. To fully take advantage of this fact, all points are sent to the robot in a single batch, hence the flow of the program is slightly different from what you'd expect (no delay function within a for-loop).

Usage (showing default option values):

 exampleOfflineTrajectorySync --remote /teo/leftArm --joint 5 --speed 2.0 --target -20.0 --period 50 --ip pt
See also
exampleOfflineTrajectoryAsync.cpp Use this if the period between points is variable.
exampleOfflineTrajectorySync.py
Tutorial: Trajectory Execution (external)
Note
This application is not suitable for simulation.
1// -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*-
2
33#include <cmath>
34
35#include <iostream>
36
37#include <yarp/os/LogStream.h>
38#include <yarp/os/Network.h>
39#include <yarp/os/Property.h>
40#include <yarp/os/ResourceFinder.h>
41#include <yarp/os/SystemClock.h>
42
43#include <yarp/dev/IControlMode.h>
44#include <yarp/dev/IEncoders.h>
45#include <yarp/dev/IPositionControl.h>
46#include <yarp/dev/IPositionDirect.h>
47#include <yarp/dev/IRemoteVariables.h>
48#include <yarp/dev/PolyDriver.h>
49
50constexpr auto DEFAULT_REMOTE = "/teo/leftArm";
51constexpr auto DEFAULT_JOINT = 5;
52constexpr auto DEFAULT_SPEED = 2.0; // deg/s
53constexpr auto DEFAULT_TARGET = (-20.0);
54constexpr auto DEFAULT_PERIOD_MS = 50;
55constexpr auto DEFAULT_IP_MODE = "pt";
56
57int main(int argc, char * argv[])
58{
59 yarp::os::ResourceFinder rf;
60 rf.configure(argc, argv);
61
62 auto remote = rf.check("remote", yarp::os::Value(DEFAULT_REMOTE), "remote port").asString();
63 auto joint = rf.check("joint", yarp::os::Value(DEFAULT_JOINT), "joint id").asInt32();
64 auto speed = rf.check("speed", yarp::os::Value(DEFAULT_SPEED), "trajectory speed (deg/s)").asFloat64();
65 auto target = rf.check("target", yarp::os::Value(DEFAULT_TARGET), "target position (deg)").asFloat64();
66 auto period = rf.check("period", yarp::os::Value(DEFAULT_PERIOD_MS), "command period (ms)").asInt32() * 0.001;
67 auto ip = rf.check("ip", yarp::os::Value(DEFAULT_IP_MODE), "interpolation submode [pt|pvt]").asString();
68
69 if (speed <= 0)
70 {
71 yError() << "Illegal speed (deg/s):" << speed;
72 return 1;
73 }
74
75 if (period <= 0)
76 {
77 yError() << "Illegal period (s):" << period;
78 return 1;
79 }
80
81 if (ip != "pt" && ip != "pvt")
82 {
83 yError() << "Illegal ip mode:" << ip;
84 return 1;
85 }
86
87 yarp::os::Network yarp;
88
89 if (!yarp::os::Network::checkNetwork())
90 {
91 yError() << "Please start a yarp name server first";
92 return 1;
93 }
94
95 yarp::os::Property options {{"device", yarp::os::Value("remote_controlboard")},
96 {"local", yarp::os::Value("/exampleOfflineTrajectorySync")},
97 {"remote", yarp::os::Value(remote)},
98 {"writeStrict", yarp::os::Value("on")}};
99
100 yarp::dev::PolyDriver dd(options);
101
102 if (!dd.isValid())
103 {
104 yError() << "Remote device not available";
105 return 1;
106 }
107
108 yarp::dev::IControlMode * mode;
109 yarp::dev::IEncoders * enc;
110 yarp::dev::IPositionControl * pos;
111 yarp::dev::IPositionDirect * posd;
112 yarp::dev::IRemoteVariables * var;
113
114 if (!dd.view(mode) || !dd.view(enc) || !dd.view(pos) || !dd.view(posd) || !dd.view(var))
115 {
116 yError() << "Unable to acquire robot interfaces";
117 return 1;
118 }
119
120 yarp::os::Bottle b;
121 yarp::os::Bottle & bb = b.addList(); // additional nesting because of controlboardremapper
122
123 bb.addList() = {yarp::os::Value("ipMode"), yarp::os::Value(ip)};
124 bb.addList() = {yarp::os::Value("ipPeriodMs"), yarp::os::Value(period * 1000.0)};
125 bb.addList() = {yarp::os::Value("enableIp"), yarp::os::Value(true)}; // important: place this last
126
127 if (!var->setRemoteVariable("all", b))
128 {
129 yError() << "Unable to set interpolation mode";
130 return 1;
131 }
132
133 if (!mode->setControlMode(joint, VOCAB_CM_POSITION_DIRECT))
134 {
135 yError() << "Unable to set position direct mode";
136 return 1;
137 }
138
139 double initialPos;
140 int retries = 0;
141
142 while (!enc->getEncoder(joint, &initialPos) && retries++ < 10)
143 {
144 yarp::os::SystemClock::delaySystem(0.05);
145 }
146
147 if (retries >= 10)
148 {
149 yError() << "getEncoders() failed";
150 return 1;
151 }
152
153 yInfo() << "Current ENC value:" << initialPos;
154
155 std::cin.get();
156
157 yInfo() << "Moving joint" << joint << "to" << target << "degrees...";
158
159 const double distance = target - initialPos;
160 const double increment = std::copysign(speed * period, distance);
161
162 int count = 1;
163 double newDistance = 0.0;
164
165 do
166 {
167 newDistance = count * increment;
168 auto position = initialPos + newDistance;
169 yInfo("[%d] New target: %f", count++, position);
170 posd->setPosition(joint, position);
171 }
172 while (std::abs(distance) > std::abs(newDistance));
173
174 bool motionDone;
175
176 do
177 {
178 std::cout << "." << std::flush;
179 yarp::os::SystemClock::delaySystem(0.1);
180 }
181 while (pos->checkMotionDone(&motionDone) && !motionDone);
182
183 std::cout << " end" << std::endl;
184
185 return 0;
186}