iCub-main
eo_ftsens_privData.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2006-2018 Istituto Italiano di Tecnologia (IIT)
3  * All rights reserved.
4  * Author: Valentina Gaggero
5  * This software may be modified and distributed under the terms of the
6  * BSD-3-Clause license. See the accompanying LICENSE file for details.
7  */
8 #include "eo_ftsens_privData.h"
9 #include "EoProtocolAS.h"
10 #include "EOnv_hid.h"
11 
12 using namespace yarp;
13 using namespace yarp::os;
14 using namespace yarp::dev;
15 
16 
17 eo_ftsens_privData::eo_ftsens_privData(std::string name):
18  embObjDevPrivData(name),
19  useCalibValues(false),
20  useTemperature(false),
21  scaleFactorIsFilled(false),
22  lastTemperature(0),
23  timestampTemperature(0.0),
24  timestampAnalogdata(0.0)
25 {
26  analogdata.resize(strain_Channels, 0.0);
27  offset.resize(strain_Channels, 0.0);
28  scaleFactor.resize(strain_Channels, 1.0);
29 }
30 
31 
33 { analogdata.resize(0);
34  offset.resize(0);
35  scaleFactor.resize(0);
36 }
37 
38 
39 bool eo_ftsens_privData::fromConfig(yarp::os::Searchable &_config, servConfigFTsensor_t &serviceConfig)
40 {
41 
42  ServiceParser* parser = new ServiceParser;
43  bool ret = parser->parseService(_config, serviceConfig);
44  delete parser;
45 
46  if(!ret)
47  {
48  yError() << getBoardInfo() << "is missing some configuration parameter. Check logs and your config file.";
49  return false;
50  }
51 
52  useCalibValues = serviceConfig.useCalibration;
53  if(serviceConfig.temperatureAcquisitionrate > 0)
54  useTemperature = true;
55  devicename = serviceConfig.nameOfStrain;
56  frameName = serviceConfig.frameName;
57 
58  if(isVerbose())
59  printServiceConfig(serviceConfig);
60  return ret;
61 }
62 
63 
64 
65 
66 //#warning --> marco.accame: review function embObjFTsensor::fillScaleFactor() as in comment below
67 // it is better to change the behaviour of the function so that: 1. we send the request, 2. we wait for the sig<> and unblock a mutex
68 // current implementation relies on a wait of 1 sec and check of non-zero length of an array: smart but not the rigth way to do it.
69 
70 // EVEN better: in serviceVerifyActivate() we allow the retrieval of a parameter which the ETH board sends back. in such a param it is contained
71 // the fullscales values ...
72 
73 // marco.accame on 09 jan 2018: much better using an ask(id32_fullscale) and making this variable proxied inside the ETH board ...
74 
76 {
77  // if we already have set the scalefactor ...
78  if(true == scaleFactorIsFilled)
79  {
80  return true;
81  }
82 
83  // at first we set the scale factors to 1, so that we are sure they have a safe value. it redundant, as we already set it to 1.0
84  for(size_t i = 0; i<scaleFactor.size(); i++)
85  {
86  scaleFactor[i] = 1.0f;
87  }
88 
89  // if we dont need calibration we are done
90  if(false == useCalibValues)
91  {
92  if(isVerbose())
93  {
94  yDebug() << getBoardInfo() << "fillScaleFactor(): we DONT use calibration, thus all scale factors are set to 1.0";
95  }
96 
97  scaleFactorIsFilled = true;
98  return true;
99  }
100 
101  // if we need calibration, then we need to ask the fullscales directly to the strain
102 
103 
104  // marco.accame on 11 apr 2014:
105  // added the code under ifdef 1. the reason is that one cannot rely on validity of data structures inside the EOnv, as in protocol v2 the requirement is that
106  // the initialisation is not specialised and is ... all zeros. if the user wants to init to proper values must redefine the relevant INIT funtion.
107  // in this case, the eoprot_fun_INIT_as_strain_status_fullscale().
108  // extern void eoprot_fun_INIT_as_strain_status_fullscale(const EOnv* nv)
109  // {
110  // eOas_arrayofupto12bytes_t fullscale_values = {0};
111  // eo_array_New(6, 2, &fullscale_values); // itemsize = 2, capacity = 6
112  // eo_nv_Set(nv, &fullscale_values, eobool_true, eo_nv_upd_dontdo);
113  // }
114  // moreover, even if properly initted, it is required to set the size to 0 because the size being not 0 is the check of reception of a message.
115 
116 
117  bool gotFullScaleValues = false;
118 
119 
120  // Check initial size of array... it should be zero.
121  int timeout, NVsize;
122  EOnv tmpNV;
123  EOnv *p_tmpNV = NULL;
124  eOas_arrayofupto12bytes_t fullscale_values = {0};
125  // force it to be an empty array of itemsize 2 and capacity 6.
126  // the reason is that the eoprot_tag_as_strain_status_fullscale contains 3 forces and 3 torques each of 2 bytes. see eOas_strain_status_t in EoAnalogSensors.h
127  eo_array_New(6, 2, &fullscale_values);
128 
129  eOprotID32_t id32_fullscale = eoprot_ID_get(eoprot_endpoint_analogsensors, eoprot_entity_as_strain, 0, eoprot_tag_as_strain_status_fullscale);
130 
131 
132  // at first we impose that the local value of fullscales is zero.
133  // we also force the change because this variable is readonly
134  const bool overrideROprotection = true;
135  res->setLocalValue(id32_fullscale, &fullscale_values, overrideROprotection);
136 
137 
138  // Prepare analog sensor
139  eOas_strain_config_t strainConfig = {0};
140  strainConfig.datarate = serviceConfig.acquisitionrate;
141  strainConfig.mode = eoas_strainmode_acquirebutdonttx;
142  strainConfig.signaloncefullscale = eobool_true;
143 
144  eOprotID32_t id32_strain_config = eoprot_ID_get(eoprot_endpoint_analogsensors, eoprot_entity_as_strain, 0, eoprot_tag_as_strain_config);
145 
146  timeout = 5;
147 
148  // wait for response
149  while(!gotFullScaleValues && (timeout != 0))
150  {
151  res->setRemoteValue(id32_strain_config, &strainConfig);
152  SystemClock::delaySystem(1.0);
153  // read fullscale values
154  res->getLocalValue(id32_fullscale, &fullscale_values);
155  // If data arrives, size is bigger than zero
156  //#warning --> marco.accame says: to wait for 1 sec and read size is ok. a different way is to ... wait for a semaphore incremented by the reply of the board. think of it!
157  NVsize = eo_array_Size((EOarray *)&fullscale_values);
158 
159  if(0 != NVsize)
160  {
161  gotFullScaleValues = true;
162  break;
163  }
164 
165  timeout--;
166  if(isVerbose())
167  {
168  yWarning() << getBoardInfo() << "filling ScaleFactor ....";
169  }
170  }
171 
172  if((false == gotFullScaleValues) && (0 == timeout))
173  {
174  yError() << getBoardInfo() << "fillScaleFactor(): ETH Analog sensor: request for calibration parameters timed out ";
175  return false;
176  }
177 
178  if((strain_Channels != NVsize))
179  {
180  yError() << getBoardInfo() << "Analog sensor Calibration data has a different size from channels number in configuration file ";
181  return false;
182  }
183 
184 
185  if(gotFullScaleValues)
186  {
187  if(isVerbose())
188  {
189  yWarning() << getBoardInfo() << "fillScaleFactor() detected that already has full scale values";
190  yDebug() << getBoardInfo() << "fillScaleFactor(): Fullscale values are: size=" << eo_array_Size((EOarray *)&fullscale_values) << " numchannel=" << strain_Channels;
191  }
192 
193  for (size_t i = 0; i<scaleFactor.size(); i++)
194  {
195  // Get the k-th element of the array as a 2 bytes msg
196  uint8_t *msg = (uint8_t *) eo_array_At((EOarray *) &fullscale_values, i);
197  if(NULL == msg)
198  {
199  yError() << getBoardInfo() << "fillScaleFactor() doesn't receive data for channel " << i;
200  return false;
201  }
202  // Got from CanBusMotionControl... here order of bytes seems inverted with respect to calibratedValues or uncalibratedValues (see callback of can strain messages inside the FW of ETHBOARD)
203  scaleFactor[i] = ((uint16_t)(msg[0]<<8) | msg[1]);
204  //yError() << " scale factor[" << i << "] = " << scaleFactor[i];
205  if(isVerbose())
206  {
207  yDebug() << getBoardInfo() << "fillScaleFactor(): channel " << i << "full scale value " << scaleFactor[i];
208  }
209  }
210 
211  scaleFactorIsFilled = true;
212  }
213 
214  return scaleFactorIsFilled;
215 }
216 
217 
219 {
220  vector<eOprotID32_t> id32v(0); //vector with id of nv to configure as regulars
221  eOprotID32_t id32 = eo_prot_ID32dummy;
222 
223  //1) set regulars for ft (strain) service
224  if(true == serviceConfig.useCalibration)
225  {
226  id32 = eoprot_ID_get(eoprot_endpoint_analogsensors, eoprot_entity_as_strain, 0, eoprot_tag_as_strain_status_calibratedvalues);
227  }
228  else
229  {
230  id32 = eoprot_ID_get(eoprot_endpoint_analogsensors, eoprot_entity_as_strain, 0, eoprot_tag_as_strain_status_uncalibratedvalues);
231  }
232 
233  id32v.push_back(id32);
234 
235  if(!serviceSetRegulars(eomn_serv_category_strain, id32v))
236  return false;
237 
238  //2) set regulars for temperature service
239  id32v.resize(0);
240  id32 = eo_prot_ID32dummy;
241 
242  id32 = eoprot_ID_get(eoprot_endpoint_analogsensors, eoprot_entity_as_temperature, 0, eoprot_tag_as_temperature_status);
243  id32v.push_back(id32);
244 
245  if(!serviceSetRegulars(eomn_serv_category_temperatures, id32v))
246  return false;
247 
248  return true;
249 }
250 
251 
253 {
254  char loc[20] = {0};
255  char fir[20] = {0};
256  char pro[20] = {0};
257  const char * boardname = (NULL != res) ? (res->getProperties().boardnameString.c_str()) : ("NOT-ASSIGNED-YET");
258  const char * ipv4 = (NULL != res) ? (res->getProperties().ipv4addrString.c_str()) : ("NOT-ASSIGNED-YET");
259  const char * boardtype = eoboards_type2string2(static_cast<eObrd_type_t>(serviceConfig.ethservice.configuration.data.as.strain.boardtype.type), eobool_true);
260  ServiceParser *parser = new ServiceParser();
261  parser->convert(serviceConfig.ethservice.configuration.data.as.strain.canloc, loc, sizeof(loc));
262  parser->convert(serviceConfig.ethservice.configuration.data.as.strain.boardtype.firmware, fir, sizeof(fir));
263  parser->convert(serviceConfig.ethservice.configuration.data.as.strain.boardtype.protocol, pro, sizeof(pro));
264 
265  yInfo() << "The embObjFTsensor device using BOARD" << boardname << " w/ IP" << ipv4 << "has the following service config:";
266  yInfo() << "- acquisitionrate =" << serviceConfig.acquisitionrate;
267  yInfo() << "- useCalibration =" << serviceConfig.useCalibration;
268  yInfo() << "- STRAIN of type" << boardtype << "named" << serviceConfig.nameOfStrain << "@" << loc << "with required protocol version =" << pro << "and required firmware version =" << fir;
269  delete parser;
270 }
271 
273 {
274  eOas_strain_config_t strainConfig = {0};
275 
276  strainConfig.datarate = serviceConfig.acquisitionrate;
277  strainConfig.signaloncefullscale = eobool_false;
278  strainConfig.mode = (true == serviceConfig.useCalibration) ? (eoas_strainmode_txcalibrateddatacontinuously) : (eoas_strainmode_txuncalibrateddatacontinuously);
279 
280  // version with read-back
281 
282  eOprotID32_t id32 = eoprot_ID_get(eoprot_endpoint_analogsensors, eoprot_entity_as_strain, 0, eoprot_tag_as_strain_config);
283 
284  if(false == res->setcheckRemoteValue(id32, &strainConfig, 10, 0.010, 0.050))
285  {
286  yError() << getBoardInfo() << "FATAL: sendConfig2Strain() had an error while calling setcheckRemoteValue() for strain config ";
287  return false;
288  }
289  else
290  {
291  if(isVerbose())
292  {
293  yDebug() << getBoardInfo() << "sendConfig2Strain() correctly configured strain coinfig ";
294  }
295  }
296 
297  //configure the service of temperature
298  id32 = eoprot_ID_get(eoprot_endpoint_analogsensors, eoprot_entity_as_temperature, 0, eoprot_tag_as_temperature_config);
299 
300 
301  eOas_temperature_config_t tempconfig = {0};
302  if(serviceConfig.temperatureAcquisitionrate > 0)
303  {
304  tempconfig.enabled = 1;
305  tempconfig.datarate = serviceConfig.temperatureAcquisitionrate/1000;
306  }
307 
308 
309  if(false == res->setcheckRemoteValue(id32, &tempconfig, 10, 0.010, 0.050))
310  {
311  yError() << getBoardInfo() << "FATAL: sendConfig2Strain(temperature) had an error while calling setcheckRemoteValue() for strain config ";
312  return false;
313  }
314  else
315  {
316  if(isVerbose())
317  {
318  yDebug() << getBoardInfo() << "sendConfig2Strain() correctly configured strain coinfig ";
319  }
320  }
321  return true;
322 }
323 
324 bool eo_ftsens_privData::fillTemperatureEthServiceInfo(eOmn_serv_parameter_t &ftSrv, eOmn_serv_parameter_t &tempSrv)
325 {
326 // const eOmn_serv_parameter_t* servparamstrain = &serviceConfig.ethservice;
327 // eOmn_serv_parameter_t servparamtemp;
328 // const eOmn_serv_parameter_t* servparamtemp_ptr = &servparamtemp;
329 
330  tempSrv.configuration.type = eomn_serv_AS_temperatures;
331 
332  EOarray* array = eo_array_New(eOas_temperature_descriptors_maxnumber, sizeof(eOas_temperature_descriptor_t), &(tempSrv.configuration.data.as.temperature.arrayofdescriptor));
333  eOas_temperature_descriptor_t descr= {0};
334  descr.typeofboard = ftSrv.configuration.data.as.strain.boardtype.type; //eobrd_strain2 ;
335  descr.typeofsensor = eoas_temperature_t1;
336  descr.on.can.place = eobrd_place_can;
337  descr.on.can.port = ftSrv.configuration.data.as.strain.canloc.port;
338  descr.on.can.addr = ftSrv.configuration.data.as.strain.canloc.addr;
339  eo_array_PushBack(array, &descr);
340 
341  eOas_temperature_setof_boardinfos_t * boardInfoSet_ptr = &tempSrv.configuration.data.as.temperature.setofboardinfos;
342  eOresult_t res = eoas_temperature_setof_boardinfos_clear(boardInfoSet_ptr);
343  if(res != eores_OK)
344  {
345  yError() << getBoardInfo() << "Error in eoas_temperature_setof_boardinfos_clear()";
346  return false;
347  }
348 
349  eObrd_info_t boardInfo = {0};
350  boardInfo.type = ftSrv.configuration.data.as.strain.boardtype.type;
351  memcpy(&boardInfo.protocol , &(ftSrv.configuration.data.as.strain.boardtype.protocol), sizeof(eObrd_protocolversion_t));
352  memcpy(&boardInfo.firmware, &(ftSrv.configuration.data.as.strain.boardtype.firmware), sizeof(eObrd_firmwareversion_t));
353  res = eoas_temperature_setof_boardinfos_add(boardInfoSet_ptr, &boardInfo);
354  if(eores_OK != res)
355  {
356  yError() << getBoardInfo() << "Error in eoas_temperature_setof_boardinfos_add()";
357  return false;
358  }
359 
360  return true;
361 
362 }
bool convert(std::string const &fromstring, eOmc_actuator_t &toactuatortype, bool &formaterror)
bool parseService(yarp::os::Searchable &config, servConfigMais_t &maisconfig)
virtual const Properties & getProperties()=0
virtual bool setcheckRemoteValue(const eOprotID32_t id32, void *value, const unsigned int retries=10, const double waitbeforecheck=0.001, const double timeout=0.050)=0
virtual bool setRemoteValue(const eOprotID32_t id32, void *value)=0
virtual bool getLocalValue(const eOprotID32_t id32, void *value)=0
virtual bool setLocalValue(eOprotID32_t id32, const void *value, bool overrideROprotection=false)=0
bool serviceSetRegulars(eOmn_serv_category_t category, vector< eOprotID32_t > &id32vector, double timeout=0.500)
eth::AbstractEthResource * res
void printServiceConfig(servConfigFTsensor_t &serviceConfig)
bool fromConfig(yarp::os::Searchable &config, servConfigFTsensor_t &serviceConfig)
bool initRegulars(servConfigFTsensor_t &serviceConfig)
std::vector< double > offset
bool fillScaleFactor(servConfigFTsensor_t &serviceConfig)
bool sendConfig2Strain(servConfigFTsensor_t &serviceConfig)
std::vector< double > scaleFactor
std::vector< double > analogdata
bool fillTemperatureEthServiceInfo(eOmn_serv_parameter_t &ftSrv, eOmn_serv_parameter_t &tempSrv)
Copyright (C) 2008 RobotCub Consortium.
std::string nameOfStrain
Definition: serviceParser.h:46
std::string frameName
Definition: serviceParser.h:49
eOmn_serv_parameter_t ethservice
Definition: serviceParser.h:43