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

Check if the software joint limits are properly set. More...

#include <jointLimits.h>

Inherits yarp::robottestingframework::TestCase.

Public Member Functions

virtual bool setup (yarp::os::Property &property)
 
virtual void tearDown ()
 
virtual void run ()
 
void goTo (yarp::sig::Vector position)
 
bool goToSingle (int i, double pos, double *reached_pos)
 
bool goToSingleExceed (int i, double position_to_reach, double limit, double reachedLimit, double *reached_pos)
 
void setMode (int desired_mode)
 
void saveToFile (std::string filename, yarp::os::Bottle &b)
 

Detailed Description

Check if the software joint limits are properly set.

The limits are set in the robot configuration files. The test asks the limits to robotInterface using the IControlLimits interface. The test moves each joint first to the max lim, then to the min lim, then to home. If the joint is unable to reach the software limits within a certain tolerance, the test fails and the joint is put back in home position. The timeout for each joint to reach the limit position is fixed to 20 seconds. The test uses an limited output to avoid to damage the joint if, for example, an hardware limit is reached before the software limit. If this limit is too small, the the joint may be unable to reach the limit (e.g. because of friction), so the value must be chosen accurately. The test assumes the the position control is properly working and the position pid is properly tuned. After testing the limits, this test also tries to move the joint out of the limits on puropose (adding to the joint limits the value of outOfBoundPosition). The test is successfull if the position move command is correctly stopped at the limit.

Example: testRunner -v -t JointLimits.dll -p "--robot icub --part head --joints ""(0 1 2)"" --home ""(0 0 0)"" --speed ""(20 20 20)"" --outputLimitPercent ""(30 30 30)"" --outOfBoundPosition ""(2 2 2)"" --tolerance 0.2"

Check the following functions:

Support functions:

Accepts the following parameters:

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
speed vector of doubles of size joints deg/s - Yes The reference speed used furing the movement
tolerance vector of doubles of size joints deg - Yes The position tolerance used to check if the limit has been properly reached. Typical value = 0.2 deg.
outputLimitPercent vector of doubles of size joints % - Yes The maximum motor output (expressed as percentage). Safe values can be, for example, 30%.
outOfBoundPosition vector of doubles of size joints % - Yes This value is added the joint limit to test that a position command is not able to move out of the joint limits Typical value 2 deg.

Definition at line 74 of file jointLimits.h.

Constructor & Destructor Documentation

◆ JointLimits()

JointLimits::JointLimits ( )

Definition at line 42 of file jointLimits.cpp.

42 : yarp::robottestingframework::TestCase("JointLimits") {
43 jointsList=0;
44 dd=0;
45 ipos=0;
46 icmd=0;
47 iimd=0;
48 ienc=0;
49 ilim=0;
50 enc_jnt=0;
51 original_pids=0;
52 pids_saved=false;
53}

◆ ~JointLimits()

JointLimits::~JointLimits ( )
virtual

Definition at line 55 of file jointLimits.cpp.

55{ }

Member Function Documentation

◆ goTo()

void JointLimits::goTo ( yarp::sig::Vector  position)

Definition at line 220 of file jointLimits.cpp.

221{
222 for (unsigned int i=0; i<jointsList.size(); i++)
223 {
224 ipos->setRefSpeed((int)jointsList[i],speed[i]);
225 ipos->positionMove((int)jointsList[i],position[i]);
226 }
227
228 int timeout = 0;
229 while (1)
230 {
231 int in_position=0;
232 for (unsigned int i=0; i<jointsList.size(); i++)
233 {
234 double tmp=0;
235 ienc->getEncoder((int)jointsList[i],&tmp);
236 if (fabs(tmp-position[i])<toleranceList[i]) in_position++;
237 }
238 if (in_position==jointsList.size()) break;
239 if (timeout>100)
240 {
241 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Timeout while reaching desired position");
242 }
243 yarp::os::Time::delay(0.2);
244 timeout++;
245 }
246}

◆ goToSingle()

bool JointLimits::goToSingle ( int  i,
double  pos,
double *  reached_pos 
)

Definition at line 248 of file jointLimits.cpp.

249{
250 ipos->setRefSpeed((int)jointsList[i],speed[i]);
251 ipos->positionMove((int)jointsList[i],pos);
252 double tmp=0;
253
254 int timeout = 0;
255 while (1)
256 {
257 ienc->getEncoder((int)jointsList[i],&tmp);
258 if (fabs(tmp-pos)<toleranceList[i]) break;
259
260 if (timeout>100)
261 {
262 if(reached_pos != NULL)
263 {
264 *reached_pos = tmp;
265 }
266 return(false);
267 }
268
269 yarp::os::Time::delay(0.2);
270 timeout++;
271 }
272 if(reached_pos != NULL)
273 {
274 *reached_pos = tmp;
275 }
276 return(true);
277}

◆ goToSingleExceed()

bool JointLimits::goToSingleExceed ( int  i,
double  position_to_reach,
double  limit,
double  reachedLimit,
double *  reached_pos 
)

Definition at line 279 of file jointLimits.cpp.

280{
281 ipos->setRefSpeed((int)jointsList[i], speed[i]);
282 ipos->positionMove((int)jointsList[i], position_to_reach);
283 double tmp = 0;
284 bool excededLimit = false;
285 int timeout = 0;
286 double limitToCheck;
287 if(fabs(reachedLimit-limit)>toleranceList[i])
288 {
289 //if i'm here joint did NOT reached the limit and I would check joint doesn't exced reached limit
290 limitToCheck = reachedLimit;
291 }
292 else
293 {
294 limitToCheck = limit;
295 }
296 while (1)
297 {
298 ienc->getEncoder((int)jointsList[i], &tmp);
299 if(fabs(tmp - limitToCheck)>toleranceList[i])
300 {
301 excededLimit = true;
302 //ROBOTTESTINGFRAMEWORK_TEST_REPORT (Asserter::format("j %d exced limitTocheck %f: reached %f",(int)jointsList[i], limitToCheck, tmp));
303 break;
304 }
305 if (fabs(tmp - position_to_reach)<toleranceList[i])
306 {
307 excededLimit = true;
308 //ROBOTTESTINGFRAMEWORK_TEST_REPORT (Asserter::format("j %d is near position_to_reach %f: reached %f",(int)jointsList[i], position_to_reach, tmp));
309 break;
310 }
311
312 if (timeout>50) break;
313 yarp::os::Time::delay(0.2);
314 timeout++;
315 }
316
317 *reached_pos = tmp;
318
319/* if (fabs(tmp - position_to_reach)<toleranceList[i])
320 {
321 //I reached the out of bound target. That's bad!
322 return (true);
323 }
324 if (fabs(tmp - limit)<toleranceList[i])
325 {
326 //I'm still near the joint limit. That's fine.
327 return (false);
328 }
329 //I dont know where I am, that's bad!
330 return(true);
331*/
332
333 if( excededLimit)
334 return (true);
335 else
336 return(false);
337}

◆ run()

void JointLimits::run ( )
virtual

Definition at line 340 of file jointLimits.cpp.

341{
342 char buff[500];
343 setMode(VOCAB_CM_POSITION);
344 ROBOTTESTINGFRAMEWORK_TEST_REPORT("all joints are going to home....");
345 goTo(home);
346
347 for (unsigned int i=0; i<jointsList.size(); i++)
348 {
349 ilim->getLimits((int)jointsList[i],&min_lims[i],&max_lims[i]);
350 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(max_lims[i]!=min_lims[i],"Invalid limit: max==min?");
351 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(max_lims[i]>min_lims[i],"Invalid limit: max<min?");
352 if (max_lims[i] == 0 && min_lims[i] == 0) ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Invalid limit: max==min==0");
353 }
354
355 for (unsigned int i=0; i<jointsList.size(); i++)
356 {
357 bool res;
358 double reached_pos=0;
359 double excededpos_reached = 0;
360
361 //1) Check max limit
362 sprintf(buff,"Testing if max limit is reachable, joint %d, max limit: %f",(int)jointsList[i],max_lims[i]);ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff);
363 //check that max_limit is reachable
364 res = goToSingle(i, max_lims[i], &reached_pos);
365 ROBOTTESTINGFRAMEWORK_TEST_CHECK (res, Asserter::format("joint %d moved to max limit: %f reached: %f", (int)jointsList[i], max_lims[i], reached_pos));
366 //if(!res)
367 //{
368 // goToSingle(i,home[i], NULL); //I need to go to home in order to leave joint in safe position for further tests (other body parts)
369 // sprintf(buff, "Timeout while reaching desired position(%.2f). Reached pos=%.2f", max_lims[i], reached_pos);ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(buff);
370 //}
371 //else { sprintf(buff, "Test successfull, joint %d, max limit: %f reached: %f", (int)jointsList[i], max_lims[i], reached_pos); ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff); }
372
373 //2) check that max_limit + outOfBoundPos is NOT reachable
374 sprintf(buff, "Testing that max limit cannot be exceeded, joint %d, max limit: %f", (int)jointsList[i], max_lims[i]); ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff);
375 res = goToSingleExceed(i, max_lims[i] + outOfBoundPos[i], max_lims[i], reached_pos, &excededpos_reached);
376 ROBOTTESTINGFRAMEWORK_TEST_CHECK (!res, Asserter::format("check if joint %d desn't exced max limit. target was: %f reached: %f, limit %f ", (int)jointsList[i], max_lims[i] + outOfBoundPos[i], excededpos_reached, max_lims[i]));
377 //if (res)
378 //{
379 // goToSingle(i, home[i], NULL); //I need to go to home in order to leave joint in safe position for further tests (other body parts)
380 // sprintf(buff, "Limit execeeded! Limit was (%.2f). Reached pos=%.2f", max_lims[i], reached_pos); ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(buff);
381 //}
382 //else { sprintf(buff, "Test successfull, joint %d, target was: %f reached: %f, limit %f ", (int)jointsList[i], max_lims[i] + outOfBoundPos[i], reached_pos, max_lims[i]); ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff); }
383
384 //3) Check min limit
385 //check that min_limit is reachable
386 sprintf(buff,"Testing if min limit is reachable, joint %d, min limit: %f",(int)jointsList[i],min_lims[i]);ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff);
387 res = goToSingle(i, min_lims[i], &reached_pos);
388 ROBOTTESTINGFRAMEWORK_TEST_CHECK (res, Asserter::format("joint %d moved to min limit: %f reached: %f", (int)jointsList[i], min_lims[i], reached_pos));
389
390 /*if(!res)
391 {
392 goToSingle(i,home[i], NULL);
393 sprintf(buff, "Timeout while reaching desired position(%.2f). Reached pos=%.2f", min_lims[i], reached_pos);ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(buff);
394 }
395 else { sprintf(buff, "Test successfull, joint %d, min limit: %f reached: %f", (int)jointsList[i], min_lims[i], reached_pos); ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff); }*/
396
397 //4) check that min_limit - outOfBoundPos is NOT reachable
398 sprintf(buff, "Testing that min limit cannot be exceeded, joint %d, min limit: %f", (int)jointsList[i], min_lims[i]); ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff);
399 res = goToSingleExceed(i, min_lims[i] - outOfBoundPos[i], min_lims[i], reached_pos, & excededpos_reached);
400 ROBOTTESTINGFRAMEWORK_TEST_CHECK (!res, Asserter::format("check if joint %d desn't exced min limit. target was: %f reached: %f, limit %f ", (int)jointsList[i], min_lims[i] - outOfBoundPos[i], excededpos_reached, min_lims[i]));
401
402 //if (res)
403 //{
404 // goToSingle(i, home[i], NULL); //I need to go to home in order to leave joint in safe position for further tests (other body parts)
405 // sprintf(buff, "Limit execeeded! Limit was (%.2f). Reached pos=%.2f", min_lims[i], reached_pos); ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(buff);
406 //}
407 //else { sprintf(buff, "Test successfull, joint %d, target was: %f reached: %f, limit %f ", (int)jointsList[i], min_lims[i] - outOfBoundPos[i], reached_pos, min_lims[i]); ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff); }
408
409 //5) Check home position
410 sprintf(buff,"Testing joint %d, homing to: %f",(int)jointsList[i],home[i]);ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff);
411 res = goToSingle(i, home[i], &reached_pos);
412 if(!res)
413 {
414 sprintf(buff, "Timeout while reaching desired position(%.2f). Reached pos=%.2f", home[i], reached_pos);ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(buff);
415 }
416 else{ sprintf(buff, "Homing joint %d complete", (int)jointsList[i]); ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff); }
417
418 }
419 ienc->getEncoders(enc_jnt.data());
420 ROBOTTESTINGFRAMEWORK_TEST_REPORT("Test ends. All joints are going to home....");
421 goTo(home);
422 yarp::os::Time::delay(2.0);
423}

◆ setMode()

void JointLimits::setMode ( int  desired_mode)

Definition at line 188 of file jointLimits.cpp.

189{
190 for (unsigned int i=0; i<jointsList.size(); i++)
191 {
192 icmd->setControlMode((int)jointsList[i],desired_mode);
193 iimd->setInteractionMode((int)jointsList[i],VOCAB_IM_STIFF);
194 yarp::os::Time::delay(0.010);
195 }
196
197 int cmode;
198 yarp::dev::InteractionModeEnum imode;
199 int timeout = 0;
200
201 while (1)
202 {
203 int ok=0;
204 for (unsigned int i=0; i<jointsList.size(); i++)
205 {
206 icmd->getControlMode ((int)jointsList[i],&cmode);
207 iimd->getInteractionMode((int)jointsList[i],&imode);
208 if (cmode==desired_mode && imode==VOCAB_IM_STIFF) ok++;
209 }
210 if (ok==jointsList.size()) break;
211 if (timeout>100)
212 {
213 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Unable to set control mode/interaction mode");
214 }
215 yarp::os::Time::delay(0.2);
216 timeout++;
217 }
218}

◆ setup()

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

Definition at line 57 of file jointLimits.cpp.

57 {
58 if(property.check("name"))
59 setName(property.find("name").asString());
60
61 // updating parameters
62 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("robot"), "The robot name must be given as the test parameter!");
63 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("part"), "The part name must be given as the test parameter!");
64 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("joints"), "The joints list must be given as the test parameter!");
65 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("home"), "The home position must be given as the test parameter!");
66 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("speed"), "The positionMove reference speed must be given as the test parameter!");
67 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("outOfBoundPosition"), "The outOfBoundPosition parameter must be given as the test parameter!");
68 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("outputLimitPercent"), "The outputLimitPercent must be given as the test parameter!");
69 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check("tolerance"), " The max error tolerance must be given as the test parameter!");
70
71 robotName = property.find("robot").asString();
72 partName = property.find("part").asString();
73
74 char buff[500];
75 sprintf(buff, "setting up test for %s", partName.c_str());
76 ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff);
77
78 Bottle* jointsBottle = property.find("joints").asList();
79 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(jointsBottle!=0,"unable to parse joints parameter");
80
81 Bottle* homeBottle = property.find("home").asList();
82 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(homeBottle!=0,"unable to parse zero parameter");
83
84 Bottle* speedBottle = property.find("speed").asList();
85 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(speedBottle!=0,"unable to parse speed parameter");
86
87 Bottle* outOfBoundPosition = property.find("outOfBoundPosition").asList();
88 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(outOfBoundPosition != 0, "unable to parse outOfBoundPosition parameter");
89
90 Bottle* outputLimitBottle = property.find("outputLimitPercent").asList();
91 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(outputLimitBottle!=0,"unable to parse speed parameter");
92
93 tolerance = property.find("tolerance").asFloat64();
94 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(tolerance>=0,"invalid tolerance");
95
96 Bottle* toleranceListBottle = property.find("toleranceList").asList(); //optional param
97
98 Property options;
99 options.put("device", "remote_controlboard");
100 options.put("remote", "/"+robotName+"/"+partName);
101 options.put("local", "/jointsLimitsTest/"+robotName+"/"+partName);
102
103 dd = new PolyDriver(options);
104 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->isValid(),"Unable to open device driver");
105 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ienc),"Unable to open encoders interface");
106 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ipos),"Unable to open position interface");
107 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(icmd),"Unable to open control mode interface");
108 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(iimd),"Unable to open interaction mode interface");
109 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ilim),"Unable to open limits interface");
110 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ipid),"Unable to open pid interface");
111
112 if (!ienc->getAxes(&n_part_joints))
113 {
114 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("unable to get the number of joints of the part");
115 }
116
117 int n_cmd_joints = jointsBottle->size();
118 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");
119 for (int i=0; i <n_cmd_joints; i++) jointsList.push_back(jointsBottle->get(i).asInt32());
120
121 enc_jnt.resize(n_part_joints);
122 max_lims.resize(n_cmd_joints);
123 min_lims.resize(n_cmd_joints);
124
125 home.resize (n_cmd_joints); for (int i=0; i< n_cmd_joints; i++) home[i]=homeBottle->get(i).asFloat64();
126 speed.resize(n_cmd_joints); for (int i=0; i< n_cmd_joints; i++) speed[i]=speedBottle->get(i).asFloat64();
127 outputLimit.resize(n_cmd_joints);for (int i=0; i< n_cmd_joints; i++) outputLimit[i]=outputLimitBottle->get(i).asFloat64();
128 outOfBoundPos.resize(n_cmd_joints); for (int i = 0; i < n_cmd_joints; i++) { outOfBoundPos[i] = outOfBoundPosition->get(i).asFloat64(); ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(outOfBoundPos[i] > 0 , "outOfBoundPosition must be > 0"); }
129 toleranceList.resize(n_cmd_joints);
130 for (int i = 0; i < n_cmd_joints; i++)
131 {
132 if(toleranceListBottle)
133 {
134 toleranceList[i] = toleranceListBottle->get(i).asFloat64();
135 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(toleranceList[i] >= 0 , "toleranceList must be > 0");
136 }
137 else
138 toleranceList[i] = tolerance;
139 }
140
141 original_pids = new yarp::dev::Pid[n_cmd_joints];
142 for (unsigned int i=0; i<jointsList.size(); i++)
143 {
144 ipid->getPid(yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_POSITION, (int)jointsList[i],&original_pids[i]);
145 }
146 pids_saved=true;
147
148 for (unsigned int i=0; i<jointsList.size(); i++)
149 {
150 yarp::dev::Pid p = original_pids[i];
151 p.max_output = p.max_output/100*outputLimit[i];
152 p.max_int = p.max_int/100*outputLimit[i];
153 ipid->setPid(yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_POSITION, (int)jointsList[i],p);
154 yarp::os::Time::delay(0.010);
155 yarp::dev::Pid t;
156 ipid->getPid(yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_POSITION, (int)jointsList[i],&t);
157
158 //since pid values are double, the returned values may differ from those sent due to conversion.
159 if (fabs(t.max_output-p.max_output) > 1.0 ||
160 fabs(t.max_int-p.max_int) > 1.0 ||
161 fabs(t.kp-p.kp) > 1.0 ||
162 fabs(t.kd-p.kd) > 1.0 ||
163 fabs(t.ki-p.ki) > 1.0)
164 {
165 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Unable to set output limits");
166 }
167
168 }
169 return true;
170}

◆ tearDown()

void JointLimits::tearDown ( )
virtual

Definition at line 172 of file jointLimits.cpp.

173{
174 if (original_pids)
175 {
176 if (pids_saved)
177 {
178 for (unsigned int i=0; i<jointsList.size(); i++)
179 {
180 ipid->setPid(yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_POSITION, (int)jointsList[i],original_pids[i]);
181 }
182 }
183 delete[] original_pids; original_pids=0;
184 }
185 if (dd) {delete dd; dd =0;}
186}

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