yarp-devices
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 
50 constexpr auto DEFAULT_REMOTE = "/teo/leftArm";
51 constexpr auto DEFAULT_JOINT = 5;
52 constexpr auto DEFAULT_SPEED = 2.0; // deg/s
53 constexpr auto DEFAULT_TARGET = (-20.0);
54 constexpr auto DEFAULT_PERIOD_MS = 50;
55 constexpr auto DEFAULT_IP_MODE = "pt";
56 
57 int 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 }