RokubiminiEthercatSlave.cpp
Go to the documentation of this file.
1 
9 
10 #include <fstream>
11 #include <thread>
12 namespace rokubimini
13 {
14 namespace ethercat
15 {
18  const uint32_t address, const PdoTypeEnum pdoTypeEnum)
19  : rokubimini::soem_interface::EthercatSlaveBase(bus, address)
20  , name_(name)
21  , pdoTypeEnum_(pdoTypeEnum)
22  , currentPdoTypeEnum_(PdoTypeEnum::NA)
23  , isRunning_{ true }
24 {
25  PdoInfo pdo_info;
26 
27  pdo_info.rxPdoId_ = OD_RX_PDO_ID_VAL_A;
28  pdo_info.txPdoId_ = OD_TX_PDO_ID_VAL_A;
29  pdo_info.rxPdoSize_ = sizeof(RxPdo);
30  pdo_info.txPdoSize_ = sizeof(TxPdoA);
31  pdo_info.moduleId_ = 0x00119800;
32  pdoInfos_.insert({ PdoTypeEnum::A, pdo_info });
33 }
34 
36 {
37  // Configure PDO setup
38  return configurePdo(pdoTypeEnum_);
39 }
40 
42 {
43  std::lock_guard<std::recursive_mutex> lock(mutex_);
44  const auto& update_stamp = bus_->getUpdateReadStamp();
45 
46  switch (getCurrentPdoTypeEnum())
47  {
48  case PdoTypeEnum::A:
49  TxPdoA tx_pdo_a;
50  bus_->readTxPdo(address_, tx_pdo_a);
51  {
52  reading_.getWrench().header.stamp = update_stamp;
53  reading_.getWrench().header.frame_id = name_ + "_wrench";
54  reading_.getWrench().wrench.force.x = tx_pdo_a.forceX_;
55  reading_.getWrench().wrench.force.y = tx_pdo_a.forceY_;
56  reading_.getWrench().wrench.force.z = tx_pdo_a.forceZ_;
57  reading_.getWrench().wrench.torque.x = tx_pdo_a.torqueX_;
58  reading_.getWrench().wrench.torque.y = tx_pdo_a.torqueY_;
59  reading_.getWrench().wrench.torque.z = tx_pdo_a.torqueZ_;
60 
61  reading_.getImu().header.stamp = update_stamp;
62  reading_.getImu().header.frame_id = name_ + "_imu";
63  reading_.getImu().angular_velocity.x = tx_pdo_a.angularRateX_ * DEG_TO_RAD;
64  reading_.getImu().angular_velocity.y = tx_pdo_a.angularRateY_ * DEG_TO_RAD;
65  reading_.getImu().angular_velocity.z = tx_pdo_a.angularRateZ_ * DEG_TO_RAD;
66  reading_.getImu().linear_acceleration.x = tx_pdo_a.accelerationX_ * G_TO_METERS_PER_SECOND_SQUARED;
67  reading_.getImu().linear_acceleration.y = tx_pdo_a.accelerationY_ * G_TO_METERS_PER_SECOND_SQUARED;
68  reading_.getImu().linear_acceleration.z = tx_pdo_a.accelerationZ_ * G_TO_METERS_PER_SECOND_SQUARED;
69  reading_.getImu().orientation.x = tx_pdo_a.estimatedOrientationX_;
70  reading_.getImu().orientation.y = tx_pdo_a.estimatedOrientationY_;
71  reading_.getImu().orientation.z = tx_pdo_a.estimatedOrientationZ_;
72  reading_.getImu().orientation.w = tx_pdo_a.estimatedOrientationW_;
73 
76 
77  reading_.getTemperature().header.stamp = update_stamp;
78  reading_.getTemperature().header.frame_id = name_ + "_temp";
79  reading_.getTemperature().temperature = tx_pdo_a.temperature_;
80  reading_.getTemperature().variance = 0; // unknown variance
81  }
82  break;
83  default:
84  break;
85  }
86 }
87 
88 bool RokubiminiEthercatSlave::getSerialNumber(unsigned int& serialNumber)
89 {
90  std::lock_guard<std::recursive_mutex> lock(mutex_);
91  bool success = true;
92  uint32_t serial_number;
93  success &= sendSdoRead(OD_IDENTITY_ID, OD_IDENTITY_SID_SERIAL_NUMBER, false, serial_number);
94  serialNumber = static_cast<unsigned int>(serial_number);
95  ROS_DEBUG("[%s] Reading serial number: %u", name_.c_str(), serialNumber);
96  return success;
97 }
98 
100 {
101  std::lock_guard<std::recursive_mutex> lock(mutex_);
102  bool success = true;
103  int16_t sampling_rate;
104  success &= sendSdoRead(OD_SAMPLING_RATE_ID, 0x00, false, sampling_rate);
105  samplingRate = static_cast<int>(sampling_rate);
106  ROS_DEBUG("[%s] Force/Torque sampling rate: %d Hz", name_.c_str(), samplingRate);
107  return success;
108 }
109 
111 {
112  std::lock_guard<std::recursive_mutex> lock(mutex_);
113  ROS_DEBUG("[%s] Setting force/torque filter", name_.c_str());
114  ROS_DEBUG("[%s] \tchop: %u", name_.c_str(), filter.getChopEnable());
115  ROS_DEBUG("[%s] \tfast: %u", name_.c_str(), filter.getFastEnable());
116  ROS_DEBUG("[%s] \tskip: %u", name_.c_str(), filter.getSkipEnable());
117  ROS_DEBUG("[%s] \tsize: %u", name_.c_str(), filter.getSincFilterSize());
118  bool success = true;
119  /* the following order is mandatory as the sinc filter size range is depending on the other values.
120  * Thats why has to be the last one to be changed */
121  success &=
123  success &=
125  success &=
127  success &=
129  return success;
130 }
131 
132 bool RokubiminiEthercatSlave::setAccelerationFilter(const unsigned int filter)
133 {
134  std::lock_guard<std::recursive_mutex> lock(mutex_);
135  ROS_DEBUG("[%s] Setting acceleration filter: %u", name_.c_str(), filter);
136  bool success = true;
137  success &= sendSdoWrite(OD_ACCELERATION_FILTER_ID, 0x00, false, static_cast<uint8_t>(filter));
138  return success;
139 }
140 
141 bool RokubiminiEthercatSlave::setAngularRateFilter(const unsigned int filter)
142 {
143  std::lock_guard<std::recursive_mutex> lock(mutex_);
144  ROS_DEBUG("[%s] Setting angular rate filter: %u", name_.c_str(), filter);
145  bool success = true;
146  success &= sendSdoWrite(OD_ANGULAR_RATE_FILTER_ID, 0x00, false, static_cast<uint8_t>(filter));
147  return success;
148 }
149 
150 bool RokubiminiEthercatSlave::setAccelerationRange(const unsigned int range)
151 {
152  std::lock_guard<std::recursive_mutex> lock(mutex_);
153  ROS_DEBUG("[%s] Setting acceleration range: %u", name_.c_str(), range);
154  bool success = true;
155  success &= sendSdoWrite(OD_ACCELERATION_RANGE_ID, 0x00, false, static_cast<uint8_t>(range));
156  return success;
157 }
158 
159 bool RokubiminiEthercatSlave::setAngularRateRange(const unsigned int range)
160 {
161  std::lock_guard<std::recursive_mutex> lock(mutex_);
162  ROS_DEBUG("[%s] Setting angular rate range: %u", name_.c_str(), range);
163  bool success = true;
164  success &= sendSdoWrite(OD_ANGULAR_RATE_RANGE_ID, 0x00, false, static_cast<uint8_t>(range));
165  return success;
166 }
167 
168 bool RokubiminiEthercatSlave::setForceTorqueOffset(const Eigen::Matrix<double, 6, 1>& forceTorqueOffset)
169 {
170  std::lock_guard<std::recursive_mutex> lock(mutex_);
171  ROS_DEBUG_STREAM("[" << name_.c_str() << "] Setting Force/Torque offset: " << forceTorqueOffset << std::endl);
172  bool success = true;
174  static_cast<float>(forceTorqueOffset(0, 0)));
176  static_cast<float>(forceTorqueOffset(1, 0)));
178  static_cast<float>(forceTorqueOffset(2, 0)));
180  static_cast<float>(forceTorqueOffset(3, 0)));
182  static_cast<float>(forceTorqueOffset(4, 0)));
184  static_cast<float>(forceTorqueOffset(5, 0)));
185  return success;
186 }
187 
189 {
190  std::lock_guard<std::recursive_mutex> lock(mutex_);
191  ROS_DEBUG("[%s] Setting sensor configuration", name_.c_str());
192  bool success = true;
193 
195  sensorConfiguration.getCalibrationMatrixActive());
197  sensorConfiguration.getTemperatureCompensationActive());
199  sensorConfiguration.getImuActive());
201  sensorConfiguration.getCoordinateSystemConfigurationActive());
203  sensorConfiguration.getInertiaCompensationActive());
205  sensorConfiguration.getOrientationEstimationActive());
206 
207  return success;
208 }
209 
211 {
212  return sendSdoWrite(OD_SENSOR_CALIBRATION_ID, subId, false, static_cast<float>(entry));
213 }
214 
216 {
217  std::lock_guard<std::recursive_mutex> lock(mutex_);
218  bool success = true;
219 
220  success &= sendCalibrationMatrixEntry(0x02, sensorCalibration.getCalibrationMatrix()(0, 0));
221  success &= sendCalibrationMatrixEntry(0x03, sensorCalibration.getCalibrationMatrix()(0, 1));
222  success &= sendCalibrationMatrixEntry(0x04, sensorCalibration.getCalibrationMatrix()(0, 2));
223  success &= sendCalibrationMatrixEntry(0x05, sensorCalibration.getCalibrationMatrix()(0, 3));
224  success &= sendCalibrationMatrixEntry(0x06, sensorCalibration.getCalibrationMatrix()(0, 4));
225  success &= sendCalibrationMatrixEntry(0x07, sensorCalibration.getCalibrationMatrix()(0, 5));
226  success &= sendCalibrationMatrixEntry(0x08, sensorCalibration.getCalibrationMatrix()(1, 0));
227  success &= sendCalibrationMatrixEntry(0x09, sensorCalibration.getCalibrationMatrix()(1, 1));
228  success &= sendCalibrationMatrixEntry(0x0A, sensorCalibration.getCalibrationMatrix()(1, 2));
229  success &= sendCalibrationMatrixEntry(0x0B, sensorCalibration.getCalibrationMatrix()(1, 3));
230  success &= sendCalibrationMatrixEntry(0x0C, sensorCalibration.getCalibrationMatrix()(1, 4));
231  success &= sendCalibrationMatrixEntry(0x0D, sensorCalibration.getCalibrationMatrix()(1, 5));
232  success &= sendCalibrationMatrixEntry(0x0E, sensorCalibration.getCalibrationMatrix()(2, 0));
233  success &= sendCalibrationMatrixEntry(0x0F, sensorCalibration.getCalibrationMatrix()(2, 1));
234  success &= sendCalibrationMatrixEntry(0x10, sensorCalibration.getCalibrationMatrix()(2, 2));
235  success &= sendCalibrationMatrixEntry(0x11, sensorCalibration.getCalibrationMatrix()(2, 3));
236  success &= sendCalibrationMatrixEntry(0x12, sensorCalibration.getCalibrationMatrix()(2, 4));
237  success &= sendCalibrationMatrixEntry(0x13, sensorCalibration.getCalibrationMatrix()(2, 5));
238  success &= sendCalibrationMatrixEntry(0x14, sensorCalibration.getCalibrationMatrix()(3, 0));
239  success &= sendCalibrationMatrixEntry(0x15, sensorCalibration.getCalibrationMatrix()(3, 1));
240  success &= sendCalibrationMatrixEntry(0x16, sensorCalibration.getCalibrationMatrix()(3, 2));
241  success &= sendCalibrationMatrixEntry(0x17, sensorCalibration.getCalibrationMatrix()(3, 3));
242  success &= sendCalibrationMatrixEntry(0x18, sensorCalibration.getCalibrationMatrix()(3, 4));
243  success &= sendCalibrationMatrixEntry(0x19, sensorCalibration.getCalibrationMatrix()(3, 5));
244  success &= sendCalibrationMatrixEntry(0x1A, sensorCalibration.getCalibrationMatrix()(4, 0));
245  success &= sendCalibrationMatrixEntry(0x1B, sensorCalibration.getCalibrationMatrix()(4, 1));
246  success &= sendCalibrationMatrixEntry(0x1C, sensorCalibration.getCalibrationMatrix()(4, 2));
247  success &= sendCalibrationMatrixEntry(0x1D, sensorCalibration.getCalibrationMatrix()(4, 3));
248  success &= sendCalibrationMatrixEntry(0x1E, sensorCalibration.getCalibrationMatrix()(4, 4));
249  success &= sendCalibrationMatrixEntry(0x1F, sensorCalibration.getCalibrationMatrix()(4, 5));
250  success &= sendCalibrationMatrixEntry(0x20, sensorCalibration.getCalibrationMatrix()(5, 0));
251  success &= sendCalibrationMatrixEntry(0x21, sensorCalibration.getCalibrationMatrix()(5, 1));
252  success &= sendCalibrationMatrixEntry(0x22, sensorCalibration.getCalibrationMatrix()(5, 2));
253  success &= sendCalibrationMatrixEntry(0x23, sensorCalibration.getCalibrationMatrix()(5, 3));
254  success &= sendCalibrationMatrixEntry(0x24, sensorCalibration.getCalibrationMatrix()(5, 4));
255  success &= sendCalibrationMatrixEntry(0x25, sensorCalibration.getCalibrationMatrix()(5, 5));
256  success &= sendSdoWrite(OD_SENSOR_CALIBRATION_ID, 0x01, false, sensorCalibration.getPassPhrase());
257 
258  return success;
259 }
261 {
263  // Sleep for some time to give the slave time to execute the pre-op cb
264  std::this_thread::sleep_for(std::chrono::milliseconds(500));
266  {
267  ROS_ERROR("[%s] Slave failed to switch to PREOP state", name_.c_str());
268  return false;
269  }
270  return true;
271 }
272 
274 {
277  return true;
278 }
279 
281 {
282  std::lock_guard<std::recursive_mutex> lock(mutex_);
283  ROS_DEBUG("[%s] Saving configuration parameters", name_.c_str());
284  bool success = true;
285  uint8_t retain_configuration = 0x01;
286  success &= sendSdoWrite(OD_CONTROL_ID, OD_CONTROL_SID_COMMAND, false, retain_configuration);
287  uint8_t status;
288  success &= sendSdoRead(OD_CONTROL_ID, OD_CONTROL_SID_STATUS, false, status);
289  if (status != 0)
290  {
291  ROS_ERROR("[%s] Could not save configuration parameters on device. Status value is: %u", name_.c_str(), status);
292  return false;
293  }
294  return success;
295 }
296 
298 {
299  std::lock_guard<std::recursive_mutex> lock(mutex_);
300  reading = reading_;
301 }
302 
304 {
305  std::lock_guard<std::recursive_mutex> lock(mutex_);
306 
307  RxPdo rx_pdo;
308  rx_pdo.digitalOutput_ = static_cast<uint8_t>(0);
309  bus_->writeRxPdo(address_, rx_pdo);
310 }
311 
313 {
314 }
315 
317 {
318  std::lock_guard<std::recursive_mutex> lock(mutex_);
319  bus_->setState(state, address_);
320 }
321 
323 {
324  std::lock_guard<std::recursive_mutex> lock(mutex_);
325  return bus_->waitForState(state, address_);
326 }
327 
329 {
330  // const auto a = pdoInfos_[PdoTypeEnum::A];
331  std::lock_guard<std::recursive_mutex> lock(mutex_);
332  return pdoInfos_.at(currentPdoTypeEnum_);
333 }
334 
336 {
337  std::lock_guard<std::recursive_mutex> lock(mutex_);
338  if (pdoTypeEnum == PdoTypeEnum::NA)
339  {
340  ROS_ERROR("[%s] Invalid EtherCAT PDO Type.", name_.c_str());
341  return false;
342  }
343 
344  // If PDO setup is already active, return.
345  if (pdoTypeEnum == getCurrentPdoTypeEnum())
346  {
347  return true;
348  }
349 
350  // {
351  // std::lock_guard<std::recursive_mutex> lock(busMutex_);
352  // if (!sendSdoWrite(OD_SWITCH_PDO_ID, OD_SWITCH_PDO_SID, false, pdoInfos_.at(pdoTypeEnum).moduleId_)) {
353  // return false;
354  // }
355  // }
356 
357  currentPdoTypeEnum_ = pdoTypeEnum;
358  return true;
359 }
360 
361 bool RokubiminiEthercatSlave::readFileToBuffer(const std::string& filePath)
362 {
363  // Read the file into the file buffer
364  std::ifstream file(filePath, std::ios::binary);
365  std::string file_buffer;
366  if (file.is_open())
367  {
368  int ch;
369  while ((ch = file.get()) != std::istream::traits_type::eof())
370  {
371  file_buffer.push_back(static_cast<char>(ch));
372  }
373  fileBuffer_ = const_cast<char*>(file_buffer.c_str());
374  fileSize_ = static_cast<int>(file_buffer.size());
375  file.close();
377  {
378  ROS_ERROR("[%s] File is too big.", name_.c_str());
379  return false;
380  }
381  }
382  else
383  {
384  ROS_ERROR_STREAM("[" << getName() << "] "
385  << "Failed to open file " << filePath);
386  return false;
387  }
388  ROS_DEBUG_STREAM("[" << getName() << "] "
389  << "The firmware was read successfully. Size of file buffer: " << fileSize_);
390  return true;
391 }
392 
393 bool RokubiminiEthercatSlave::firmwareUpdate(const std::string& filePath, const std::string& fileName,
394  const uint32_t& password)
395 {
396  bool success;
397  std::lock_guard<std::recursive_mutex> lock(mutex_);
398  if (!readFileToBuffer(filePath))
399  {
400  ROS_ERROR_STREAM("[" << getName() << "] "
401  << "Could not read file in path " << filePath << ".");
402  return false;
403  }
404  success = bus_->writeFirmware(address_, fileName, password, fileSize_, fileBuffer_);
405  if (!bus_->isRunning())
406  {
407  isRunning_ = false;
408  }
409  if (!success)
410  {
411  ROS_ERROR("[%s] Flashing was not successful.", name_.c_str());
412  }
413  return success;
414 }
415 } // namespace ethercat
416 } // namespace rokubimini
bool setAccelerationRange(const unsigned int range)
Sets an acceleration range to the device.
bool setAngularRateRange(const unsigned int range)
Sets an angular rate range to the device.
bool firmwareUpdate(const std::string &filePath, const std::string &fileName, const uint32_t &password)
Updates the firmware of the device.
#define OD_SENSOR_CONFIGURATION_SID_CALIBRATION_MATRIX_ACTIVE
void updateRead() override
This method is called by the EthercatBusManager. Each device attached to this bus reads its data from...
bool getForceTorqueSamplingRate(int &samplingRate)
Gets the force torque sampling rate of the device.
bool getSerialNumber(unsigned int &serialNumber)
Accessor for device serial number.
const WrenchType & getWrench() const
#define OD_IDENTITY_SID_SERIAL_NUMBER
void readTxPdo(const uint16_t slave, TxPdo &txPdo) const
#define OD_TX_PDO_ID_VAL_A
RokubiminiEthercatSlave()=delete
Default constructor is deleted.
void getReading(rokubimini::Reading &reading) const
Gets the internal reading variable.
std::atomic< PdoTypeEnum > currentPdoTypeEnum_
Current PDO type.
Base class for generic ethercat slaves using soem.
#define OD_ANGULAR_RATE_RANGE_ID
bool isRunning()
Returns if the instance is running.
bool writeFirmware(const uint16_t slave, const std::string &fileName, const uint32_t &password, const int fileSize, char *fileBuffer)
#define OD_SENSOR_CONFIGURATION_ID
unsigned short uint16_t
bool sendSdoRead(const uint16_t index, const uint8_t subindex, const bool completeAccess, Value &value)
void updateWrite() override
This method is called by the EthercatBusManager. Each device attached to the bus writes its data to t...
#define OD_FORCE_TORQUE_FILTER_SID_SINC_SIZE
#define OD_SAMPLING_RATE_ID
unsigned char uint8_t
void shutdown() override
Shuts down the device.
bool setSensorConfiguration(const configuration::SensorConfiguration &sensorConfiguration)
Sets a sensor configuration to the device.
#define OD_SENSOR_CONFIGURATION_SID_ORIENTATION_ESTIMATION
bool configurePdo(const PdoTypeEnum pdoTypeEnum)
Configures a PDO in the Ethercat device.
bool setAccelerationFilter(const unsigned int filter)
Sets an acceleration filter to the device.
#define OD_SENSOR_CONFIGURATION_SID_IMU_ACTIVE
#define MAX_FILE_SIZE_FIRMWARE
bool readFileToBuffer(const std::string &filePath)
Reads the contents of a file to an internal buffer.
#define OD_CONTROL_SID_STATUS
bool setAngularRateFilter(const unsigned int filter)
Sets an angular rate filter to the device.
EC_STATE_OPERATIONAL
PdoInfos pdoInfos_
Map between PDO types and their infos.
#define OD_CONTROL_SID_COMMAND
unsigned int uint32_t
#define OD_FORCE_TORQUE_FILTER_SID_FIR_DISABLE
void setState(const uint16_t state, const uint16_t slave=0)
#define OD_FORCE_TORQUE_FILTER_ID
signed short int16_t
PdoTypeEnum getCurrentPdoTypeEnum() const
Accessor for the current PDO type.
bool saveConfigParameter()
Saves the current configuration to the device.
#define OD_ACCELERATION_RANGE_ID
#define OD_SENSOR_FORCE_TORQUE_OFFSET_SID_1
char * fileBuffer_
The buffer to save the contents of the file.
void setStatusword(const Statusword &statusword)
EC_STATE_SAFE_OP
EC_STATE_PRE_OP
void setState(const uint16_t state)
Sets the desired EtherCAT state machine state of the device in the bus.
#define OD_FORCE_TORQUE_FILTER_SID_CHOP_ENABLE
const ros::Time & getUpdateReadStamp() const
void setForceTorqueSaturated(const bool isForceTorqueSaturated)
#define OD_RX_PDO_ID_VAL_A
#define OD_SENSOR_FORCE_TORQUE_OFFSET_SID_3
bool waitForState(const uint16_t state)
Wait for an EtherCAT state machine state to be reached.
#define ROS_DEBUG_STREAM(args)
bool setForceTorqueOffset(const Eigen::Matrix< double, 6, 1 > &forceTorqueOffset)
Sets a force torque offset to the device.
bool sendCalibrationMatrixEntry(const uint8_t subId, const double entry)
Sends a calibration matrix entry to device.
#define OD_SENSOR_FORCE_TORQUE_OFFSET_SID_6
bool waitForState(const uint16_t state, const uint16_t slave=0, const unsigned int maxRetries=40, const double retrySleep=0.001)
#define OD_CONTROL_ID
PdoInfo getCurrentPdoInfo() const override
Accessor for the current PDO info.
static constexpr double G_TO_METERS_PER_SECOND_SQUARED
#define OD_SENSOR_FORCE_TORQUE_OFFSET_SID_2
#define OD_SENSOR_CONFIGURATION_SID_TEMPERATURE_COMPENSATION
#define OD_SENSOR_FORCE_TORQUE_OFFSET_SID_4
#define OD_SENSOR_CALIBRATION_ID
#define OD_SENSOR_FORCE_TORQUE_OFFSET_SID_5
bool setConfigMode()
Sets the device in config mode.
Struct defining the Pdo characteristic.
Class for managing an ethercat bus containing one or multiple slaves.
std::string getName() const override
Accessor for device name.
const TempType & getTemperature() const
#define OD_SENSOR_CONFIGURATION_SID_COORD_SYSTEM_CONFIGURATION
#define OD_FORCE_TORQUE_FILTER_SID_FAST_ENABLE
bool sendSdoWrite(const uint16_t index, const uint8_t subindex, const bool completeAccess, const Value value)
#define OD_ACCELERATION_FILTER_ID
uint8_t state
#define ROS_ERROR_STREAM(args)
#define OD_ANGULAR_RATE_FILTER_ID
#define OD_IDENTITY_ID
#define OD_SENSOR_FORCE_TORQUE_OFFSET_ID
#define OD_SENSOR_CONFIGURATION_SID_INERTIA_COMPENSATION
#define ROS_ERROR(...)
bool setForceTorqueFilter(const configuration::ForceTorqueFilter &filter)
Sets a force torque filter to the device.
void writeRxPdo(const uint16_t slave, const RxPdo &rxPdo)
const Eigen::Matrix< double, 6, 6 > & getCalibrationMatrix() const
const ImuType & getImu() const
bool startup() override
This method starts up and initializes the device.
bool setSensorCalibration(const calibration::SensorCalibration &sensorCalibration)
Sets a sensor calibration to the device.
Reading reading_
The internal reading variable. It&#39;s used for providing to client code the sensor readings, through the getReading () function.
std::atomic< bool > isRunning_
Internal flag to indicate if the instance is running.
static constexpr double DEG_TO_RAD
#define ROS_DEBUG(...)


rokubimini_ethercat
Author(s):
autogenerated on Wed Mar 3 2021 03:09:16