22 #include <robottestingframework/TestAssert.h>
23 #include <robottestingframework/dll/Plugin.h>
24 #include <yarp/os/LogStream.h>
25 #include <yarp/os/Time.h>
26 #include <yarp/os/Property.h>
31 #include "PositionControlAccuracyExternalPid.h"
33 using namespace robottestingframework;
34 using namespace yarp::os;
35 using namespace yarp::dev;
40 PositionControlAccuracyExernalPid::PositionControlAccuracyExernalPid() : yarp::robottestingframework::TestCase(
"PositionControlAccuracyExernalPid") {
57 PositionControlAccuracyExernalPid::~PositionControlAccuracyExernalPid() { }
59 bool PositionControlAccuracyExernalPid::setup(yarp::os::Property& property) {
62 if(property.check(
"name"))
63 setName(property.find(
"name").asString());
66 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check(
"robot"),
"The robot name must be given as the test parameter!");
67 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check(
"part"),
"The part name must be given as the test parameter!");
68 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check(
"joints"),
"The joints list must be given as the test parameter!");
69 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check(
"zeros"),
"The zero position list must be given as the test parameter!");
70 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check(
"cycles"),
"The number of cycles of the control signal must be given as the test parameter!");
71 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check(
"step"),
"The amplitude of the step reference signal expressed in degrees!");
72 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(property.check(
"sampleTime"),
"The sampleTime of the control signal must be given as the test parameter!");
74 if(property.check(
"filename"))
75 {m_requested_filename =
property.find(
"filename").asString();}
76 if(property.check(
"home_tolerance"))
77 {m_home_tolerance =
property.find(
"home_tolerance").asFloat64();}
78 if(property.check(
"step_duration"))
79 {m_step_duration =
property.find(
"step_duration").asFloat64();}
80 if(property.check(
"pid_vup"))
81 {m_pospid_vup =
property.find(
"pid_vup").asFloat64();}
82 if(property.check(
"pid_vdown"))
83 {m_pospid_vdown =
property.find(
"pid_vdown").asFloat64();}
85 m_robotName =
property.find(
"robot").asString();
86 m_partName =
property.find(
"part").asString();
88 Bottle* jointsBottle =
property.find(
"joints").asList();
89 Bottle* zerosBottle =
property.find(
"zeros").asList();
91 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(jointsBottle!=0,
"unable to parse joints parameter");
92 m_n_cmd_joints = jointsBottle->size();
93 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(m_n_cmd_joints>0,
"invalid number of joints, it must be >0");
95 m_step =
property.find(
"step").asFloat64();
97 m_cycles =
property.find(
"cycles").asInt32();
98 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(m_cycles>0,
"invalid cycles");
100 m_sampleTime =
property.find(
"sampleTime").asFloat64();
101 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(m_sampleTime>0,
"invalid sampleTime");
104 options.put(
"device",
"remote_controlboard");
105 options.put(
"remote",
"/" + m_robotName +
"/" + m_partName);
106 options.put(
"local",
"/positionControlAccuracyTest/" + m_robotName +
"/" + m_partName);
108 dd =
new PolyDriver(options);
109 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->isValid(),
"Unable to open device driver");
110 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(idir),
"Unable to open position direct interface");
111 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ienc),
"Unable to open encoders interface");
112 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ipos),
"Unable to open position interface");
113 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(icmd),
"Unable to open control mode interface");
114 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(iimd),
"Unable to open interaction mode interface");
115 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR_IF_FALSE(dd->view(ipwm),
"Unable to open pwm mode interface");
117 if (!ienc->getAxes(&m_n_part_joints))
119 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(
"unable to get the number of joints of the part");
122 m_zeros =
new double[m_n_part_joints];
123 m_encoders =
new double[m_n_part_joints];
124 m_jointsList =
new int[m_n_cmd_joints];
125 for (
int i = 0; i <m_n_cmd_joints; i++) m_jointsList[i] = jointsBottle->get(i).asInt32();
126 for (
int i = 0; i <m_n_cmd_joints; i++) m_zeros[i] = zerosBottle->get(i).asFloat64();
128 double p_Ts = m_sampleTime;
129 yarp::sig::Vector p_Kp(1,0.0);
130 yarp::sig::Vector p_Ki(1,0.0);
131 yarp::sig::Vector p_Kd(1,0.0);
132 if(property.check(
"Kp"))
133 {p_Kp =
property.find(
"Kp").asFloat64();}
134 if(property.check(
"Ki"))
135 {p_Ki =
property.find(
"Ki").asFloat64();}
136 if(property.check(
"Kd"))
137 {p_Kd =
property.find(
"Kd").asFloat64();}
139 if(property.check(
"MaxValue"))
140 {p_Max =
property.find(
"MaxValue").asFloat64();}
141 yarp::sig::Vector p_Wp(1,1);
142 yarp::sig::Vector p_Wi(1,1);
143 yarp::sig::Vector p_Wd(1,1);
144 yarp::sig::Vector p_N (1,10);
145 yarp::sig::Vector p_Tt (1,1);
146 yarp::sig::Matrix p_Lim (1,2);
147 yInfo() <<
"Using gains Kp:" << p_Kp[0] <<
" Ki:"<<p_Ki[0] <<
" Kd:"<<p_Kd[0] <<
" Max:" << p_Max;
150 ppid =
new iCub::ctrl::parallelPID(p_Ts, p_Kp, p_Ki, p_Kd, p_Wp, p_Wi, p_Wd, p_N, p_Tt, p_Lim);
152 if (m_requested_filename==
"auto")
155 m_requested_filename=
"ext_";
156 m_requested_filename+=(m_robotName+
"_");
157 m_requested_filename+=(m_partName+
"_");
158 sprintf(buff,
"%.3f",p_Kp[0]);
159 m_requested_filename+=(
"Kp_"+std::string(buff)+
"_");
160 sprintf(buff,
"%.3f",p_Ki[0]);
161 m_requested_filename+=(
"Ki_"+std::string(buff)+
"_");
162 sprintf(buff,
"%.3f",p_Kd[0]);
163 m_requested_filename+=(
"Kdi_"+std::string(buff)+
"_");
164 sprintf(buff,
"%.3f",m_pospid_vup);
165 m_requested_filename+=(
"Vup_"+std::string(buff)+
"_");
166 sprintf(buff,
"%.3f",m_pospid_vdown);
167 m_requested_filename+=(
"Vdown_"+std::string(buff)+
"_");
168 sprintf(buff,
"%.1f",m_step);
169 m_requested_filename+=(
"step_"+std::string(buff)+
".txt");
171 yDebug() <<
"File: " << m_requested_filename <<
" will be used";
176 void PositionControlAccuracyExernalPid::tearDown()
178 if (m_jointsList) {
delete [] m_jointsList; m_jointsList = 0; }
179 if (m_zeros) {
delete [] m_zeros; m_zeros = 0; }
180 if (m_encoders) {
delete [] m_encoders; m_encoders = 0; }
181 if (dd) {
delete dd; dd =0;}
184 void PositionControlAccuracyExernalPid::setMode(
int desired_mode)
186 for (
int i = 0; i<m_n_cmd_joints; i++)
188 icmd->setControlMode(m_jointsList[i], desired_mode);
189 iimd->setInteractionMode(m_jointsList[i], VOCAB_IM_STIFF);
190 yarp::os::Time::delay(0.010);
194 yarp::dev::InteractionModeEnum imode;
200 for (
int i = 0; i<m_n_cmd_joints; i++)
202 icmd->getControlMode(m_jointsList[i], &cmode);
203 iimd->getInteractionMode(m_jointsList[i], &imode);
204 if (cmode==desired_mode && imode==VOCAB_IM_STIFF) ok++;
206 if (ok == m_n_cmd_joints)
break;
209 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(
"Unable to set control mode/interaction mode");
211 yarp::os::Time::delay(0.2);
216 bool PositionControlAccuracyExernalPid::goHome()
218 for (
int i = 0; i<m_n_cmd_joints; i++)
220 ipos->setRefSpeed(m_jointsList[i], 20.0);
221 ipos->positionMove(m_jointsList[i], m_zeros[i]);
228 for (
int i = 0; i<m_n_cmd_joints; i++)
230 ienc->getEncoder(m_jointsList[i], &m_encoders[m_jointsList[i]]);
231 if (fabs(m_encoders[m_jointsList[i]] - m_zeros[i])<m_home_tolerance) in_position++;
233 if (in_position == m_n_cmd_joints)
break;
236 ROBOTTESTINGFRAMEWORK_ASSERT_ERROR(
"Timeout while reaching zero position");
239 yarp::os::Time::delay(0.2);
243 yarp::os::Time::delay(0.5);
247 void PositionControlAccuracyExernalPid::run()
249 for (
int i = 0; i < m_n_cmd_joints; i++)
251 for (
int cycle = 0; cycle < m_cycles; cycle++)
253 setMode(VOCAB_CM_POSITION);
254 if (goHome() ==
false)
256 ROBOTTESTINGFRAMEWORK_ASSERT_FAIL(
"Test stopped");
259 ppid->reset(yarp::sig::Vector(1,0.0));
261 setMode(VOCAB_CM_PWM);
262 double start_time = yarp::os::Time::now();
265 sprintf(cbuff,
"Testing Joint: %d cycle: %d", i, cycle);
267 std::string buff(cbuff);
268 ROBOTTESTINGFRAMEWORK_TEST_REPORT(buff);
270 double time_zero = 0;
271 yarp::os::Bottle dataToPlotRaw;
272 yarp::os::Bottle dataToPlotSync;
273 ienc->getEncoders(m_encoders);
277 double curr_time = yarp::os::Time::now();
278 double elapsed = curr_time - start_time;
284 else if (elapsed > 1.0 && elapsed <= m_step_duration)
286 ref=m_zeros[i]+m_step;
287 if (time_zero == 0) time_zero = elapsed;
295 ienc->getEncoders(m_encoders);
296 m_cmd_single = ppid->compute(yarp::sig::Vector(1,ref),yarp::sig::Vector(1,m_encoders[m_jointsList[i]]))[0];
299 if (ref>m_encoders[m_jointsList[i]])
301 m_cmd_single+=m_pospid_vup;
305 m_cmd_single+=m_pospid_vdown;
309 ipwm->setRefDutyCycle(m_jointsList[i], m_cmd_single);
311 Bottle& b1 = dataToPlotRaw.addList();
313 b1.addFloat64(elapsed);
314 b1.addFloat64(m_encoders[m_jointsList[i]]);
316 b1.addFloat64(m_cmd_single);
317 yarp::os::Time::delay(m_sampleTime);
321 for (
int t = 0; t < dataToPlotRaw.size(); t++)
323 int cycle = dataToPlotRaw.get(t).asList()->get(0).asInt32();
324 double time = dataToPlotRaw.get(t).asList()->get(1).asFloat64();
325 double val = dataToPlotRaw.get(t).asList()->get(2).asFloat64();
326 double cmd = dataToPlotRaw.get(t).asList()->get(3).asFloat64();
327 double duty = dataToPlotRaw.get(t).asList()->get(4).asFloat64();
328 Bottle& b1 = dataToPlotSync.addList();
330 b1.addFloat64(time - time_zero);
336 m_dataToSave.append(dataToPlotSync);
340 std::string filename;
341 if (m_requested_filename==
"")
344 sprintf(cfilename,
"positionControlAccuracyExternalPid_plot_%s%d.txt", m_partName.c_str(), i);
345 filename = cfilename;
352 filename=m_requested_filename;
354 yInfo() <<
"Saving file to: "<< filename;
355 saveToFile(filename, m_dataToSave);
359 setMode(VOCAB_CM_POSITION);
361 ROBOTTESTINGFRAMEWORK_TEST_REPORT(
"Data acquisition complete");
376 void PositionControlAccuracyExernalPid::saveToFile(std::string filename, yarp::os::Bottle &b)
379 fs.open(filename.c_str(), std::fstream::out);
381 for (
int i = 0; i<b.size(); i++)
383 std::string s = b.get(i).toString();
384 std::replace(s.begin(), s.end(),
'(',
' ');
385 std::replace(s.begin(), s.end(),
')',
' ');
386 fs << s << std::endl;
This tests checks the response of the system to a position step, sending directly PWM commands to a j...