yarp-devices
Loading...
Searching...
No Matches
exampleOfflineTrajectoryAsync.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 don't assume a constant period between points.

Usage (showing default option values):

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