23 #include <robottestingframework/TestAssert.h>
24 #include <robottestingframework/dll/Plugin.h>
25 #include <yarp/os/Time.h>
26 #include <yarp/math/Math.h>
27 #include <yarp/os/Property.h>
28 #include <yarp/conf/environment.h>
32 #include "opticalEncodersDrift.h"
39 using namespace robottestingframework;
40 using namespace yarp::os;
41 using namespace yarp::dev;
42 using namespace yarp::math;
44 using namespace std::filesystem;
49 OpticalEncodersDrift::OpticalEncodersDrift() : yarp::robottestingframework::TestCase(
"OpticalEncodersDrift") {
65 OpticalEncodersDrift::~OpticalEncodersDrift() { }
67 bool OpticalEncodersDrift::setup(yarp::os::Property& property) {
69 if(property.check(
"name"))
70 setName(property.find(
"name").asString());
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!");
83 robotName =
property.find(
"robot").asString();
85 partName =
property.find(
"part").asString();
87 Bottle* jointsBottle =
property.find(
"joints").asList();
88 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(jointsBottle!=0,
"unable to parse joints parameter");
90 Bottle* homeBottle =
property.find(
"home").asList();
91 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(homeBottle!=0,
"unable to parse zero parameter");
93 Bottle* maxBottle =
property.find(
"max").asList();
94 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(maxBottle!=0,
"unable to parse max parameter");
96 Bottle* minBottle =
property.find(
"min").asList();
97 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(minBottle!=0,
"unable to parse min parameter");
99 Bottle* speedBottle =
property.find(
"speed").asList();
100 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(speedBottle!=0,
"unable to parse speed parameter");
102 tolerance =
property.find(
"tolerance").asFloat64();
103 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(tolerance>=0,
"invalid tolerance");
105 cycles =
property.find(
"cycles").asInt32();
106 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(cycles>=0,
"invalid cycles");
108 plot =
property.find(
"plot_enabled").asBool();
111 ROBOTTESTINGFRAMEWORK_TEST_REPORT(
"This test will run gnuplot utility at the end.");
113 ROBOTTESTINGFRAMEWORK_TEST_REPORT(
"This test will NOT run gnuplot utility at the end.");
118 options.put(
"device",
"remote_controlboard");
119 options.put(
"remote",
"/"+robotName+
"/"+partName);
120 options.put(
"local",
"/opticalEncodersDrift/"+robotName+
"/"+partName);
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");
130 if (!ienc->getAxes(&n_part_joints))
132 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(
"unable to get the number of joints of the part");
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());
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);
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();
153 void OpticalEncodersDrift::tearDown()
155 if (dd) {delete dd; dd =0;}
158 void OpticalEncodersDrift::setMode(int desired_mode)
160 for (unsigned int i=0; i<jointsList.size(); i++)
162 icmd->setControlMode((int)jointsList[i],desired_mode);
163 iimd->setInteractionMode((int)jointsList[i],VOCAB_IM_STIFF);
164 yarp::os::Time::delay(0.010);
168 yarp::dev::InteractionModeEnum imode;
174 for (unsigned int i=0; i<jointsList.size(); i++)
176 icmd->getControlMode ((int)jointsList[i],&cmode);
177 iimd->getInteractionMode((int)jointsList[i],&imode);
178 if (cmode==desired_mode && imode==VOCAB_IM_STIFF) ok++;
180 if (ok==jointsList.size()) break;
183 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Unable to set control mode/interaction mode
");
185 yarp::os::Time::delay(0.2);
190 bool OpticalEncodersDrift::goHome()
192 for (unsigned int i=0; i<jointsList.size(); i++)
194 ipos->setRefSpeed((int)jointsList[i],speed[i]);
195 ipos->positionMove((int)jointsList[i],home[i]);
202 for (unsigned int i=0; i<jointsList.size(); i++)
205 ienc->getEncoder((int)jointsList[i],&tmp);
206 if (fabs(tmp-home[i])<tolerance) in_position++;
208 if (in_position==jointsList.size()) break;
211 ROBOTTESTINGFRAMEWORK_TEST_REPORT("Timeout
while reaching home position
");
214 yarp::os::Time::delay(0.2);
220 bool OpticalEncodersDrift::saveToFile(const std::string &filename, const yarp::os::Bottle &b)
223 fs.open (filename.c_str(), std::fstream::out);
225 if ( (fs.rdstate() & std::ifstream::failbit ) != 0 )
227 std::cerr << "Error opening
" << filename << "\n
";
231 for (unsigned int i=0; i<b.size(); i++)
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;
243 void OpticalEncodersDrift::run()
245 setMode(VOCAB_CM_POSITION);
246 ROBOTTESTINGFRAMEWORK_ASSERT_FAIL_IF_FALSE(goHome(), "Test can
't run");
248 bool go_to_max=false;
249 for (unsigned int i=0; i<jointsList.size(); i++)
251 ipos->positionMove((int)jointsList[i], min[i]);
255 double start_time = yarp::os::Time::now();
258 imot->getMotorEncoders (home_enc_mot.data());
261 double curr_time = yarp::os::Time::now();
262 double elapsed = curr_time-start_time;
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++)
272 enc_jnt_of_interest[i] = enc_jnt[jointsList[i]];
273 enc_mot_of_interest[i] = enc_mot[jointsList[i]];
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);
285 for (unsigned int i=0; i<jointsList.size(); i++)
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++;
292 if (in_position==jointsList.size()) reached=true;
296 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Timeout while moving joint");
301 if (go_to_max==false)
303 for (unsigned int i=0; i<jointsList.size(); i++)
304 ipos->positionMove(i,max[i]);
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));
312 for (unsigned int i=0; i<jointsList.size(); i++)
313 ipos->positionMove(i,min[i]);
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));
321 if (curr_cycle>=cycles) break;
323 yarp::os::Time::delay(0.010);
326 bool isInHome = goHome();
327 yarp::os::Time::delay(2.0);
329 //automatic check, not complete yet
331 imot->getMotorEncoders (end_enc_mot.data());
332 for (int i=0; i<n_part_joints; i++)
334 err_enc_mot[i]=home_enc_mot[i]-end_enc_mot[i];
336 if (fabs(err_enc_mot[i]) > tolerance)
338 //...assert something
343 time_t now = time(0);
344 tm *ltm = localtime(&now);
346 char folder_time_buffer[80];
347 char file_time_buffer[80];
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);
352 string folder_time_str(folder_time_buffer);
353 string file_time_str(file_time_buffer); //This string contain also minutes
355 // Create the filename with date and time
356 string filename = "encDrift_plot_";
357 filename += partName;
359 filename += file_time_str;
362 constexpr char default_robot_name[] = "RobotName";
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
368 string filename_with_path = directory_tree + "/" + filename;
369 bool saved_files = saveToFile(filename_with_path,dataToPlot);
373 ROBOTTESTINGFRAMEWORK_TEST_REPORT("Error saving files to plot!");
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());
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));
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);
This tests checks if the relative encoders measurements are consistent over time, by performing cycli...