YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
controlBoardRemapper_t1_test.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
6#include <yarp/os/Time.h>
11
12#include <vector>
13
14#include <catch2/catch_amalgamated.hpp>
15#include <harness.h>
16
17using namespace yarp::os;
18using namespace yarp::dev;
19
20const char *fmcA_file_content = "device fakeMotionControl\n"
21 "[GENERAL]\n"
22 "Joints 2\n"
23 "\n"
24 "AxisName (\"axisA1\" \"axisA2\") \n";
25
26const char *fmcB_file_content = "device fakeMotionControl\n"
27 "[GENERAL]\n"
28 "Joints 3\n"
29 "\n"
30 "AxisName (\"axisB1\" \"axisB2\" \"axisB3\") \n";
31
32const char *fmcC_file_content = "device fakeMotionControl\n"
33 "[GENERAL]\n"
34 "Joints 4\n"
35 "\n"
36 "AxisName (\"axisC1\" \"axisC2\" \"axisC3\" \"axisC4\") \n";
37
38const char *fmcA_file_content_micro = "device fakeMotionControlMicro\n"
39 "[GENERAL]\n"
40 "Joints 2\n"
41 "\n"
42 "AxisName (\"axisA1\" \"axisA2\") \n";
43
44const char *fmcB_file_content_micro = "device fakeMotionControlMicro\n"
45 "[GENERAL]\n"
46 "Joints 3\n"
47 "\n"
48 "AxisName (\"axisB1\" \"axisB2\" \"axisB3\") \n";
49
50const char *fmcC_file_content_micro = "device fakeMotionControlMicro\n"
51 "[GENERAL]\n"
52 "Joints 4\n"
53 "\n"
54 "AxisName (\"axisC1\" \"axisC2\" \"axisC3\" \"axisC4\") \n";
55
56const char *wrapperA_file_content = "device controlBoard_nws_yarp\n"
57 "name /testRemapperRobot/a\n"
58 "period 0.01\n";
59
60const char *wrapperB_file_content = "device controlBoard_nws_yarp\n"
61 "name /testRemapperRobot/b\n"
62 "period 0.01\n";
63
64const char *wrapperC_file_content = "device controlBoard_nws_yarp\n"
65 "name /testRemapperRobot/c\n"
66 "period 0.01\n";
67
68
70{
71 IPositionControl *pos = nullptr;
72 REQUIRE(ddRemapper.view(pos)); // interface position correctly opened
73 REQUIRE(pos);
74
75 int axes = 0;
76 CHECK(pos->getAxes(&axes)); // getAxes returned correctly
77 CHECK((size_t) axes == nrOfRemappedAxes); // remapper seems functional
78
79 IPositionDirect *posdir = nullptr;
80 REQUIRE(ddRemapper.view(posdir)); // direct position interface correctly opened
82
83 IEncoders * encs = nullptr;
84 REQUIRE(ddRemapper.view(encs)); // encoders interface correctly opened
85 REQUIRE(encs);
86
87 IControlMode *ctrlmode = nullptr;
88 REQUIRE(ddRemapper.view(ctrlmode)); // control mode interface correctly opened
90
91 // Vector used for setting/getting data from the controlboard
92 std::vector<double> setPosition(nrOfRemappedAxes,-10),
93 setRefSpeeds(nrOfRemappedAxes,-15),
96
97 for(size_t i=0; i < nrOfRemappedAxes; i++)
98 {
99 setPosition[i] = i*100.0+50.0 + rand;
100 setRefSpeeds[i] = i*10.0+5 + rand;
101 readedPosition[i] = -100 + rand;
102 }
103
104 // Set the control mode in position direct
107
108 CHECK(ctrlmode->setControlModes(settedControlMode.data())); // setControlModes correctly called
109
110 // Check that the read control mode is actually position direct
111 // Let's try 10 times because if the remapper is using some remotecontrolboards,
112 // it is possible that this return false if it is called before the first message
113 // has been received from the controlboard_nws_yarp
114 bool getControlModesOk = false;
115 for(int wait=0; wait < 20 && !getControlModesOk; wait++)
116 {
117 getControlModesOk = ctrlmode->getControlModes(readedControlMode.data());
119 }
120 CHECK(getControlModesOk); // getControlModes correctly called
121
122 for(size_t i=0; i < nrOfRemappedAxes; i++)
123 {
124 CHECK(settedControlMode[i] == readedControlMode[i]); // Setted control mode and readed control mode match
125 }
126
127 // Test position direct methods
128
129 // Set position
130 CHECK(posdir->setPositions(setPosition.data())); // setPositions correctly called
131
132 // Set also the speeds in the mean time, so we are sure that we don't get
133 // spurios successful set/get of position because of intermediate buffers
134 CHECK(pos->setRefSpeeds(setRefSpeeds.data())); // setRefSpeeds correctly called
135
136 // Wait some time to make sure that the vector has been correctly propagated
137 // back and forth
139
140 // Read position
141 CHECK(posdir->getRefPositions(readedPosition.data())); // getRefPositions correctly called
142
143 // Check that the two vector match
144 for(size_t i=0; i < nrOfRemappedAxes; i++)
145 {
146 CHECK(setPosition[i] == readedPosition[i]); // Setted position and readed ref position match
147 }
148
149 // Do a similar test for the encoders
150 // in fakeMotionControl their value is the one setted with setPosition
151 CHECK(encs->getEncoders(readedEncoders.data())); // getEncoders correctly called
152
153 // Check that the two vector match
154 for(size_t i=0; i < nrOfRemappedAxes; i++)
155 {
156 CHECK(setPosition[i] == readedEncoders[i]); // Setted position and readed encoders match
157 }
158}
159
160
162{
163 IPositionControl *pos = nullptr;
164 REQUIRE(ddRemapper.view(pos)); // interface position correctly opened
165 REQUIRE(pos);
166
167 int axes = 0;
168 CHECK(pos->getAxes(&axes)); // getAxes returned correctly
169 CHECK((size_t) axes == nrOfRemappedAxes); // remapper seems functional
170
171 IPositionDirect *posdir = nullptr;
172 REQUIRE(ddRemapper.view(posdir)); // direct position interface correctly opened
174
175 IEncoders * encs = nullptr;
176 REQUIRE(ddRemapper.view(encs)); // encoders interface correctly opened
177 REQUIRE(encs);
178
179 IControlMode *ctrlmode = nullptr;
180 REQUIRE(ddRemapper.view(ctrlmode)); // control mode interface correctly opened
182
183 // Vector used for setting/getting data from the controlboard
184 std::vector<double> setPosition(nrOfRemappedAxes,-10),
185 setRefSpeeds(nrOfRemappedAxes,-15),
188
189 for(size_t i=0; i < nrOfRemappedAxes; i++)
190 {
191 setPosition[i] = i*100.0+50.0 + rand;
192 setRefSpeeds[i] = i*10.0+5 + rand;
193 readedPosition[i] = -100 + rand;
194 }
195
196 // Set the control mode in position direct
199
200 CHECK_FALSE(ctrlmode->setControlModes(settedControlMode.data()));
201
202 // Check that the read control mode is actually position direct
203 // Let's try 10 times because if the remapper is using some remotecontrolboards,
204 // it is possible that this return false if it is called before the first message
205 // has been received from the controlboard_nws_yarp
206 bool getControlModesOk = false;
207 for(int wait=0; wait < 20 && !getControlModesOk; wait++)
208 {
209 getControlModesOk = ctrlmode->getControlModes(readedControlMode.data());
211 }
213
214 // Test position direct methods
215
216 // Set also the speeds in the mean time, so we are sure that we don't get
217 // spurios successful set/get of position because of intermediate buffers
218 CHECK_FALSE(pos->setRefSpeeds(setRefSpeeds.data()));
219
220 // Wait some time to make sure that the vector has been correctly propagated
221 // back and forth
223
224 // Read position
225 CHECK_FALSE(posdir->getRefPositions(readedPosition.data()));
226
227 // Do a similar test for the encoders
228 // in fakeMotionControl their value is the one setted with setPosition
229 CHECK(encs->getEncoders(readedEncoders.data())); // getEncoders correctly called
230}
231
232
233TEST_CASE("dev::ControlBoardRemapperTest", "[yarp::dev]")
234{
235 YARP_REQUIRE_PLUGIN("fakeMotionControl", "device");
236 YARP_REQUIRE_PLUGIN("fakeMotionControlMicro", "device");
237 YARP_REQUIRE_PLUGIN("controlboardremapper", "device");
238 YARP_REQUIRE_PLUGIN("controlBoard_nws_yarp", "device");
239 YARP_REQUIRE_PLUGIN("remotecontrolboardremapper", "device");
240
241 Network::setLocalMode(true);
242
243 SECTION("Test the controlboard remapper")
244 {
245 // We first allocate three fakeMotionControl boards
246 // and their wrappers that we will remap using the remapper
247 std::vector<PolyDriver *> fmcbs;
248 std::vector<PolyDriver *> wrappers;
249 fmcbs.resize(3);
250 wrappers.resize(3);
251
252 std::vector<int> fmcbsSizes;
253 fmcbsSizes.push_back(2);
254 fmcbsSizes.push_back(3);
255 fmcbsSizes.push_back(4);
256
257 std::vector<std::string> fmcbsNames;
258 fmcbsNames.push_back("fakeControlBoardA");
259 fmcbsNames.push_back("fakeControlBoardB");
260 fmcbsNames.push_back("fakeControlBoardC");
261
262 std::vector<std::string> wrapperNetworks;
263 wrapperNetworks.push_back("net_a");
264 wrapperNetworks.push_back("net_b");
265 wrapperNetworks.push_back("net_c");
266
267
268 for(int i=0; i < 3; i++)
269 {
270 fmcbs[i] = new PolyDriver();
271
272 Property p;
273
274 if(i==0) { p.fromConfig(fmcA_file_content); }
275 if(i==1) { p.fromConfig(fmcB_file_content); }
276 if(i==2) { p.fromConfig(fmcC_file_content); }
277
278 REQUIRE(fmcbs[i]->open(p)); // fakeMotionControlBoard open reported successful
279
280 IPositionControl *pos = nullptr;
281 REQUIRE(fmcbs[i]->view(pos)); // interface position correctly opened
282 REQUIRE(pos);
283
284 int axes = 0;
285 pos->getAxes(&axes);
286 CHECK(axes == fmcbsSizes[i]); // fakeMotionControlBoard seems functional
287
288 // Open the wrapper
289 wrappers[i] = new PolyDriver();
290
291 if(i==0) { p.fromConfig(wrapperA_file_content); }
292 if(i==1) { p.fromConfig(wrapperB_file_content); }
293 if(i==2) { p.fromConfig(wrapperC_file_content); }
294
295 REQUIRE(wrappers[i]->open(p)); // controlBoard_nws_yarp open reported successful
296
298 REQUIRE(wrappers[i]->view(iwrap)); // interface for multiple wrapper correctly opened for the controlBoard_nws_yarp
299 REQUIRE(iwrap);
300
302 pdList.push(fmcbs[i],wrapperNetworks[i].c_str());
303
304 REQUIRE(iwrap->attachAll(pdList)); // controlBoard_nws_yarp attached successfully to the device
305 }
306
307 // Create a list containing all the fake controlboards
309
310 for(int i=0; i < 3; i++)
311 {
312 fmcList.push(fmcbs[i],fmcbsNames[i].c_str());
313 }
314
315 // Open a controlboardremapper with the wrong axisName,
316 // and make sure that if fails during attachAll
319 pRemapperWN.put("device","controlboardremapper");
320 pRemapperWN.addGroup("axesNames");
321 Bottle & axesListWN = pRemapperWN.findGroup("axesNames").addList();
322 axesListWN.addString("axisA1");
323 axesListWN.addString("axisB1");
324 axesListWN.addString("axisC1");
325 axesListWN.addString("axisB3");
326 axesListWN.addString("axisC3");
327 axesListWN.addString("axisA2");
328 axesListWN.addString("thisIsAnAxisNameThatDoNotExist");
329
330 REQUIRE(ddRemapperWN.open(pRemapperWN)); // controlboardremapper with wrong names open reported successful
331
333 REQUIRE(ddRemapperWN.view(imultwrapWN)); // interface for multiple wrapper with wrong names correctly opened
335
336 REQUIRE_FALSE(imultwrapWN->attachAll(fmcList)); // attachAll for controlboardremapper with wrong names successful
337
338 // Make sure that a controlboard in which attachAll is not successfull
339 // closes correctly
340 CHECK(ddRemapperWN.close()); // controlboardremapper with wrong names close was successful
341
342 // Open the controlboardremapper
345 pRemapper.put("device","controlboardremapper");
346 pRemapper.addGroup("axesNames");
347 Bottle & axesList = pRemapper.findGroup("axesNames").addList();
348 axesList.addString("axisA1");
349 axesList.addString("axisB1");
350 axesList.addString("axisC1");
351 axesList.addString("axisB3");
352 axesList.addString("axisC3");
353 axesList.addString("axisA2");
354 size_t nrOfRemappedAxes = 6;
355
356 REQUIRE(ddRemapper.open(pRemapper)); // controlboardremapper open reported successful
357
359 REQUIRE(ddRemapper.view(imultwrap)); // interface for multiple wrapper correctly opened
361
362 REQUIRE(imultwrap->attachAll(fmcList)); // attachAll for controlboardremapper successful
363
364
365 // Test the controlboardremapper
367
368 // Open the remotecontrolboardremapper
371 pRemoteRemapper.put("device","remotecontrolboardremapper");
372 pRemoteRemapper.addGroup("axesNames");
373 Bottle & remoteAxesList = pRemoteRemapper.findGroup("axesNames").addList();
374 remoteAxesList.addString("axisA1");
375 remoteAxesList.addString("axisB1");
376 remoteAxesList.addString("axisC1");
377 remoteAxesList.addString("axisB3");
378 remoteAxesList.addString("axisC3");
379 remoteAxesList.addString("axisA2");
380
383 remoteControlBoardsList.addString("/testRemapperRobot/a");
384 remoteControlBoardsList.addString("/testRemapperRobot/b");
385 remoteControlBoardsList.addString("/testRemapperRobot/c");
386 pRemoteRemapper.put("remoteControlBoards",remoteControlBoards.get(0));
387
388 pRemoteRemapper.put("localPortPrefix","/test/remoteControlBoardRemapper");
389
390 Property & opts = pRemoteRemapper.addGroup("REMOTE_CONTROLBOARD_OPTIONS");
391 opts.put("writeStrict","on");
392
393 REQUIRE(ddRemoteRemapper.open(pRemoteRemapper)); // remotecontrolboardremapper open reported successful, testing it
394
395 // Test the remotecontrolboardremapper
397
398 // Close devices
399 imultwrap->detachAll();
402
403 for(int i=0; i < 3; i++)
404 {
405 wrappers[i]->close();
406 delete wrappers[i];
407 wrappers[i] = nullptr;
408 fmcbs[i]->close();
409 delete fmcbs[i];
410 fmcbs[i] = nullptr;
411 }
412 }
413
414 SECTION("Test the controlboard remapper micro")
415 {
416 // We first allocate three fakeMotionControl boards
417 // and their wrappers that we will remap using the remapper
418 std::vector<PolyDriver *> fmcbs;
419 std::vector<PolyDriver *> wrappers;
420 fmcbs.resize(3);
421 wrappers.resize(3);
422
423 std::vector<int> fmcbsSizes;
424 fmcbsSizes.push_back(2);
425 fmcbsSizes.push_back(3);
426 fmcbsSizes.push_back(4);
427
428 std::vector<std::string> fmcbsNames;
429 fmcbsNames.push_back("fakeControlBoardAMicro");
430 fmcbsNames.push_back("fakeControlBoardBMicro");
431 fmcbsNames.push_back("fakeControlBoardCMicro");
432
433 std::vector<std::string> wrapperNetworks;
434 wrapperNetworks.push_back("net_a");
435 wrapperNetworks.push_back("net_b");
436 wrapperNetworks.push_back("net_c");
437
438
439 for(int i=0; i < 3; i++)
440 {
441 fmcbs[i] = new PolyDriver();
442
443 Property p;
444
445 if(i==0) { p.fromConfig(fmcA_file_content_micro); }
446 if(i==1) { p.fromConfig(fmcB_file_content_micro); }
447 if(i==2) { p.fromConfig(fmcC_file_content_micro); }
448
449 REQUIRE(fmcbs[i]->open(p)); // fakeMotionControlBoard open reported successful
450
451 IPositionControl *pos = nullptr;
452 REQUIRE_FALSE(fmcbs[i]->view(pos)); // interface position correctly not opened
453 REQUIRE_FALSE(pos);
454
455 int axes = 0;
456
457 IAxisInfoRaw *axisInfo = nullptr;
458 REQUIRE(fmcbs[i]->view(axisInfo)); // interface axisInfo correctly opened
460 axisInfo->getAxes(&axes);
461 CHECK(axes == fmcbsSizes[i]); // fakeMotionControlBoard seems functional
462
463 // Open the wrapper
464 wrappers[i] = new PolyDriver();
465
466 if(i==0) { p.fromConfig(wrapperA_file_content); }
467 if(i==1) { p.fromConfig(wrapperB_file_content); }
468 if(i==2) { p.fromConfig(wrapperC_file_content); }
469
470 REQUIRE(wrappers[i]->open(p)); // controlBoard_nws_yarp open reported successful
471
473 REQUIRE(wrappers[i]->view(iwrap)); // interface for multiple wrapper correctly opened for the controlBoard_nws_yarp
474 REQUIRE(iwrap);
475
477 pdList.push(fmcbs[i],wrapperNetworks[i].c_str());
478
479 REQUIRE(iwrap->attachAll(pdList)); // controlBoard_nws_yarp attached successfully to the device
480 }
481
482 // Create a list containing all the fake controlboards
484
485 for(int i=0; i < 3; i++)
486 {
487 fmcList.push(fmcbs[i],fmcbsNames[i].c_str());
488 }
489
490 // Open a controlboardremapper with the wrong axisName,
491 // and make sure that if fails during attachAll
494 pRemapperWN.put("device","controlboardremapper");
495 pRemapperWN.addGroup("axesNames");
496 Bottle & axesListWN = pRemapperWN.findGroup("axesNames").addList();
497 axesListWN.addString("axisA1");
498 axesListWN.addString("axisB1");
499 axesListWN.addString("axisC1");
500 axesListWN.addString("axisB3");
501 axesListWN.addString("axisC3");
502 axesListWN.addString("axisA2");
503 axesListWN.addString("thisIsAnAxisNameThatDoNotExist");
504
505 REQUIRE(ddRemapperWN.open(pRemapperWN)); // controlboardremapper with wrong names open reported successful
506
508 REQUIRE(ddRemapperWN.view(imultwrapWN)); // interface for multiple wrapper with wrong names correctly opened
510
511 REQUIRE_FALSE(imultwrapWN->attachAll(fmcList)); // attachAll for controlboardremapper with wrong names successful
512
513 // Make sure that a controlboard in which attachAll is not successfull
514 // closes correctly
515 CHECK(ddRemapperWN.close()); // controlboardremapper with wrong names close was successful
516
517 // Open the controlboardremapper
520 pRemapper.put("device","controlboardremapper");
521 pRemapper.addGroup("axesNames");
522 Bottle & axesList = pRemapper.findGroup("axesNames").addList();
523 axesList.addString("axisA1");
524 axesList.addString("axisB1");
525 axesList.addString("axisC1");
526 axesList.addString("axisB3");
527 axesList.addString("axisC3");
528 axesList.addString("axisA2");
529 size_t nrOfRemappedAxes = 6;
530
531 REQUIRE(ddRemapper.open(pRemapper)); // controlboardremapper open reported successful
532
534 REQUIRE(ddRemapper.view(imultwrap)); // interface for multiple wrapper correctly opened
536
537 REQUIRE(imultwrap->attachAll(fmcList)); // attachAll for controlboardremapper successful
538
539
540 // Test the controlboardremapper
542
543 // Open the remotecontrolboardremapper
546 pRemoteRemapper.put("device","remotecontrolboardremapper");
547 pRemoteRemapper.addGroup("axesNames");
548 Bottle & remoteAxesList = pRemoteRemapper.findGroup("axesNames").addList();
549 remoteAxesList.addString("axisA1");
550 remoteAxesList.addString("axisB1");
551 remoteAxesList.addString("axisC1");
552 remoteAxesList.addString("axisB3");
553 remoteAxesList.addString("axisC3");
554 remoteAxesList.addString("axisA2");
555
558 remoteControlBoardsList.addString("/testRemapperRobot/a");
559 remoteControlBoardsList.addString("/testRemapperRobot/b");
560 remoteControlBoardsList.addString("/testRemapperRobot/c");
561 pRemoteRemapper.put("remoteControlBoards",remoteControlBoards.get(0));
562
563 pRemoteRemapper.put("localPortPrefix","/test/remoteControlBoardRemapper");
564
565 Property & opts = pRemoteRemapper.addGroup("REMOTE_CONTROLBOARD_OPTIONS");
566 opts.put("writeStrict","on");
567
568 REQUIRE(ddRemoteRemapper.open(pRemoteRemapper)); // remotecontrolboardremapper open reported successful, testing it
569
570 // Test the remotecontrolboardremapper
572
573 // Close devices
574 imultwrap->detachAll();
577
578 for(int i=0; i < 3; i++)
579 {
580 wrappers[i]->close();
581 delete wrappers[i];
582 wrappers[i] = nullptr;
583 fmcbs[i]->close();
584 delete fmcbs[i];
585 fmcbs[i] = nullptr;
586 }
587 }
588
589 Network::setLocalMode(false);
590}
define control board standard interfaces
constexpr yarp::conf::vocab32_t VOCAB_CM_POSITION
constexpr yarp::conf::vocab32_t VOCAB_CM_POSITION_DIRECT
Interface for getting information about specific axes, if available.
Definition IAxisInfo.h:72
Interface for setting control mode in control board.
Control board, encoder interface.
Definition IEncoders.h:116
virtual bool getEncoders(double *encs)=0
Read the position of all axes.
Interface for an object that can wrap/attach to to another.
Interface for a generic control board device implementing position control.
virtual bool getAxes(int *ax)=0
Get the number of controlled axes.
virtual bool setRefSpeeds(const double *spds)=0
Set reference speed on all joints.
Interface for a generic control board device implementing position control.
A container for a device driver.
Definition PolyDriver.h:23
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:65
A mini-server for performing network communication in the background.
void close() override
Stop port activity.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
A class for storing options and configuration information.
Definition Property.h:33
void fromConfig(const char *txt, bool wipe=true)
Parses text in the configuration format described in fromConfigFile().
const char * wrapperC_file_content
static void checkRemapperMicro(yarp::dev::PolyDriver &ddRemapper, int rand, size_t nrOfRemappedAxes)
TEST_CASE("dev::ControlBoardRemapperTest", "[yarp::dev]")
const char * fmcA_file_content_micro
const char * fmcA_file_content
const char * fmcB_file_content_micro
const char * fmcB_file_content
const char * fmcC_file_content_micro
const char * fmcC_file_content
static void checkRemapper(yarp::dev::PolyDriver &ddRemapper, int rand, size_t nrOfRemappedAxes)
const char * wrapperA_file_content
const char * wrapperB_file_content
For streams capable of holding different kinds of content, check what they actually have.
void delay(double seconds)
Wait for a certain number of seconds.
Definition Time.cpp:111
An interface to the operating system, including Port based communication.