46 #define _WIN32_WINNT 0x0501 47 #pragma warning(disable: 4996) 48 #pragma warning(disable: 4267) 62 #include "sick_scan/rosconsole_simu.hpp" 66 #include <geometry_msgs/Pose2D.h> 68 #include "sensor_msgs/Imu.h" 70 #define _USE_MATH_DEFINES 77 #ifdef DEBUG_DUMP_ENABLED 132 bool isImuMsg =
false;
133 std::string szKeyWord =
"sEA InertialMeasurementUnit";
134 std::string cmpKeyWord =
"";
135 int keyWordLen = szKeyWord.length();
136 int posTrial[] = {0, 1, 8};
137 for (
int iPos = 0; iPos <
sizeof(posTrial) /
sizeof(posTrial[0]); iPos++)
139 if (datagram_length >= (keyWordLen + posTrial[iPos]))
142 for (
int i = 0; i < keyWordLen; i++)
144 cmpKeyWord += datagram[i + posTrial[iPos]];
147 if (szKeyWord.compare(cmpKeyWord) == 0)
170 bool isImuMsg =
false;
171 std::string szKeyWord =
"sSN InertialMeasurementUnit";
172 std::string cmpKeyWord =
"";
173 int keyWordLen = szKeyWord.length();
174 if (datagram_length >= (keyWordLen + 8))
176 for (
int i = 0; i < keyWordLen; i++)
178 cmpKeyWord += datagram[i + 8];
181 if (szKeyWord.compare(cmpKeyWord) == 0)
202 float tmpArr[13] = {0};
204 unsigned char *receiveBuffer = (
unsigned char *) datagram;
210 unsigned char *bufPtr = (
unsigned char *) datagram;
211 #ifdef DEBUG_DUMP_TO_CONSOLE_ENABLED 214 memcpy(&timeStamp, receiveBuffer + 36 + 13 * 4, 4);
217 for (
int i = 0; i < 13; i++)
219 memcpy(&(tmpArr[i]), receiveBuffer + adrOffset, 4);
238 double angleVelMultiplier = 1.0;
268 bool isImuMsg =
false;
269 std::string szKeyWord =
"sSN InertialMeasurementUnit";
270 int keyWordLen = szKeyWord.length();
271 if (datagram_length >= keyWordLen)
275 ptr = strstr(datagram, szKeyWord.c_str());
278 int offset = ptr - datagram;
279 if ((offset == 0) || (offset == 1))
296 bool dumpData =
false;
297 int verboseLevel = 0;
301 int HEADER_FIELDS = 32;
306 std::vector<char *> fields;
307 fields.reserve(datagram_length / 2);
310 std::vector<char> datagram_copy_vec;
311 datagram_copy_vec.resize(datagram_length + 1);
312 char *datagram_copy = &(datagram_copy_vec[0]);
314 if (verboseLevel > 0)
316 ROS_WARN(
"Verbose LEVEL activated. Only for DEBUG.");
320 strncpy(datagram_copy, datagram, datagram_length);
321 datagram_copy[datagram_length] = 0;
325 cur_field = strtok(datagram,
" ");
327 while (cur_field != NULL)
329 fields.push_back(cur_field);
331 cur_field = strtok(NULL,
" ");
336 count = fields.size();
343 IMU_TOKEN_QUATERNION_W,
344 IMU_TOKEN_QUATERNION_X,
345 IMU_TOKEN_QUATERNION_Y,
346 IMU_TOKEN_QUATERNION_Z,
347 IMU_TOKEN_QUATERNION_ACCURACY,
348 IMU_TOKEN_ANGULAR_VELOCITY_X,
349 IMU_TOKEN_ANGULAR_VELOCITY_Y,
350 IMU_TOKEN_ANGULAR_VELOCITY_Z,
351 IMU_TOKEN_ANGULAR_VELOCITY_RELIABILITY,
352 IMU_TOKEN_LINEAR_ACCELERATION_X,
353 IMU_TOKEN_LINEAR_ACCELERATION_Y,
354 IMU_TOKEN_LINEAR_ACCELERATION_Z,
355 IMU_TOKEN_LINEAR_ACCELERATION_RELIABILITY,
358 for (
int i = 0; i < IMU_TOKEN_NUM; i++)
362 unsigned long int uliDummy;
363 uliDummy = strtoul(fields[i], NULL, 16);
367 case IMU_TOKEN_TIMESTAMP:
370 case IMU_TOKEN_QUATERNION_X:
371 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
374 case IMU_TOKEN_QUATERNION_Y:
375 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
378 case IMU_TOKEN_QUATERNION_Z:
379 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
382 case IMU_TOKEN_QUATERNION_W:
383 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
387 case IMU_TOKEN_QUATERNION_ACCURACY:
388 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
391 case IMU_TOKEN_ANGULAR_VELOCITY_X:
392 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
395 case IMU_TOKEN_ANGULAR_VELOCITY_Y:
396 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
399 case IMU_TOKEN_ANGULAR_VELOCITY_Z:
400 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
403 case IMU_TOKEN_ANGULAR_VELOCITY_RELIABILITY:
404 uiValue = (
UINT16) (0xFFFF & uliDummy);
408 case IMU_TOKEN_LINEAR_ACCELERATION_X:
409 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
412 case IMU_TOKEN_LINEAR_ACCELERATION_Y:
413 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
416 case IMU_TOKEN_LINEAR_ACCELERATION_Z:
417 memcpy(&floatDummy, &uliDummy,
sizeof(
float));
420 case IMU_TOKEN_LINEAR_ACCELERATION_RELIABILITY:
421 uiValue = (
UINT16) (0xFFFF & uliDummy);
440 double wxyz_test_vec[] = { 0.723, 0.440, 0.022, -0.532};
451 double roll, pitch, yaw;
452 m.
getRPY(roll, pitch, yaw);
454 printf(
"Test result\n");
455 printf(
"Roll 45.054 [deg]: %8.3lf [deg]\n", roll * rad2deg);
456 printf(
"Pitch: 30.004 [deg]: %8.3lf [deg]\n", pitch * rad2deg);
457 printf(
"Yaw: -60.008 [deg]: %8.3lf [deg]\n", yaw * rad2deg);
465 double roll, pitch, yaw;
469 q.x = wxyz_test_vec[1];
470 q.y = wxyz_test_vec[2];
471 q.z = wxyz_test_vec[3];
472 q.w = wxyz_test_vec[0];
478 double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
479 double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
480 angles.roll = std::atan2(sinr_cosp, cosr_cosp);
483 double sinp = 2 * (q.w * q.y - q.z * q.x);
484 if (std::abs(sinp) >= 1)
485 angles.pitch = std::copysign(M_PI / 2, sinp);
487 angles.pitch = std::asin(sinp);
490 double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
491 double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
492 angles.yaw = std::atan2(siny_cosp, cosy_cosp);
494 printf(
"Test result (should be similiar to the result above)\n");
495 printf(
"Roll 45 [deg]: %8.3lf [deg]\n", angles.roll * rad2deg);
496 printf(
"Pitch: 30 [deg]: %8.3lf [deg]\n", angles.pitch * rad2deg);
497 printf(
"Yaw: -60 [deg]: %8.3lf [deg]\n", angles.yaw * rad2deg);
507 std::string imuTestStr =
"sSN IMUData 34FEEDF 3F7FF800 BBBC0000 3C848000 00000000 00000000 00000000 3B0B9AB1 00000000 3 BE9F6AD9 BDDCBB53 411D2CF1 0";
508 const char imuTestBinStr[] =
531 "\x02\x02\x02\x02\x00\x00\x00\x58" 532 "\x73\x53\x4e\x20\x49\x6e\x65\x72\x74\x69\x61\x6c\x4d\x65" 533 "\x61\x73\x75\x72\x65\x6d\x65\x6e\x74\x55\x6e\x69\x74\x20\xbe\xa4" 534 "\xe1\x1c\x3b\x6b\x5d\xe5\x41\x1c\x6e\xad\xbb\x0b\xa1\x6f\xbb\x0b" 535 "\xa1\x6f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" 536 "\x00\x00\x3f\x7f\xec\x00\x3a\x60\x00\x00\x3c\xcd\x00\x00\x39\xa0" 537 "\x00\x00\x00\x00\x00\x02\x1c\x7e\x6c\x01\x20";
539 char *datagramPtr = (
char *) imuTestStr.c_str();
540 int datagramLen = imuTestStr.size();
547 datagramPtr = (
char *) imuTestBinStr;
548 datagramLen =
sizeof(imuTestBinStr) /
sizeof(imuTestBinStr[0]);
558 bool useBinaryProtocol)
563 sensor_msgs::Imu imuMsg_;
566 static double lastRoll = 0.0;
567 static double lastPitch = 0.0;
568 static double lastYaw = 0.0;
570 static bool firstTime =
true;
600 if (useBinaryProtocol)
615 (uint32_t) (imuValue.
TimeStamp() & 0xFFFFFFFF));
621 imuMsg_.header.stamp = timeStamp;
622 imuMsg_.header.seq = 0;
631 imuMsg_.orientation_covariance[0] = 1.0;
633 double roll, pitch, yaw;
640 imuMsg_.orientation.x,
641 imuMsg_.orientation.y,
642 imuMsg_.orientation.z,
643 imuMsg_.orientation.w);
645 m.
getRPY(roll, pitch, yaw);
646 #else // barebone implementation without include tf.h 653 double roll, pitch, yaw;
657 q.x = imuMsg_.orientation.x;
658 q.y = imuMsg_.orientation.y;
659 q.z = imuMsg_.orientation.z;
660 q.w = imuMsg_.orientation.w;
666 double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
667 double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
668 angles.roll = std::atan2(sinr_cosp, cosr_cosp);
671 double sinp = 2 * (q.w * q.y - q.z * q.x);
672 if (std::abs(sinp) >= 1)
673 angles.pitch = std::copysign(M_PI / 2, sinp);
675 angles.pitch = std::asin(sinp);
678 double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
679 double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
680 angles.yaw = std::atan2(siny_cosp, cosy_cosp);
683 pitch = angles.pitch;
693 lastTimeStamp = timeStamp;
699 #ifdef DEBUG_DUMP_ENABLED 721 double timeDiff = timeDiffRos.
toSec();
724 double angleDiffX = roll - lastRoll;
725 double angleDiffY = pitch - lastPitch;
726 double angleDiffZ = yaw - lastYaw;
730 double angleAngleApproxX = angleDiffX / timeDiff;
731 double angleAngleApproxY = angleDiffY / timeDiff;
732 double angleAngleApproxZ = angleDiffZ / timeDiff;
734 imuMsg_.angular_velocity.x = angleAngleApproxX;
735 imuMsg_.angular_velocity.y = angleAngleApproxY;
736 imuMsg_.angular_velocity.z = angleAngleApproxZ;
740 lastTimeStamp = timeStamp;
755 for (
int i = 0; i < 9; i++)
757 imuMsg_.angular_velocity_covariance[i] = 0.00;
758 imuMsg_.linear_acceleration_covariance[i] = 0.00;
759 imuMsg_.orientation_covariance[i] = 0.00;
765 imuMsg_.angular_velocity_covariance[0] = 0.02;
766 imuMsg_.angular_velocity_covariance[1] = 0;
767 imuMsg_.angular_velocity_covariance[2] = 0;
768 imuMsg_.angular_velocity_covariance[3] = 0;
769 imuMsg_.angular_velocity_covariance[4] = 0.02;
770 imuMsg_.angular_velocity_covariance[5] = 0;
771 imuMsg_.angular_velocity_covariance[6] = 0;
772 imuMsg_.angular_velocity_covariance[7] = 0;
773 imuMsg_.angular_velocity_covariance[8] = 0.02;
775 imuMsg_.linear_acceleration_covariance[0] = 0.04;
776 imuMsg_.linear_acceleration_covariance[1] = 0;
777 imuMsg_.linear_acceleration_covariance[2] = 0;
778 imuMsg_.linear_acceleration_covariance[3] = 0;
779 imuMsg_.linear_acceleration_covariance[4] = 0.04;
780 imuMsg_.linear_acceleration_covariance[5] = 0;
781 imuMsg_.linear_acceleration_covariance[6] = 0;
782 imuMsg_.linear_acceleration_covariance[7] = 0;
783 imuMsg_.linear_acceleration_covariance[8] = 0.04;
785 imuMsg_.orientation_covariance[0] = 0.0025;
786 imuMsg_.orientation_covariance[1] = 0;
787 imuMsg_.orientation_covariance[2] = 0;
788 imuMsg_.orientation_covariance[3] = 0;
789 imuMsg_.orientation_covariance[4] = 0.0025;
790 imuMsg_.orientation_covariance[5] = 0;
791 imuMsg_.orientation_covariance[6] = 0;
792 imuMsg_.orientation_covariance[7] = 0;
793 imuMsg_.orientation_covariance[8] = 0.0025;
797 imuMsg_.angular_velocity_covariance[0] = 0;
798 imuMsg_.angular_velocity_covariance[1] = 0;
799 imuMsg_.angular_velocity_covariance[2] = 0;
800 imuMsg_.angular_velocity_covariance[3] = 0;
801 imuMsg_.angular_velocity_covariance[4] = 0;
802 imuMsg_.angular_velocity_covariance[5] = 0;
803 imuMsg_.angular_velocity_covariance[6] = 0;
804 imuMsg_.angular_velocity_covariance[7] = 0;
805 imuMsg_.angular_velocity_covariance[8] = 0;
807 imuMsg_.linear_acceleration_covariance[0] = 0;
808 imuMsg_.linear_acceleration_covariance[1] = 0;
809 imuMsg_.linear_acceleration_covariance[2] = 0;
810 imuMsg_.linear_acceleration_covariance[3] = 0;
811 imuMsg_.linear_acceleration_covariance[4] = 0;
812 imuMsg_.linear_acceleration_covariance[5] = 0;
813 imuMsg_.linear_acceleration_covariance[6] = 0;
814 imuMsg_.linear_acceleration_covariance[7] = 0;
815 imuMsg_.linear_acceleration_covariance[8] = 0;
817 imuMsg_.orientation_covariance[0] = 0;
818 imuMsg_.orientation_covariance[1] = 0;
819 imuMsg_.orientation_covariance[2] = 0;
820 imuMsg_.orientation_covariance[3] = 0;
821 imuMsg_.orientation_covariance[4] = 0;
822 imuMsg_.orientation_covariance[5] = 0;
823 imuMsg_.orientation_covariance[6] = 0;
824 imuMsg_.orientation_covariance[7] = 0;
825 imuMsg_.orientation_covariance[8] = 0;
static void imuParserTest()
bool isImuDatagram(char *datagram, size_t datagram_length)
UINT16 LinearAccelerationReliability() const
void publish(const boost::shared_ptr< M > &message) const
int pushData(double timeStamp, std::string info, double val)
static SoftwarePLL & instance()
bool isImuAckDatagram(char *datagram, size_t datagram_length)
float AngularVelocityZ() const
float LinearAccelerationY() const
SickScanCommon * commonPtr
int parseAsciiDatagram(char *datagram, size_t datagram_length, SickScanImuValue *imValuePtr)
Parsing Ascii datagram.
float AngularVelocityX() const
bool isImuBinaryDatagram(char *datagram, size_t datagram_length)
Checking ASCII diagram for imu message type.
void swap_endian(unsigned char *ptr, int numBytes)
Universal swapping function.
TFSIMD_FORCE_INLINE const tfScalar & y() const
int parseDatagram(ros::Time timeStamp, unsigned char *receiveBuffer, int actual_length, bool useBinaryProtocol)
float QuaternionAccuracy() const
bool getCorrectedTimeStamp(uint32_t &sec, uint32_t &nanoSec, uint32_t tick)
float QuaternionY() const
void getRPY(tfScalar &roll, tfScalar &pitch, tfScalar &yaw, unsigned int solution_number=1) const
float LinearAccelerationZ() const
ros::Publisher imuScan_pub_
TFSIMD_FORCE_INLINE const tfScalar & x() const
bool isImuAsciiDatagram(char *datagram, size_t datagram_length)
Checking ASCII diagram for imu message type.
float AngularVelocityY() const
float QuaternionZ() const
static DataDumper & instance()
TFSIMD_FORCE_INLINE const tfScalar & z() const
static void quaternion2rpyTest()
Test barebone implemetation from quaternio to euler (Roll-Pitch-Yaw-Sequence) to avoid problems using...
float LinearAccelerationX() const
TFSIMD_FORCE_INLINE const tfScalar & w() const
float QuaternionW() const
UINT16 AngularVelocityReliability() const
int parseBinaryDatagram(char *datagram, size_t datagram_length, SickScanImuValue *imValuePtr)
Parsing Ascii datagram.
float QuaternionX() const
int dumpUcharBufferToConsole(unsigned char *buffer, int bufLen)
double simpleFmodTwoPi(double angle)
Checking angle to be in the interval [-M_PI,M_PI] Of course you can also use fmod, e.g. fmod(angle + M_PI,2*M_PI) - M_PI.