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