icub-test
Loading...
Searching...
No Matches
Public Member Functions
OpticalEncodersDrift Class Reference

This tests checks if the relative encoders measurements are consistent over time, by performing cyclic movements between two reference positions (min and max). More...

#include <opticalEncodersDrift.h>

Inherits yarp::robottestingframework::TestCase.

Public Member Functions

virtual bool setup (yarp::os::Property &property)
 
virtual void tearDown ()
 
virtual void run ()
 
bool goHome ()
 
void setMode (int desired_mode)
 
bool saveToFile (const std::string &filename, const yarp::os::Bottle &b)
 

Detailed Description

This tests checks if the relative encoders measurements are consistent over time, by performing cyclic movements between two reference positions (min and max).

The test collects data during the joint motion, saves data to a text file a plots the result. If the relative encoder is working correctly, the plot should have no drift. Otherwise, a drift in the plot may be caused by a damaged reflective encoder/ optical disk. For best reliability an high number of cycles (e.g. >100) is suggested.

example: testRunner -v -t OpticalEncodersDrift.dll -p "--robot icub --part head --joints ""(0 1 2)"" --home ""(0 0 0)" –speed "(20 20 20)" –max "(10 10 10)" –min "(-10 -10 -10)" –cycles 100 –tolerance 1.0 " example: testRunner -v -t OpticalEncodersDrift.dll -p "–robot icub –part head –joints ""(2)"" –home ""(0)"" –speed "(20 )" –max "(10 )" –min "(-10)" –cycles 100 –tolerance 1.0 " Check the following functions: \li IMotorEncoder::getMotorEncoders() Accepts the following parameters: <table class="markdownTable"> <tr class="markdownTableHead"> <th class="markdownTableHeadCenter"> Parameter name

Type

Units

Default Value

Required

Description

Notes

robot

string

-

-

Yes

The name of the robot.

e.g. icub

part

string

-

-

Yes

The name of trhe robot part.

e.g. left_arm

joints

vector of ints

-

-

Yes

List of joints to be tested

home

vector of doubles of size joints

deg

-

Yes

The home position for each joint

cycles

int

-

-

Yes

The number of test cycles (going from max to min position and viceversa)

Use values > 100

max

vector of doubles of size joints

deg

-

Yes

The max position using during the joint movement

min

vector of doubles of size joints

deg

-

Yes

The min position using during the joint movement

tolerance

vector of doubles of size joints

deg

-

Yes

The tolerance used when moving from min to max reference position and viceversa

speed

vector of doubles of size joints

deg/s

-

Yes

The reference speed used during the movement

Definition at line 62 of file opticalEncodersDrift.h.

Constructor & Destructor Documentation

◆ OpticalEncodersDrift()

OpticalEncodersDrift::OpticalEncodersDrift ( )

Definition at line 49 of file opticalEncodersDrift.cpp.

49 : yarp::robottestingframework::TestCase("OpticalEncodersDrift") {
50 jointsList=0;
51 dd=0;
52 ipos=0;
53 icmd=0;
54 iimd=0;
55 ienc=0;
56 imot=0;
57 enc_jnt=0;
58 enc_mot=0;
59 home_enc_mot=0;
60 end_enc_mot=0;
61 err_enc_mot=0;
62 cycles=100;
63}

◆ ~OpticalEncodersDrift()

OpticalEncodersDrift::~OpticalEncodersDrift ( )
virtual

Definition at line 65 of file opticalEncodersDrift.cpp.

65{ }

Member Function Documentation

◆ goHome()

bool OpticalEncodersDrift::goHome ( )

Definition at line 190 of file opticalEncodersDrift.cpp.

191{
192 for (unsigned int i=0; i<jointsList.size(); i++)
193 {
194 ipos->setRefSpeed((int)jointsList[i],speed[i]);
195 ipos->positionMove((int)jointsList[i],home[i]);
196 }
197
198 int timeout = 0;
199 while (1)
200 {
201 int in_position=0;
202 for (unsigned int i=0; i<jointsList.size(); i++)
203 {
204 double tmp=0;
205 ienc->getEncoder((int)jointsList[i],&tmp);
206 if (fabs(tmp-home[i])<tolerance) in_position++;
207 }
208 if (in_position==jointsList.size()) break;
209 if (timeout>100)
210 {
211 ROBOTTESTINGFRAMEWORK_TEST_REPORT("Timeout while reaching home position");
212 return false;
213 }
214 yarp::os::Time::delay(0.2);
215 timeout++;
216 }
217 return true;
218}

◆ run()

void OpticalEncodersDrift::run ( )
virtual

Definition at line 243 of file opticalEncodersDrift.cpp.

244{
245 setMode(VOCAB_CM_POSITION);
246 ROBOTTESTINGFRAMEWORK_ASSERT_FAIL_IF_FALSE(goHome(), "Test can't run");
247
248 bool go_to_max=false;
249 for (unsigned int i=0; i<jointsList.size(); i++)
250 {
251 ipos->positionMove((int)jointsList[i], min[i]);
252 }
253
254 int curr_cycle=0;
255 double start_time = yarp::os::Time::now();
256 Bottle dataToPlot;
257
258 imot->getMotorEncoders (home_enc_mot.data());
259 while(1)
260 {
261 double curr_time = yarp::os::Time::now();
262 double elapsed = curr_time-start_time;
263
264 //get joint e motor encoders data for the whole robot part
265 ienc->getEncoders (enc_jnt.data());
266 imot->getMotorEncoders (enc_mot.data());
267 //extract only the joints of interest
268 yarp::sig::Vector enc_jnt_of_interest (jointsList.size());
269 yarp::sig::Vector enc_mot_of_interest (jointsList.size());
270 for (size_t i =0; i< jointsList.size(); i++)
271 {
272 enc_jnt_of_interest[i] = enc_jnt[jointsList[i]];
273 enc_mot_of_interest[i] = enc_mot[jointsList[i]];
274 }
275 //put the data into a Bottle
276 //this is the output format: n values for the motor encoders, then n values for the jnt encoders
277 Bottle& row = dataToPlot.addList();
278 Bottle& b_mot = row.addList();
279 Bottle& b_jnt = row.addList();
280 b_mot.read(enc_mot_of_interest);
281 b_jnt.read(enc_jnt_of_interest);
282
283 bool reached= false;
284 int in_position=0;
285 for (unsigned int i=0; i<jointsList.size(); i++)
286 {
287 double curr_val=0;
288 if (go_to_max==false) curr_val = min[i];
289 else curr_val = max[i];
290 if (fabs(enc_jnt[i]-curr_val)<tolerance) in_position++;
291 }
292 if (in_position==jointsList.size()) reached=true;
293
294 if (elapsed >= 20.0)
295 {
296 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Timeout while moving joint");
297 }
298
299 if (reached)
300 {
301 if (go_to_max==false)
302 {
303 for (unsigned int i=0; i<jointsList.size(); i++)
304 ipos->positionMove(i,max[i]);
305 go_to_max=true;
306 curr_cycle++;
307 start_time = yarp::os::Time::now();
308 if (curr_cycle % 10 == 0) ROBOTTESTINGFRAMEWORK_TEST_REPORT(Asserter::format("Cycle %d/%d completed", curr_cycle, cycles));
309 }
310 else
311 {
312 for (unsigned int i=0; i<jointsList.size(); i++)
313 ipos->positionMove(i,min[i]);
314 go_to_max=false;
315 curr_cycle++;
316 start_time = yarp::os::Time::now();
317 if (curr_cycle % 10 == 0) ROBOTTESTINGFRAMEWORK_TEST_REPORT(Asserter::format("Cycle %d/%d completed", curr_cycle, cycles));
318 }
319 }
320
321 if (curr_cycle>=cycles) break;
322
323 yarp::os::Time::delay(0.010);
324 }
325
326 bool isInHome = goHome();
327 yarp::os::Time::delay(2.0);
328
329 //automatic check, not complete yet
330 {
331 imot->getMotorEncoders (end_enc_mot.data());
332 for (int i=0; i<n_part_joints; i++)
333 {
334 err_enc_mot[i]=home_enc_mot[i]-end_enc_mot[i];
335
336 if (fabs(err_enc_mot[i]) > tolerance)
337 {
338 //...assert something
339 }
340 }
341 }
342
343 time_t now = time(0);
344 tm *ltm = localtime(&now);
345
346 char folder_time_buffer[80];
347 char file_time_buffer[80];
348
349 strftime(folder_time_buffer, sizeof(folder_time_buffer), "%d%m%Y", ltm);
350 strftime(file_time_buffer, sizeof(file_time_buffer), "%d%m%Y_%H%M", ltm);
351
352 string folder_time_str(folder_time_buffer);
353 string file_time_str(file_time_buffer); //This string contain also minutes
354
355 // Create the filename with date and time
356 string filename = "encDrift_plot_";
357 filename += partName;
358 filename += "_";
359 filename += file_time_str;
360 filename += ".txt";
361
362 constexpr char default_robot_name[] = "RobotName";
363
364 string robot_str = yarp::conf::environment::get_string("YARP_ROBOT_NAME", default_robot_name);
365 string directory_tree = "results/" + robot_str + "/encoders-icub_" + folder_time_str + "/encDrift";
366 create_directories(directory_tree); // This function return false if there is an error or if the directories already exist
367
368 string filename_with_path = directory_tree + "/" + filename;
369 bool saved_files = saveToFile(filename_with_path,dataToPlot);
370
371 if(!saved_files)
372 {
373 ROBOTTESTINGFRAMEWORK_TEST_REPORT("Error saving files to plot!");
374 }
375
376 char plotstring[1000];
377 sprintf (plotstring, "gnuplot -e \" unset key; plot for [col=1:%d] '%s' using col with lines \" -persist", (int)jointsList.size(),filename_with_path.c_str());
378
379 if(plot)
380 {
381 system (plotstring);
382 }
383 else
384 {
385 ROBOTTESTINGFRAMEWORK_TEST_REPORT("Test is finished. Please check if collected date are ok, by using following command: ");
386 ROBOTTESTINGFRAMEWORK_TEST_REPORT(robottestingframework::Asserter::format("%s", plotstring));
387 }
388
389 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(isInHome, "This part is not in home. Suite test will be terminated!");
390 ROBOTTESTINGFRAMEWORK_TEST_REPORT("Test is finished. Your files are saved in: \n" + filename_with_path);
391
392}

◆ saveToFile()

bool OpticalEncodersDrift::saveToFile ( const std::string &  filename,
const yarp::os::Bottle &  b 
)

Definition at line 220 of file opticalEncodersDrift.cpp.

221{
222 std::fstream fs;
223 fs.open (filename.c_str(), std::fstream::out);
224
225 if ( (fs.rdstate() & std::ifstream::failbit ) != 0 )
226 {
227 std::cerr << "Error opening " << filename << "\n";
228 return false;
229 }
230
231 for (unsigned int i=0; i<b.size(); i++)
232 {
233 std::string s = b.get(i).toString();
234 std::replace(s.begin(), s.end(), '(', ' ');
235 std::replace(s.begin(), s.end(), ')', ' ');
236 fs << s << std::endl;
237 }
238
239 fs.close();
240 return true;
241}

◆ setMode()

void OpticalEncodersDrift::setMode ( int  desired_mode)

Definition at line 158 of file opticalEncodersDrift.cpp.

159{
160 for (unsigned int i=0; i<jointsList.size(); i++)
161 {
162 icmd->setControlMode((int)jointsList[i],desired_mode);
163 iimd->setInteractionMode((int)jointsList[i],VOCAB_IM_STIFF);
164 yarp::os::Time::delay(0.010);
165 }
166
167 int cmode;
168 yarp::dev::InteractionModeEnum imode;
169 int timeout = 0;
170
171 while (1)
172 {
173 int ok=0;
174 for (unsigned int i=0; i<jointsList.size(); i++)
175 {
176 icmd->getControlMode ((int)jointsList[i],&cmode);
177 iimd->getInteractionMode((int)jointsList[i],&imode);
178 if (cmode==desired_mode && imode==VOCAB_IM_STIFF) ok++;
179 }
180 if (ok==jointsList.size()) break;
181 if (timeout>100)
182 {
183 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Unable to set control mode/interaction mode");
184 }
185 yarp::os::Time::delay(0.2);
186 timeout++;
187 }
188}

◆ setup()

bool OpticalEncodersDrift::setup ( yarp::os::Property &  property)
virtual

Definition at line 67 of file opticalEncodersDrift.cpp.

67 {
68
69 if(property.check("name"))
70 setName(property.find("name").asString());
71
72 // updating parameters
73 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("robot"), "The robot name must be given as the test parameter!");
74 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("part"), "The part name must be given as the test parameter!");
75 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("joints"), "The joints list must be given as the test parameter!");
76 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("home"), "The home position must be given as the test parameter!");
77 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("max"), "The max position must be given as the test parameter!");
78 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("min"), "The min position must be given as the test parameter!");
79 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("speed"), "The positionMove reference speed must be given as the test parameter!");
80 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("cycles"), "The number of cycles of the control signal must be given as the test parameter!");
81 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("tolerance"), "The max error tolerance must be given as the test parameter!");
82
83 robotName = property.find("robot").asString();
84
85 partName = property.find("part").asString();
86
87 Bottle* jointsBottle = property.find("joints").asList();
88 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(jointsBottle!=0,"unable to parse joints parameter");
89
90 Bottle* homeBottle = property.find("home").asList();
91 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(homeBottle!=0,"unable to parse zero parameter");
92
93 Bottle* maxBottle = property.find("max").asList();
94 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(maxBottle!=0,"unable to parse max parameter");
95
96 Bottle* minBottle = property.find("min").asList();
97 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(minBottle!=0,"unable to parse min parameter");
98
99 Bottle* speedBottle = property.find("speed").asList();
100 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(speedBottle!=0,"unable to parse speed parameter");
101
102 tolerance = property.find("tolerance").asFloat64();
103 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(tolerance>=0,"invalid tolerance");
104
105 cycles = property.find("cycles").asInt32();
106 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(cycles>=0,"invalid cycles");
107
108 plot = property.find("plot_enabled").asBool();
109
110 if(plot)
111 ROBOTTESTINGFRAMEWORK_TEST_REPORT("This test will run gnuplot utility at the end.");
112 else
113 ROBOTTESTINGFRAMEWORK_TEST_REPORT("This test will NOT run gnuplot utility at the end.");
114
115
116
117 Property options;
118 options.put("device", "remote_controlboard");
119 options.put("remote", "/"+robotName+"/"+partName);
120 options.put("local", "/opticalEncodersDrift/"+robotName+"/"+partName);
121
122 dd = new PolyDriver(options);
123 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->isValid(),"Unable to open device driver");
124 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ienc),"Unable to open encoders interface");
125 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ipos),"Unable to open position interface");
126 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(icmd),"Unable to open control mode interface");
127 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(iimd),"Unable to open interaction mode interface");
128 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(imot),"Unable to open motor encoders interface");
129
130 if (!ienc->getAxes(&n_part_joints))
131 {
132 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("unable to get the number of joints of the part");
133 }
134
135 int n_cmd_joints = jointsBottle->size();
136 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(n_cmd_joints>0 && n_cmd_joints<=n_part_joints,"invalid number of joints, it must be >0 & <= number of part joints");
137 for (int i=0; i <n_cmd_joints; i++) jointsList.push_back(jointsBottle->get(i).asInt32());
138
139 enc_jnt.resize(n_part_joints);
140 enc_mot.resize(n_part_joints);
141 home_enc_mot.resize(n_part_joints);
142 end_enc_mot.resize(n_part_joints);
143 err_enc_mot.resize(n_part_joints);
144
145 max.resize (n_cmd_joints); for (int i=0; i< n_cmd_joints; i++) max[i]=maxBottle->get(i).asFloat64();
146 min.resize (n_cmd_joints); for (int i=0; i< n_cmd_joints; i++) min[i]=minBottle->get(i).asFloat64();
147 home.resize (n_cmd_joints); for (int i=0; i< n_cmd_joints; i++) home[i]=homeBottle->get(i).asFloat64();
148 speed.resize(n_cmd_joints); for (int i=0; i< n_cmd_joints; i++) speed[i]=speedBottle->get(i).asFloat64();
149
150 return true;
151}

◆ tearDown()

void OpticalEncodersDrift::tearDown ( )
virtual

Definition at line 153 of file opticalEncodersDrift.cpp.

154{
155 if (dd) {delete dd; dd =0;}
156}

The documentation for this class was generated from the following files: