22 #include <robottestingframework/TestAssert.h>
23 #include <robottestingframework/dll/Plugin.h>
24 #include <yarp/os/Time.h>
25 #include <yarp/math/Math.h>
26 #include <yarp/os/Property.h>
30 #include "jointLimits.h"
34 using namespace robottestingframework;
35 using namespace yarp::os;
36 using namespace yarp::dev;
37 using namespace yarp::math;
42 JointLimits::JointLimits() : yarp::robottestingframework::TestCase(
"JointLimits") {
55 JointLimits::~JointLimits() { }
57 bool JointLimits::setup(yarp::os::Property& property) {
58 if(property.check(
"name"))
59 setName(property.find(
"name").asString());
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!");
71 robotName =
property.find(
"robot").asString();
72 partName =
property.find(
"part").asString();
75 sprintf(buff,
"setting up test for %s", partName.c_str());
76 ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff);
78 Bottle* jointsBottle =
property.find(
"joints").asList();
79 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(jointsBottle!=0,
"unable to parse joints parameter");
81 Bottle* homeBottle =
property.find(
"home").asList();
82 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(homeBottle!=0,
"unable to parse zero parameter");
84 Bottle* speedBottle =
property.find(
"speed").asList();
85 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(speedBottle!=0,
"unable to parse speed parameter");
87 Bottle* outOfBoundPosition =
property.find(
"outOfBoundPosition").asList();
88 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(outOfBoundPosition != 0,
"unable to parse outOfBoundPosition parameter");
90 Bottle* outputLimitBottle =
property.find(
"outputLimitPercent").asList();
91 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(outputLimitBottle!=0,
"unable to parse speed parameter");
93 tolerance =
property.find(
"tolerance").asFloat64();
94 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(tolerance>=0,
"invalid tolerance");
96 Bottle* toleranceListBottle =
property.find(
"toleranceList").asList();
99 options.put(
"device",
"remote_controlboard");
100 options.put(
"remote",
"/"+robotName+
"/"+partName);
101 options.put(
"local",
"/jointsLimitsTest/"+robotName+
"/"+partName);
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");
112 if (!ienc->getAxes(&n_part_joints))
114 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(
"unable to get the number of joints of the part");
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());
121 enc_jnt.resize(n_part_joints);
122 max_lims.resize(n_cmd_joints);
123 min_lims.resize(n_cmd_joints);
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++)
132 if(toleranceListBottle)
134 toleranceList[i] = toleranceListBottle->get(i).asFloat64();
135 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(toleranceList[i] >= 0 , "toleranceList must be > 0
");
138 toleranceList[i] = tolerance;
141 original_pids = new yarp::dev::Pid[n_cmd_joints];
142 for (unsigned int i=0; i<jointsList.size(); i++)
144 ipid->getPid(yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_POSITION, (int)jointsList[i],&original_pids[i]);
148 for (unsigned int i=0; i<jointsList.size(); i++)
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);
156 ipid->getPid(yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_POSITION, (int)jointsList[i],&t);
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)
165 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Unable to set output limits
");
172 void JointLimits::tearDown()
178 for (unsigned int i=0; i<jointsList.size(); i++)
180 ipid->setPid(yarp::dev::PidControlTypeEnum::VOCAB_PIDTYPE_POSITION, (int)jointsList[i],original_pids[i]);
183 delete[] original_pids; original_pids=0;
185 if (dd) {delete dd; dd =0;}
188 void JointLimits::setMode(int desired_mode)
190 for (unsigned int i=0; i<jointsList.size(); i++)
192 icmd->setControlMode((int)jointsList[i],desired_mode);
193 iimd->setInteractionMode((int)jointsList[i],VOCAB_IM_STIFF);
194 yarp::os::Time::delay(0.010);
198 yarp::dev::InteractionModeEnum imode;
204 for (unsigned int i=0; i<jointsList.size(); i++)
206 icmd->getControlMode ((int)jointsList[i],&cmode);
207 iimd->getInteractionMode((int)jointsList[i],&imode);
208 if (cmode==desired_mode && imode==VOCAB_IM_STIFF) ok++;
210 if (ok==jointsList.size()) break;
213 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Unable to set control mode/interaction mode
");
215 yarp::os::Time::delay(0.2);
220 void JointLimits::goTo(yarp::sig::Vector position)
222 for (unsigned int i=0; i<jointsList.size(); i++)
224 ipos->setRefSpeed((int)jointsList[i],speed[i]);
225 ipos->positionMove((int)jointsList[i],position[i]);
232 for (unsigned int i=0; i<jointsList.size(); i++)
235 ienc->getEncoder((int)jointsList[i],&tmp);
236 if (fabs(tmp-position[i])<toleranceList[i]) in_position++;
238 if (in_position==jointsList.size()) break;
241 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR("Timeout
while reaching desired position
");
243 yarp::os::Time::delay(0.2);
248 bool JointLimits::goToSingle(int i, double pos, double *reached_pos)
250 ipos->setRefSpeed((int)jointsList[i],speed[i]);
251 ipos->positionMove((int)jointsList[i],pos);
257 ienc->getEncoder((int)jointsList[i],&tmp);
258 if (fabs(tmp-pos)<toleranceList[i]) break;
262 if(reached_pos != NULL)
269 yarp::os::Time::delay(0.2);
272 if(reached_pos != NULL)
279 bool JointLimits::goToSingleExceed(int i, double position_to_reach, double limit, double reachedLimit, double *reached_pos)
281 ipos->setRefSpeed((int)jointsList[i], speed[i]);
282 ipos->positionMove((int)jointsList[i], position_to_reach);
284 bool excededLimit = false;
287 if(fabs(reachedLimit-limit)>toleranceList[i])
289 //if i'm here joint did NOT reached the limit and I would check joint doesn't exced reached limit
290 limitToCheck = reachedLimit;
294 limitToCheck = limit;
298 ienc->getEncoder((int)jointsList[i], &tmp);
299 if(fabs(tmp - limitToCheck)>toleranceList[i])
302 //ROBOTTESTINGFRAMEWORK_TEST_REPORT (Asserter::format("j %d exced limitTocheck %f: reached %f
",(int)jointsList[i], limitToCheck, tmp));
305 if (fabs(tmp - position_to_reach)<toleranceList[i])
308 //ROBOTTESTINGFRAMEWORK_TEST_REPORT (Asserter::format("j %d is near position_to_reach %f: reached %f
",(int)jointsList[i], position_to_reach, tmp));
312 if (timeout>50) break;
313 yarp::os::Time::delay(0.2);
319 /* if (fabs(tmp - position_to_reach)<toleranceList[i])
321 //I reached the out of bound target. That's bad!
324 if (fabs(tmp - limit)<toleranceList[i])
326 //I'm still near the joint limit. That's fine.
329 //I dont know where I am, that's bad!
340 void JointLimits::run()
343 setMode(VOCAB_CM_POSITION);
344 ROBOTTESTINGFRAMEWORK_TEST_REPORT("all joints are going to home....
");
347 for (unsigned int i=0; i<jointsList.size(); i++)
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
");
355 for (unsigned int i=0; i<jointsList.size(); i++)
358 double reached_pos=0;
359 double excededpos_reached = 0;
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));
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);
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); }
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]));
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);
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); }
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));
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);
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); }*/
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]));
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);
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); }
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);
414 sprintf(buff, "Timeout
while reaching desired position(%.2f). Reached pos=%.2f
", home[i], reached_pos);ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(buff);
416 else{ sprintf(buff, "Homing joint %d complete
", (int)jointsList[i]); ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff); }
419 ienc->getEncoders(enc_jnt.data());
420 ROBOTTESTINGFRAMEWORK_TEST_REPORT("Test ends. All joints are going to home....
");
422 yarp::os::Time::delay(2.0);
Check if the software joint limits are properly set.