OrientedTactileSensorUnit.cpp
Go to the documentation of this file.
2 
3 #include <math.h>
4 
5 #include <fcntl.h>
6 #include <sys/ioctl.h>
7 #include <termios.h>
8 
13 
15 
16 using namespace armarx;
17 
19 {
20 
21  sampleIndexRotation = 0;
22  sampleIndexPressure = 0;
23  sampleIndexAcceleration = 0;
24  sampleIndexPressureRate = 0;
25 }
26 
27 void
29 {
30  //logger part
31  if (getProperty<bool>("logData").getValue())
32  {
33  IceUtil::Time now = IceUtil::Time::now();
34  time_t timer = now.toSeconds();
35  struct tm* ts;
36  char buffer[80];
37  ts = localtime(&timer);
38  strftime(buffer, 80, "%Y-%m-%d-%H-%M-%S", ts);
39  std::string packageName = "RobotAPI";
40  armarx::CMakePackageFinder finder(packageName);
41  std::string dataDir = finder.getDataDir() + "/" + packageName + "/logs/";
42  std::string filename = dataDir + buffer + std::string("_data") + ".json";
43  //ARMARX_IMPORTANT << filename;
44 
45  logger.reset(new SimpleJsonLogger(filename, true));
46  prefix = std::string(buffer);
47  }
48  maxSamplesRotation = stoi(getProperty<std::string>("SamplesRotation").getValue());
49  maxSamplesPressure = stoi(getProperty<std::string>("SamplesPressure").getValue());
50  maxSamplesAcceleration = stoi(getProperty<std::string>("SamplesAcceleration").getValue());
51 
52  std::string topicName = getProperty<std::string>("TopicName").getValue();
53  offeringTopic(topicName);
54 
55  //open serial port
56  std::string portname = getProperty<std::string>("SerialInterfaceDevice").getValue();
57  arduinoIn.open(getProperty<std::string>("SerialInterfaceDevice").getValue(), std::ios::in);
58  arduinoOut.open(getProperty<std::string>("SerialInterfaceDevice").getValue(), std::ios::out);
59 
60  fd = open(portname.c_str(), O_RDWR | O_NOCTTY);
61  struct termios toptions;
62 
63  /* Get currently set options for the tty */
64  tcgetattr(fd, &toptions);
65 
66  /* Set custom options */
67  cfsetispeed(&toptions, B115200);
68  cfsetospeed(&toptions, B115200);
69 
70  /* 8 bits, no parity, no stop bits */
71  toptions.c_lflag = 0;
72  toptions.c_iflag = 0;
73  toptions.c_oflag = 0;
74 
75  /* commit the options */
76  tcsetattr(fd, TCSANOW, &toptions);
77 
78  /* Wait for the Arduino to reset */
79  usleep(1000 * 1000);
80 
81  /* Flush anything already in the serial buffer */
82  tcflush(fd, TCIFLUSH);
83 
84  ARMARX_INFO << "opening device "
85  << getProperty<std::string>("SerialInterfaceDevice").getValue();
86 
87  if (!arduinoIn.is_open())
88  {
89 
90  throw LocalException("Cannot open Arduino on ")
91  << getProperty<std::string>("SerialInterfaceDevice").getValue();
92  }
93 
94  ARMARX_INFO << "Arduino restarts, please wait ...";
95 
96  //wait for the Arduino to reboot
97  usleep(4000000);
98  std::string arduinoLine;
99 
100  //wait for the IMU to be calibrated or load calibration
101  ARMARX_INFO << "waiting for IMU calibration - this can take some time";
102  if (getProperty<bool>("calibrateSensor").getValue())
103  {
104  //calibrate
105 
106  while (arduinoLine.find("mode") == std::string::npos)
107  {
108  getline(arduinoIn, arduinoLine, '\n');
109  }
110 
111  arduinoOut << "calibrate";
112  arduinoOut.flush();
113 
114  while (arduinoLine.find("Calibration Sucessfull") == std::string::npos)
115  {
116  getline(arduinoIn, arduinoLine, '\n');
117  ARMARX_INFO << arduinoLine;
118  }
119  getline(arduinoIn, arduinoLine, '\n');
120  if (getCalibrationValues(arduinoLine))
121  {
122  ARMARX_IMPORTANT << "calibrated sensor";
123  }
124  }
125  else
126  {
127  //load calibration
128  ARMARX_INFO << "load calibration data "
129  << getProperty<std::string>("CalibrationData").getValue();
130  if (loadCalibration())
131  {
132  ARMARX_IMPORTANT << "loaded calibration";
133  first = true;
134  /*std::string line;
135  getline(arduinoIn, line, '\n');
136  ARMARX_IMPORTANT<<line;
137  SensorData dataInit = getValues(line.c_str());
138  ARMARX_IMPORTANT<<dataInit.qw<<" "dataInit.qx<<" "<<dataInit.qy<<" "<<dataInit.qz;
139  Eigen::Quaternionf initialOrientation = Eigen::Quaternionf(dataInit.qw, dataInit.qx, dataInit.qy, dataInit.qz);
140  inverseOrientation = initialOrientation.inverse();*/
141  }
142  }
143  readTask = new RunningTask<OrientedTactileSensorUnit>(this, &OrientedTactileSensorUnit::run);
144  readTask->start();
145 }
146 
147 void
149 {
150  debugDrawerTopic = getTopic<DebugDrawerInterfacePrx>(
151  getProperty<std::string>("DebugDrawerTopicName").getValue());
152  std::string topicName = getProperty<std::string>("TopicName").getValue();
153  topicPrx = getTopic<OrientedTactileSensorUnitListenerPrx>(topicName);
154 }
155 
158 {
159  return PropertyDefinitionsPtr(
161 }
162 
163 void
164 OrientedTactileSensorUnit::run()
165 {
166  while (readTask->isRunning())
167  {
168  std::string line;
169  getline(arduinoIn, line, '\n');
170  SensorData data = getValues(line.c_str());
171  IceUtil::Time now = IceUtil::Time::now();
172  TimestampVariantPtr nowTimestamp = new TimestampVariant(now);
173 
174  //compute rotationRate
175  float rotationRate = 0;
176 
177  //condition for inverse quaternion
178  if ((pow(data.qw, 2) + pow(data.qx, 2) + pow(data.qy, 2) + pow(data.qz, 2)) != 0)
179  {
180  RotationRate sampleRotation;
181  sampleRotation.timestamp = now;
182  sampleRotation.orientation = Eigen::Quaternionf(data.qw, data.qx, data.qy, data.qz);
183  //sampleRotation.orientation = sampleRotation.orientation * inverseOrientation;
184  if (0 < maxSamplesRotation &&
185  samplesRotation.size() < static_cast<std::size_t>(maxSamplesRotation))
186  {
187  samplesRotation.push_back(sampleRotation);
188  }
189  else
190  {
191  samplesRotation[sampleIndexRotation].timestamp = sampleRotation.timestamp;
192  samplesRotation[sampleIndexRotation].orientation = sampleRotation.orientation;
193  sampleIndexRotation = (sampleIndexRotation + 1) % maxSamplesRotation;
194  RotationRate oldsampleRotation;
195  oldsampleRotation.timestamp = samplesRotation.at(sampleIndexRotation).timestamp;
196  oldsampleRotation.orientation = samplesRotation.at(sampleIndexRotation).orientation;
197  Eigen::AngleAxisf aa(sampleRotation.orientation *
198  oldsampleRotation.orientation.inverse());
199  //ARMARX_IMPORTANT << "aa: " << aa.axis() << " " << aa.angle();
200  rotationRate =
201  aa.angle() /
202  (sampleRotation.timestamp - oldsampleRotation.timestamp).toSecondsDouble();
203  }
204  }
205  //compute pressureRate
206  float pressureRate = 0;
207  PressureRate samplePressure;
208  samplePressure.timestamp = now;
209  samplePressure.pressure = data.pressure;
210  if (0 < maxSamplesPressure &&
211  samplesPressure.size() < static_cast<std::size_t>(maxSamplesPressure))
212  {
213  samplesPressure.push_back(samplePressure);
214  }
215  else
216  {
217  samplesPressure[sampleIndexPressure] = samplePressure;
218  sampleIndexPressure = (sampleIndexPressure + 1) % maxSamplesPressure;
219  PressureRate oldsamplePressure;
220  oldsamplePressure.timestamp = samplesPressure.at(sampleIndexPressure).timestamp;
221  oldsamplePressure.pressure = samplesPressure.at(sampleIndexPressure).pressure;
222  pressureRate =
223  (samplePressure.pressure - oldsamplePressure.pressure) /
224  (samplePressure.timestamp - oldsamplePressure.timestamp).toSecondsDouble();
225  }
226 
227  //compute angular accceleration Rate
228  float accelerationRate = 0;
229  AccelerationRate sampleAcceleration;
230  sampleAcceleration.timestamp = now;
231  sampleAcceleration.rotationRate = rotationRate;
232  if (0 < maxSamplesAcceleration &&
233  samplesAcceleration.size() < static_cast<std::size_t>(maxSamplesAcceleration))
234  {
235  samplesAcceleration.push_back(sampleAcceleration);
236  }
237  else
238  {
239  samplesAcceleration[sampleIndexAcceleration] = sampleAcceleration;
240  sampleIndexAcceleration = (sampleIndexAcceleration + 1) % maxSamplesAcceleration;
241  AccelerationRate oldsampleAcceleration;
242  oldsampleAcceleration.timestamp =
243  samplesAcceleration.at(sampleIndexAcceleration).timestamp;
244  oldsampleAcceleration.rotationRate =
245  samplesAcceleration.at(sampleIndexAcceleration).rotationRate;
246  accelerationRate =
247  (sampleAcceleration.rotationRate - oldsampleAcceleration.rotationRate) /
248  (sampleAcceleration.timestamp - oldsampleAcceleration.timestamp).toSecondsDouble();
249  }
250  if (0 < maxSamplesPressure &&
251  pressureRates.size() < static_cast<std::size_t>(maxSamplesPressure))
252  {
253  pressureRates.push_back(pressureRate);
254  }
255  else
256  {
257  pressureRates[sampleIndexPressureRate] = pressureRate;
258  sampleIndexPressureRate = (sampleIndexPressureRate + 1) % maxSamplesPressure;
259  }
260  if (pressureRate > 50)
261  {
262  ARMARX_IMPORTANT << "contact";
263  }
264 
265  Eigen::Quaternionf orientationQuaternion =
266  Eigen::Quaternionf(data.qw, data.qx, data.qy, data.qz);
267  if (getProperty<bool>("logData").getValue())
268  {
269 
270  if (i < 50)
271  {
272  inverseOrientation = orientationQuaternion.inverse();
273  i++;
274  }
275  Eigen::Matrix3f quatMatrix = orientationQuaternion.toRotationMatrix();
277 
278  quat4Matrix.block(0, 0, 3, 3) = quatMatrix;
279 
280  Eigen::Vector3f linearAcceleration(data.accelx, data.accely, data.accelz);
282  e.AddTimestamp();
283  e.Add("Pressure", data.pressure);
284  e.Add("PressureRate", pressureRate);
285  e.Add("RotationRate", rotationRate);
286  e.AddAsArr("Orientation", quat4Matrix);
287  e.AddAsArr("Linear Acceleration", linearAcceleration);
288  logger->log(e);
289  }
290  /*Eigen::Matrix3f rotZ;
291  rotZ(0, 0) = 0;
292  rotZ(0, 1) = 1;
293  rotZ(0, 2) = 0;
294  rotZ(1, 0) = -1;
295  rotZ(1, 1) = 0;
296  rotZ(1, 2) = 0;
297  rotZ(2, 0) = 0;
298  rotZ(2, 1) = 0;
299  rotZ(2, 2) = 1;
300  Eigen::Matrix3f rotX;
301  rotX(0, 0) = 1;
302  rotX(0, 1) = 0;
303  rotX(0, 2) = 0;
304  rotX(1, 0) = 0;
305  rotX(1, 1) = -1;
306  rotX(1, 2) = 0;
307  rotX(2, 0) = 0;
308  rotX(2, 1) = 0;
309  rotX(2, 2) = -1;*/
310  Eigen::Matrix3f rotY;
311  rotY(0, 0) = 0;
312  rotY(0, 1) = 0;
313  rotY(0, 2) = 1;
314  rotY(1, 0) = 0;
315  rotY(1, 1) = 1;
316  rotY(1, 2) = 0;
317  rotY(2, 0) = -1;
318  rotY(2, 1) = 0;
319  rotY(2, 2) = 0;
320  Eigen::Matrix3f rawOrientation = orientationQuaternion.toRotationMatrix();
321 
322  PosePtr pose = new Pose(rawOrientation, Eigen::Vector3f(100.0, 200.0, 0.0));
323  if (debugDrawerTopic)
324  {
325  debugDrawerTopic->setPoseVisu("debugdrawerlayer", "pose", pose);
326  }
327  Eigen::Quaternionf quaternion(rawOrientation);
328  data.qw = quaternion.w();
329  data.qx = quaternion.x();
330  data.qy = quaternion.y();
331  data.qz = quaternion.z();
332  ARMARX_IMPORTANT << "or " << orientationQuaternion.w() << " " << orientationQuaternion.x()
333  << " " << orientationQuaternion.y() << " " << orientationQuaternion.z();
334  if (topicPrx)
335  {
336  topicPrx->reportSensorValues(data.id,
337  data.pressure,
338  data.qw,
339  data.qx,
340  data.qy,
341  data.qz,
342  pressureRate,
343  rotationRate,
344  accelerationRate,
345  data.accelx,
346  data.accely,
347  data.accelz,
348  nowTimestamp);
349  }
350  }
351 }
352 
353 // get imu values from incoming string
355 OrientedTactileSensorUnit::getValues(std::string line)
356 {
357  SensorData data;
358  std::vector<std::string> splitValues = Split(line, " ");
359  data.id = stoi(splitValues.at(0));
360  data.pressure = std::stof(splitValues.at(1));
361  data.qw = std::stof(splitValues.at(2));
362  data.qx = std::stof(splitValues.at(3));
363  data.qy = std::stof(splitValues.at(4));
364  data.qz = std::stof(splitValues.at(5));
365  data.accelx = std::stof(splitValues.at(6));
366  data.accely = std::stof(splitValues.at(7));
367  data.accelz = std::stof(splitValues.at(8));
368  return data;
369 }
370 
371 std::string space = " ";
372 
373 bool
374 OrientedTactileSensorUnit::loadCalibration()
375 {
376  std::string calibrationStream = getProperty<std::string>("CalibrationData").getValue();
377  std::string arduinoLine;
378  while (arduinoLine.find("mode") == std::string::npos)
379  {
380  getline(arduinoIn, arduinoLine, '\n');
381  }
382  arduinoOut << "load";
383  arduinoOut.flush();
384  while (arduinoLine.find("calibration data") == std::string::npos)
385  {
386  getline(arduinoIn, arduinoLine, '\n');
387  }
388 
389  arduinoOut << calibrationStream;
390  arduinoOut.flush();
391 
392  while (arduinoLine.find("Calibration Sucessfull") == std::string::npos)
393  {
394  getline(arduinoIn, arduinoLine, '\n');
395  }
396  return true;
397 }
398 
399 bool
400 OrientedTactileSensorUnit::getCalibrationValues(std::string line)
401 {
402  std::vector<std::string> splitValues = Split(line, " ");
403  calibration.accel_offset_x = stoi(splitValues.at(0));
404  calibration.accel_offset_y = stoi(splitValues.at(1));
405  calibration.accel_offset_z = stoi(splitValues.at(2));
406  calibration.gyro_offset_x = stoi(splitValues.at(3));
407  calibration.gyro_offset_y = stoi(splitValues.at(4));
408  calibration.gyro_offset_z = stoi(splitValues.at(5));
409  calibration.mag_offset_x = stoi(splitValues.at(6));
410  calibration.mag_offset_y = stoi(splitValues.at(7));
411  calibration.mag_offset_z = stoi(splitValues.at(8));
412  calibration.accel_radius = stoi(splitValues.at(9));
413  calibration.mag_radius = stoi(splitValues.at(10));
414  std::string space = " ";
415  std::string calibrationStream = "";
416  calibrationStream =
417  calibrationStream + to_string(calibration.accel_offset_x) + space +
418  to_string(calibration.accel_offset_y) + space + to_string(calibration.accel_offset_z) +
419  space + to_string(calibration.gyro_offset_x) + space +
420  to_string(calibration.gyro_offset_y) + space + to_string(calibration.gyro_offset_z) +
421  space + to_string(calibration.mag_offset_x) + space + to_string(calibration.mag_offset_y) +
422  space + to_string(calibration.mag_offset_z) + space + to_string(calibration.accel_radius) +
423  space + to_string(calibration.mag_radius) + space;
424  ARMARX_IMPORTANT << "calibration data: " << calibrationStream;
425  return true;
426 }
armarx::OrientedTactileSensorUnit::CalibrationData::gyro_offset_y
int gyro_offset_y
Definition: OrientedTactileSensorUnit.h:90
armarx::OrientedTactileSensorUnitPropertyDefinitions
Definition: OrientedTactileSensorUnit.h:23
armarx::OrientedTactileSensorUnit::CalibrationData::accel_offset_x
int accel_offset_x
Definition: OrientedTactileSensorUnit.h:90
armarx::SimpleJsonLoggerEntry::AddAsArr
void AddAsArr(const std::string &key, const Eigen::Vector3f &vec)
Definition: SimpleJsonLoggerEntry.cpp:35
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::navigation::core::Pose
Eigen::Isometry3f Pose
Definition: basic_types.h:31
armarx::OrientedTactileSensorUnit::createPropertyDefinitions
PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: OrientedTactileSensorUnit.cpp:157
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:650
armarx::OrientedTactileSensorUnit::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: OrientedTactileSensorUnit.cpp:28
armarx::OrientedTactileSensorUnit::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: OrientedTactileSensorUnit.cpp:148
Pose.h
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:36
armarx::TimestampVariant
Definition: TimestampVariant.h:54
armarx::OrientedTactileSensorUnit::OrientedTactileSensorUnit
OrientedTactileSensorUnit()
Definition: OrientedTactileSensorUnit.cpp:18
armarx::CMakePackageFinder
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
Definition: CMakePackageFinder.h:52
armarx::OrientedTactileSensorUnit::CalibrationData::mag_radius
int mag_radius
Definition: OrientedTactileSensorUnit.h:91
armarx::SimpleJsonLogger
Definition: SimpleJsonLogger.h:42
armarx::RunningTask
Definition: ArmarXMultipleObjectsScheduler.h:36
armarx::OrientedTactileSensorUnit::CalibrationData::gyro_offset_x
int gyro_offset_x
Definition: OrientedTactileSensorUnit.h:90
armarx::OrientedTactileSensorUnit::CalibrationData::mag_offset_z
int mag_offset_z
Definition: OrientedTactileSensorUnit.h:91
StringHelpers.h
armarx::OrientedTactileSensorUnit::CalibrationData::mag_offset_x
int mag_offset_x
Definition: OrientedTactileSensorUnit.h:91
IceInternal::Handle< TimestampVariant >
GfxTL::Identity
void Identity(MatrixXX< N, N, T > *a)
Definition: MatrixXX.h:570
space
std::string space
Definition: OrientedTactileSensorUnit.cpp:371
armarx::OrientedTactileSensorUnit::CalibrationData::accel_offset_z
int accel_offset_z
Definition: OrientedTactileSensorUnit.h:90
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
TimestampVariant.h
armarx::CMakePackageFinder::getDataDir
std::string getDataDir() const
Definition: CMakePackageFinder.h:194
armarx::SimpleJsonLoggerEntry::Add
void Add(const std::string &key, const std::string &value)
Definition: SimpleJsonLoggerEntry.cpp:65
armarx::OrientedTactileSensorUnit::CalibrationData::gyro_offset_z
int gyro_offset_z
Definition: OrientedTactileSensorUnit.h:91
filename
std::string filename
Definition: VisualizationRobot.cpp:86
Eigen::Quaternionf
Quaternion< float, 0 > Quaternionf
Definition: EigenForwardDeclarations.h:61
armarx::OrientedTactileSensorUnit::CalibrationData::mag_offset_y
int mag_offset_y
Definition: OrientedTactileSensorUnit.h:91
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
armarx::control::common::getValue
T getValue(nlohmann::json &userConfig, nlohmann::json &defaultConfig, const std::string &entryName)
Definition: utils.h:71
armarx::OrientedTactileSensorUnit::CalibrationData::accel_offset_y
int accel_offset_y
Definition: OrientedTactileSensorUnit.h:90
armarx::OrientedTactileSensorUnit::CalibrationData::accel_radius
int accel_radius
Definition: OrientedTactileSensorUnit.h:91
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
CMakePackageFinder.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::Quaternion< float, 0 >
armarx::ManagedIceObject::offeringTopic
void offeringTopic(const std::string &name)
Registers a topic for retrival after initialization.
Definition: ManagedIceObject.cpp:300
IceUtil::Handle< class PropertyDefinitionContainer >
GfxTL::Matrix3f
MatrixXX< 3, 3, float > Matrix3f
Definition: MatrixXX.h:649
OrientedTactileSensorUnit.h
armarx::SimpleJsonLoggerEntry
Definition: SimpleJsonLoggerEntry.h:37
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:35
armarx::SimpleJsonLoggerEntry::AddTimestamp
void AddTimestamp()
Definition: SimpleJsonLoggerEntry.cpp:185
armarx::StateUtilFunctions::getValues
StringVariantContainerBaseMap getValues(const StateParameterMap &paramMap)
Definition: StateUtilFunctions.cpp:72
armarx::OrientedTactileSensorUnit::SensorData
Definition: OrientedTactileSensorUnit.h:80
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
Application.h