YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
main.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include <yarp/os/Network.h>
7#include <yarp/os/RFModule.h>
8#include <yarp/os/Time.h>
9#include <yarp/os/Log.h>
10#include <yarp/os/LogStream.h>
12#include <yarp/sig/Vector.h>
14
15#include <fstream>
16#include <iostream>
17#include <iomanip>
18#include <string>
19#include <vector>
20#include <deque>
21#include <cmath>
22#include <map>
23#include <mutex>
24
25#include "robotDriver.h"
26#include "robotAction.h"
27#include "broadcastingThread.h"
28#include "controlThread.h"
29
30// ******************** THE MODULE
32{
33protected:
35 std::string m_name;
37 std::map<std::string,robotDriver*> m_robotControllers;
38 std::map<std::string,action_class> m_actions;
41
43
44 public: //yarpActionsPlayer_IDL methods
45 bool start() override;
46 bool stop() override;
47 bool reset() override;
48 bool forever() override;
49 bool print_frames() override;
50 bool speed_factor(const double value) override;
51 bool resample(const double value) override;
52 bool choose_action(const std::string& action_name) override;
53 bool play_action(const std::string& action_name) override;
54 bool show_actions() override;
55 bool set_thread_period(const double value) override;
56 bool set_initial_move_time(const double value) override;
57
58 public:
60 {
61 m_verbose=true;
62 }
63
65 {
66 for (auto it = m_robotControllers.begin(); it != m_robotControllers.end(); it++)
67 {
68 if (it->second)
69 {
70 delete it->second;
71 it->second = nullptr;
72 }
73 }
74 yInfo() << "cleanup complete";
75
76 if (m_wthread)
77 {
78 delete m_wthread;
79 m_wthread=nullptr;
80 }
81
82 if (m_bthread)
83 {
84 delete m_bthread;
85 m_bthread=nullptr;
86 }
87 }
88
89 bool chooseActionByName(std::string id)
90 {
91 if (m_actions.find(id) == m_actions.end())
92 {
93 yError() << "action id not found";
94 return false;
95 }
97
98 action_class *action = &m_actions[id];
99 std::string controller_name = action->controller_name;
100 robotDriver *driver = m_robotControllers[controller_name];
101
102 if (!driver || !action)
103 {
104 yError() << "invalid driver/action pointer";
105 return false;
106 }
107 yInfo() << "action selected:" << id;
108 yDebug() << "action controller:" << controller_name;
109 yDebug() << "number of action frames:" << action->action_frames_vector.size();
110 return m_wthread->action_change(action, driver);
111 }
112
114 {
115 std::string ss = "actions:\n";
116 size_t i = 0;
117 for (auto it=m_actions.begin(); it!=m_actions.end();it++)
118 {
119 ss = ss + "(" + std::to_string(i++) + ") " + it->second.action_name + "\n";
120 }
121 return ss;
122 }
123
124 bool loadConfiguration(std::string filename, double resample_period)
125 {
127 if (!p.fromConfigFile(filename))
128 {
129 yError() << "Unable to read configuration file!";
130 return false;
131 }
132
133 yarp::os::Bottle& bot_cont = p.findGroup("CONTROLLERS");
134 if (bot_cont.size() == 0)
135 {
136 yError() << "Unable to read CONTROLLERS section";
137 return false;
138 }
139 size_t num_of_controllers = bot_cont.size();
140 for (size_t i = 1; i < num_of_controllers; i++)
141 {
142 yDebug() << bot_cont.get(i).toString();
143 yarp::os::Bottle* bot_cont_elem = bot_cont.get(i).asList();
144 size_t num_of_celems = bot_cont_elem->size();
145 if (bot_cont_elem && num_of_celems == 3)
146 {
147 //parse a line of the controllers section
148 std::string controller_name = bot_cont_elem->get(0).toString();
149 std::string remoteControlBoards = bot_cont_elem->get(1).toString();
150 std::string axesNames = bot_cont_elem->get(2).toString();
151 robotDriver* rob = new robotDriver;
152 yarp::os::Property rmoptions;
153 rmoptions.put("remoteControlBoards", bot_cont_elem->get(1));
154 rmoptions.put("axesNames", bot_cont_elem->get(2));
155 rmoptions.put("localPortPrefix", m_name + "/controller/" + controller_name);
156
157 //configure the controller
158 bool rob_ok = true;
159 rob_ok &= rob->configure(rmoptions);
160 rob_ok &= rob->init();
161 if (!rob_ok)
162 {
163 yError() << "Unable to initialize controller" << controller_name;
164 return false;
165 }
166 //put the controller in the list
167 m_robotControllers[controller_name] = rob;
168 }
169 else
170 {
171 yError() << "Invalid entry in CONTROLLERS section";
172 return false;
173 }
174 }
175
176 yarp::os::Bottle& bot_action = p.findGroup("ACTIONS");
177 if (bot_action.size() == 0)
178 {
179 yError() << "Unable to read ACTIONS section";
180 return false;
181 }
182 for (size_t i = 1; i < bot_action.size(); i++)
183 {
184 std::string str = bot_action.toString();
185 yDebug() << bot_action.get(i).toString();
186 yarp::os::Bottle* bot_act_elem = bot_action.get(i).asList();
187 size_t num_of_aelems = bot_act_elem->size();
188 if (bot_act_elem && num_of_aelems==3)
189 {
190 //parse a line of the ACTIONS section
191 std::string action_name = bot_act_elem->get(0).toString();
192 std::string controller_name = bot_act_elem->get(1).toString();
193 std::string action_file_name = bot_act_elem->get(2).toString();
194
195 //check if the controller name exists
196 if (m_robotControllers.find(controller_name) == m_robotControllers.end())
197 {
198 yError() << controller_name << "in action" << action_name << "does not exists";
199 return false;
200 }
201
202 //load the action file
203 action_class tmpAction;
204 tmpAction.action_name = action_name;
205 tmpAction.controller_name = controller_name;
206 size_t njoints = m_robotControllers[controller_name]->getNJoints();
207
208 if (!tmpAction.openFile(action_file_name, njoints, 0.010))
209 {
210 yError() << "Unable to parse file";
211 return false;
212 }
213 if (resample_period!=0.0)
214 {
215 tmpAction.interpolate_action_frames(resample_period);
216 }
217
218 //put the action in the list
219 m_actions[action_name] = tmpAction;
220 }
221 else
222 {
223 yError() << "Invalid entry in ACTIONS section";
224 return false;
225 }
226 }
227
228 yInfo() << "configuration file successfully loaded";
229 return true;
230 }
231
233 {
234 yInfo();
235 yInfo() << "Command line:";
236 yInfo() << "yarpActionsPlayer --filename `name` [--name `module_name`] [--execute] [--period period_s] [--resample resample_period_s] [--pos_tolerance pos] [--pos_timeout pos] [--pos_strict_check enable] ";
237 yInfo();
238 yInfo() << "`name` : file containing the actions";
239 yInfo() << "`module_name` : prefix of the ports opened by the module (default: /yarpActionsPlayer)";
240 yInfo() << "`execute` : if enabled, the yarpActionsPlayer will send commands to the robot. Otherwise, only it will operate in simulation mode only";
241 yInfo() << "`pos_tolerance` : the tolerance (in degrees) that will be checked by the initial movement in position mode, before switching to positionDirect mode. Default: 2degrees";
242 yInfo() << "`pos_timeout` : the amount of time (in seconds) the robot will attempt to reach the target position within the specified position tolerance. Default: 2s";
243 yInfo() << "`pos_strict_check` : if set to true, the system will halt if home position is halted, otherwise it will continue after the timeout expires. Default: false";
244 yInfo() << "`period` : the period (in s) of the thread processing the commands. Default 0.010s";
245 yInfo() << "`resample`: all the loaded trajectory files are internally resampled at the specified period. Default: not enabled";
246 yInfo() << "`initial_move_time`: the duration (in seconds) of the initial homing position of the joints before starting the trajectory. Default: 4s";
247 yInfo();
248 }
249
251 {
252 std::string test_string = rf.toString();
253
254 // generic configuration
255 if (rf.check("name"))
256 m_name = std::string("/") + rf.find("name").asString().c_str();
257 else
258 m_name = "/yarpActionsPlayer";
259
260 // rpc port
261 m_rpcPort.open((m_name + "/rpc").c_str());
262 this->yarp().attachAsServer(m_rpcPort);
263
264 // get the configuration for parameter period
265 double period = 0.005;
266 if (rf.check("period") == true)
267 {
268 period = rf.find("period").asFloat64();
269 }
270
271 // Instantiate the thread
272 m_wthread = new ControlThread(m_name,period);
273
274 //set the configuration for parameter execute
275 if (rf.check("execute")==true)
276 {
277 yInfo() << "Enabling iPid->setReference() controller";
279 }
280 else
281 {
282 yInfo() << "Not using iPid->setReference() controller";
284 }
285
286 //set the position tolerance
287 if (rf.check("help") == true)
288 {
289 print_help();
290 return false;
291 }
292
293 if (rf.check("initial_move_time") == true)
294 {
295 double imt = rf.find("initial_move_time").asFloat64();
297 }
298
299 //set the position tolerance
300 if (rf.check("pos_tolerance") == true)
301 {
302 double tol = rf.find("tolerance").asFloat64();
303 yInfo() << "Position tolerance set to " << tol << "degrees";
305 }
306
307 //set the position timeout
308 if (rf.check("pos_timeout") == true)
309 {
310 double timeout = rf.find("pos_timeout").asFloat64();
311 yInfo() << "Position timeout set to " << timeout << "seconds";
313 }
314
315 //set the position timeout
316 if (rf.check("pos_strict_check") == true)
317 {
318 bool enable = rf.find("pos_strict_check").asBool();
320 }
321
322 double resample_period = 0;
323 if (rf.check("resample") == true)
324 {
325 resample_period = rf.find("resample_period").asFloat64();
326 yInfo() << "Set resample period equal to:" << resample_period << "s";
327 }
328
329 //open the configuration file
330 if (rf.check("filename")==true)
331 {
332 if (rf.find("filename").isString())
333 {
334 std::string filename = rf.find("filename").asString();
335 bool b = loadConfiguration(filename, resample_period);
336 if (!b)
337 {
338 yError() << "Configuration error!";
339 return false;
340 }
341 }
342 else
343 {
344 yError() << "`filename` option syntax error.";
345 print_help();
346 return false;
347 }
348 }
349 else
350 {
351 yWarning() << "`filename` option not found. No sequence files loaded.";
352 }
353
354 //check if actions are valid
355 if (m_actions.empty())
356 {
357 yInfo() << "There are no actions!";
358 return false;
359 }
360
361 //select the first action
362 yInfo() << "automatically selecting the first action";
363 std::string first_action_name;
364 first_action_name = this->m_actions.begin()->first;
365 this->chooseActionByName(first_action_name);
366
367 //start the thread
368 if (!m_wthread->start())
369 {
370 yError() << "Working thread did not start, queue will not work";
371 }
372 else
373 {
374 yInfo() << "Working thread started";
375 }
376
377 yInfo() << "module successfully configured. ready.";
378 return true;
379 }
380
381 virtual bool close()
382 {
384
385 return true;
386 }
387
388 virtual double getPeriod() { return 1.0; }
389 virtual bool updateModule() { return true; }
390};
391
392//--------------------------------------------------------------------------
393int main(int argc, char *argv[])
394{
396 rf.setDefaultContext("yarpActionsPlayer");
397 rf.configure(argc,argv);
398
400
401 if (!yarp.checkNetwork())
402 {
403 yError() << "yarp.checkNetwork() failed.";
404 return -1;
405 }
406
407 scriptModule mod;
408
409 return mod.runModule(rf);
410}
411
413{
414 return this->m_wthread->action_start();
415}
416
418{
419 return this->m_wthread->action_stop();
420}
421
423{
424 return this->m_wthread->action_reset();
425}
426
428{
429 return this->m_wthread->action_forever();
430}
431
433{
434 return this->m_wthread->action_print();
435}
436
437bool scriptModule::speed_factor(const double value)
438{
439 return this->m_wthread->action_setSpeedFactor(value);
440}
441
442bool scriptModule::resample(const double value)
443{
444 return this->m_wthread->action_resample(value);
445}
446
447bool scriptModule::choose_action(const std::string& action_name)
448{
449 return this->chooseActionByName(action_name);
450}
451
452bool scriptModule::play_action(const std::string& action_name)
453{
454 bool b = this->chooseActionByName(action_name);
455 if (b)
456 {
457 bool b1 = this->m_wthread->action_start();
458 }
459 do { yarp::os::Time::delay(0.010); }
461 return true;
462}
463
465{
466 std::string actions_str = this->string_list_actions();
467 std::string current_action_name;
468 bool b = m_wthread->action_getname(current_action_name);
469 yInfo() << "current_action: " <<current_action_name;
470 yInfo() << actions_str;
471 return true;
472}
473
474bool scriptModule::set_thread_period(const double value)
475{
476 if (value > 0)
477 {
478 m_wthread->setPeriod(value);
479 yError("invalid period value");
480 }
481 else
482 {
483 yInfo("Period set to %f", value);
484 }
485 return true;
486}
487
489{
490 if (value > 0)
491 {
493 yError("invalid initial move time");
494 }
495 else
496 {
497 yInfo("Initial move time set to %f", value);
498 }
499 return true;
500}
#define yInfo(...)
Definition Log.h:319
#define yError(...)
Definition Log.h:361
#define yDebug(...)
Definition Log.h:275
#define yWarning(...)
Definition Log.h:340
contains the definition of a Vector type
bool action_getname(std::string &name)
void setPositionStrictCheck(bool enable)
bool m_enable_execute_joint_command
void setInitialMoveTime(double t)
action_status_enum getStatus()
bool action_resample(double value)
bool action_setSpeedFactor(double factor=1)
void setPositionTolerance(double tolerance)
bool action_change(action_class *action, robotDriver *driver)
void setPositionTimeout(double timeloops)
void interpolate_action_frames(double timestep)
std::string action_name
Definition robotAction.h:48
bool openFile(std::string filename, size_t njoints, double timestep=-1)
std::string controller_name
Definition robotAction.h:49
std::deque< action_frame > action_frames_vector
Definition robotAction.h:53
bool configure(const yarp::os::Property &copt)
bool reset() override
Rewinds the currently selected action.
Definition main.cpp:422
bool speed_factor(const double value) override
Sets the playback speed factor for the currently selected action (default value: 1....
Definition main.cpp:437
bool show_actions() override
Prints all the loaded actions.
Definition main.cpp:464
std::string string_list_actions()
Definition main.cpp:113
bool loadConfiguration(std::string filename, double resample_period)
Definition main.cpp:124
void print_help()
Definition main.cpp:232
std::map< std::string, action_class > m_actions
Definition main.cpp:38
virtual bool updateModule()
Override this to do whatever your module needs to do.
Definition main.cpp:389
BroadcastingThread * m_bthread
Definition main.cpp:40
bool resample(const double value) override
Resamples the currently selected action (in seconds, recommended value 0.010s).
Definition main.cpp:442
std::string m_name
Definition main.cpp:35
bool start() override
Start (or resumes, if stopped) the currently selected action.
Definition main.cpp:412
bool m_verbose
Definition main.cpp:36
bool choose_action(const std::string &action_name) override
Choose the current action and wait for further commands.
Definition main.cpp:447
bool forever() override
Similar to play, but it will automatically restart the playback when the last frame is reached.
Definition main.cpp:427
bool set_thread_period(const double value) override
Sets the period of the sampling thread (for advanced use only, default value: 0.010s).
Definition main.cpp:474
bool print_frames() override
Prints all the frames of the currently selected action.
Definition main.cpp:432
std::string m_current_action_id
Definition main.cpp:42
~scriptModule()
Definition main.cpp:64
virtual double getPeriod()
You can override this to control the approximate periodicity at which updateModule() is called by run...
Definition main.cpp:388
yarp::os::Port m_rpcPort
Definition main.cpp:34
virtual bool configure(yarp::os::ResourceFinder &rf)
Configure the module, pass a ResourceFinder object to the module.
Definition main.cpp:250
bool stop() override
Stops the currently selected (running) action.
Definition main.cpp:417
bool play_action(const std::string &action_name) override
Play an action one single time.
Definition main.cpp:452
bool chooseActionByName(std::string id)
Definition main.cpp:89
virtual bool close()
Close function.
Definition main.cpp:381
bool set_initial_move_time(const double value) override
Sets the uration for the initial homing movement (for advanced use only, default value: 2s).
Definition main.cpp:488
scriptModule()
Definition main.cpp:59
ControlThread * m_wthread
Definition main.cpp:39
std::map< std::string, robotDriver * > m_robotControllers
Definition main.cpp:37
yarpActionsPlayer_IDL Interface.
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:65
size_type size() const
Gets the number of elements in the bottle.
Definition Bottle.cpp:257
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition Bottle.cpp:252
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition Bottle.cpp:217
Utilities for manipulating the YARP network, including initialization and shutdown.
Definition Network.h:706
bool setPeriod(double period)
Set the (new) period of the thread.
bool start()
Call this to start the thread.
A mini-server for network communication.
Definition Port.h:46
void close() override
Stop port activity.
Definition Port.cpp:330
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
Definition Port.cpp:79
A class for storing options and configuration information.
Definition Property.h:33
bool fromConfigFile(const std::string &fname, bool wipe=true)
Interprets a file as a list of properties.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition Property.cpp:987
Bottle & findGroup(const std::string &key) const override
Gets a list corresponding to a given keyword.
A base-class for standard YARP modules that supports ResourceFinder.
Definition RFModule.h:20
virtual int runModule()
Calls updateModule() until that returns false.
Definition RFModule.cpp:323
Helper class for finding config files and other external resources.
bool check(const std::string &key) const override
Check if there exists a property of the given name.
bool setDefaultContext(const std::string &contextName)
Sets the context for the current ResourceFinder object.
bool configure(int argc, char *argv[], bool skipFirstArgument=true)
Sets up the ResourceFinder.
std::string toString() const override
Return a standard text representation of the content of the object.
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
virtual yarp::conf::float64_t asFloat64() const
Get 64-bit floating point value.
Definition Value.cpp:228
virtual bool isString() const
Checks if value is a string.
Definition Value.cpp:156
virtual bool asBool() const
Get boolean value.
Definition Value.cpp:192
virtual Bottle * asList() const
Get list value.
Definition Value.cpp:252
std::string toString() const override
Return a standard text representation of the content of the object.
Definition Value.cpp:368
virtual std::string asString() const
Get string value.
Definition Value.cpp:246
yarp::os::WireLink & yarp()
Get YARP state associated with this object.
Definition Wire.h:28
int main(int argc, char *argv[])
Definition main.cpp:393
void delay(double seconds)
Wait for a certain number of seconds.
Definition Time.cpp:111
The main, catch-all namespace for YARP.
Definition dirs.h:16
@ ACTION_IDLE
Definition robotAction.h:19