ocra-recipes
Doxygen documentation for the ocra-recipes repository
ControlThread.cpp
Go to the documentation of this file.
1 
9 /*
10  * This file is part of ocra-icub.
11  * Copyright (C) 2016 Institut des Systèmes Intelligents et de Robotique (ISIR)
12  *
13  * This program is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 */
26 
28 
29 
30 
31 using namespace ocra_recipes;
32 
34 
35 ControlThread::ControlThread(int period, const std::string& taskRpcPortName):
36 RateThread(period),
37 taskRpcServerName(taskRpcPortName),
38 controlThreadPeriod(period),
39 weightDimension(0),
40 stateDimension(0),
41 closePortTimeout(5.0)
42 {
44 }
45 
47 {
48 
49 }
50 
51 
53 {
54  if(openControlPorts()){
55  if(connectControlPorts()){
56  if(getTaskDimensions()){
59  }
60  }
61  }
63  {
64  yarp::os::Time::delay(controlThreadPeriod/1000.);
65  }
66  return ct_threadInit();
67 }
68 
70 {
71  std::cout << "\nControlThread: Closing control ports for thread id = " << threadId << " for task: " << originalTaskParams.name << ".\n\n";
72  inputPort.close();
73  outputPort.close();
74  yarp::os::Bottle message, reply;
75  message.addString("closeControlPorts");
76  threadRpcClient.write(message, reply);
77  double closeDelay = 0.5;
78  double closeDelayTotal = 0.0;
79  while (!reply.get(0).asInt() && closeDelayTotal < closePortTimeout) // if 1
80  {
81  reply.clear();
82  threadRpcClient.write(message, reply);
83  yarp::os::Time::delay(closeDelay);
84  closeDelayTotal += closeDelay;
85  }
86  if (reply.get(0).asInt()) {
87  threadRpcClient.close();
88  }else{
89  std::cout << "[WARNING](ControlThread::threadRelease): Couldn't close task control ports." << std::endl;
90  }
91  std::cout << "Done.\n";
92 
93 
95 }
96 
98 {
99  ct_run();
100 }
101 
102 
104 
106 {
107  bool portsOpened = yarp.checkNetwork();
108 
109  if (portsOpened)
110  {
111  std::string portNameBase = "/CT/" + getThreadType() + "/id_";
112  std::stringstream portNameStream;
113  portNameStream << threadId;
114  portNameBase += portNameStream.str();
115 
116  inputPortName = portNameBase + ":i";
117  outputPortName = portNameBase + ":o";
118 
119 
120  portsOpened = portsOpened && inputPort.open(inputPortName.c_str());
121  portsOpened = portsOpened && outputPort.open(outputPortName.c_str());
122 
123  threadRpcClientName = portNameBase + "/rpc:o";
124 
125  portsOpened = portsOpened && threadRpcClient.open(threadRpcClientName.c_str());
126 
127  isFirstInputBottle = true;
128  inpCallback = new inputCallback(*this);
129  inputPort.setReader(*inpCallback);
130 
132 
133  }
134  else{
135  std::cout << "[ERROR](ControlThread::openControlPorts): Yarp network not running." << std::endl;
136  }
137 
138  return portsOpened;
139 }
140 
142 {
143  bool portsConnected = yarp.checkNetwork();
144 
145  if (portsConnected)
146  {
147  portsConnected = portsConnected && yarp.connect(threadRpcClientName.c_str(), taskRpcServerName.c_str());
148 
149  yarp::os::Bottle message, reply;
150  message.addString("openControlPorts");
151  threadRpcClient.write(message, reply);
152  if (reply.get(0).asInt()) // if 1
153  {
154  std::string taskOutputPortName, taskInputPortName;
155 
156  message.clear();
157  reply.clear();
158  message.addString("getControlPortNames");
159  threadRpcClient.write(message, reply);
160 
161  taskInputPortName = reply.get(1).asString();
162  taskOutputPortName = reply.get(2).asString();
163 
164  portsConnected = portsConnected && yarp.connect(taskOutputPortName.c_str(), inputPortName.c_str());
165  portsConnected = portsConnected && yarp.connect(outputPortName.c_str(), taskInputPortName.c_str());
166 
167  }
168  else
169  {
170  portsConnected = false;
171  }
172  }
173  else{
174  std::cout << "[ERROR](ControlThread::connectControlPorts): Yarp network not running." << std::endl;
175  }
176 
177  return portsConnected;
178 }
179 
180 bool ControlThread::parseInput(yarp::os::Bottle* input)
181 {
182  if (isFirstInputBottle) {
183  currentStateVector.resize(input->size());
184  isFirstInputBottle = false;
186  }
187  for(int i=0; i<input->size(); i++)
188  {
189  currentStateVector(i) = input->get(i).asDouble();
190  }
191 }
192 
193 
194 /**************************************************************************************************
195  Nested PortReader Class
196 **************************************************************************************************/
198 {
199  //do nothing
200 }
201 
202 bool ControlThread::inputCallback::read(yarp::os::ConnectionReader& connection)
203 {
204  // std::cout << "Got a message!" << std::endl;
205  yarp::os::Bottle input;
206  if (input.read(connection)){
207  return ctBase.parseInput(&input);
208  }
209  else{
210  return false;
211  }
212 }
213 /**************************************************************************************************
214 **************************************************************************************************/
215 
216 
218 {
219  return currentStateVector;
220 }
221 
223 {
224  yarp::os::Bottle message;
225  message.addString("updateCurrentStateAndSend");
226  inputPort.write(message);
227 }
228 
230 {
231  yarp::os::Bottle message, reply;
232  message.addString("deactivate");
233  threadRpcClient.write(message, reply);
234  if (reply.get(0).asString()=="deactivated")
235  {
237  return true;
238  }
239  else{return false;}
240 }
241 
243 {
244  yarp::os::Bottle message, reply;
245  message.addString("activate");
246  threadRpcClient.write(message, reply);
247  if (reply.get(0).asString()=="activated")
248  {
250  return true;
251  }
252  else{return false;}
253 }
254 
256 {
257  yarp::os::Bottle message, reply;
258  message.addString("getWeight");
259  threadRpcClient.write(message, reply);
260  if (reply.size()>1) {
261  weightDimension = reply.size()-1;
262  }else{
263  std::cout << "[ERROR](ControlThread::getTaskDimensions): Did not get a valid response from the task for its weight dimension." << std::endl;
264  return false;
265  }
266 
267  message.clear();
268  reply.clear();
269  message.addString("getDesired");
270  threadRpcClient.write(message, reply);
271  if (reply.size()>1) {
272  stateDimension = reply.size()-1;
273  }else{
274  std::cout << "[ERROR](ControlThread::getTaskDimensions): Did not get a valid response from the task for its state dimension." << std::endl;
275  return false;
276  }
277  return true;
278 }
279 
281 {
282  TP.weight.resize(weightDimension);
283  TP.desired.resize(stateDimension);
284  TP.currentState.resize(stateDimension);
285 
286 
287  yarp::os::Bottle message, reply;
288  message.addString("getStiffness");
289  message.addString("getDamping");
290  message.addString("getDimension");
291  message.addString("getWeight");
292  message.addString("getDesired");
293  message.addString("getCurrentState");
294  message.addString("getType");
295  message.addString("getName");
296  message.addString("getActivityStatus");
297 
298  int maxCount = message.size();
299  int count=0;
300 
301  threadRpcClient.write(message, reply);
302  for(int i=0; i<reply.size(); i++)
303  {
304  if (reply.get(i).asString()=="Kp:"){
305  i++;
306  TP.kp = reply.get(i).asDouble();
307  count++;
308  }
309  else if (reply.get(i).asString()=="Kd:"){
310  i++;
311  TP.kd = reply.get(i).asDouble();
312  count++;
313  }
314  else if (reply.get(i).asString()=="Dimension:"){
315  i++;
316  TP.dimension = reply.get(i).asInt();
317  count++;
318  }
319  else if (reply.get(i).asString()=="Weight:"){
320 
321  for(int j=0; j<weightDimension; j++){
322  i++;
323  TP.weight(j) = reply.get(i).asDouble();
324  }
325  count++;
326  }
327  else if (reply.get(i).asString()=="Desired:"){
328 
329  for(int j=0; j<stateDimension; j++){
330  i++;
331  TP.desired(j) = reply.get(i).asDouble();
332  }
333  count++;
334  }
335  else if (reply.get(i).asString()=="currentState:"){
336 
337  for(int j=0; j<stateDimension; j++){
338  i++;
339  TP.currentState(j) = reply.get(i).asDouble();
340  }
341  count++;
342  }
343  else if (reply.get(i).asString()=="Type:"){
344  i++;
345  TP.type = reply.get(i).asString();
346  count++;
347  }
348  else if (reply.get(i).asString()=="Name:"){
349  i++;
350  TP.name = reply.get(i).asString();
351  count++;
352  }
353  else if (reply.get(i).asString()=="activated"){
354  i++;
355  TP.isActive = reply.get(i).asBool();
356  count++;
357  }
358 
359  }
360  return count==maxCount;
361 
362 }
ControlThread(int period, const std::string &taskRpcPortName)
Eigen::VectorXd currentStateVector
yarp::os::RpcClient threadRpcClient
A class for launching generic control threads.
Eigen::VectorXd getCurrentState()
virtual void ct_threadRelease()=0
Eigen::VectorXd currentState
Definition: ControlThread.h:55
TaskParameters currentTaskParams
virtual bool ct_threadInit()=0
TaskParameters originalTaskParams
bool getTaskParameters(TaskParameters &TP)
virtual bool read(yarp::os::ConnectionReader &connection)
bool parseInput(yarp::os::Bottle *input)