Advertisement
Guest User

original code

a guest
Jul 24th, 2014
405
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.98 KB | None | 0 0
  1. /**
  2. *******************************************************************************
  3. * @file sweepLaser/sweepLaserInterface.cpp
  4. * @brief This is an example application that interfaces with the sweeping laser
  5. * sensor.
  6. *
  7. * @b PROJECT: sweepLaser
  8. *
  9. * @par ORIGINAL AUTHOR:
  10. * Stephan Roth, September 13, 2011
  11. *
  12. * @par DEPENDENCIES:
  13. * motorInterface, sickLMS115Interface, common/libcommon
  14. *
  15. * @par DESCRIPTION:
  16. * This is an example application that interfaces with the sweeping laser
  17. * sensor. You can modify this program to meet your specific needs.
  18. * The application has the following command line:
  19. * sweepLaserInterface 192.168.2.41 /dev/ttyUSB0
  20. * Here, 192.168.2.41 should be replaced by the Sick laser's IP address
  21. * /dev/ttyUSB0 should be replaced by the serial port where the smart motor is connected.
  22. *
  23. * The program follows this basic structure
  24. *
  25. * @code
  26. * main {
  27. *   Open Sick socket connection
  28. *   Open smart motor serial port
  29. *   Home the smart motor
  30. *   Calculate the offset in (relative) encoder readings between the Sick and smart motor
  31. *   Set the laser in measurement mode
  32. *   while (!done) {
  33. *     Request a single measurement from the laser
  34. *     Receive a single measurement from the laser
  35. *     Log the laser data to file
  36. *   }
  37. *   Stop the smart motor
  38. * }
  39. *
  40. * @endcode
  41. *
  42. * If your processing code is fast enough, you can alternatively set the laser in
  43. * continuous measurement mode. In this mode, you do not need to request individual
  44. * measurements. You set the continuous measurement mode and then in the while loop
  45. * receive the measurements from the laser. You can select this mode by using the
  46. * macro #define CONTINOUS_MEASUREMENT
  47. *
  48. * @par NOTES:
  49. * Use the macro #define CONTINOUS_MEASUREMENT to use continuous measurement mode
  50. *
  51. * @par FUTURE WORK:
  52. * No future additions at this time
  53. *
  54. * @par REFERENCES:
  55. * The Sick LMS1xx family operating instructions .pdf
  56. * The animatics smart motor user guide
  57. *
  58. *
  59. * (c) Copyright 2011 Sensible Machines. All rights reserved
  60. ******************************************************************************/
  61.  
  62. /**
  63.  *@defgroup sweepLaser sweepLaser
  64.  *@brief The Sweep Laser group contains all of the applications and functions
  65.  * necessary to interface with the Sweeping Laser instrument
  66.  *
  67.  * The Sweeping Laser is a sensor useful in an array of applications from
  68.  * surveying to robotics. The sweeping laser system is a laser rangefinder
  69.  * mounted on a motor. This provides the ability to obtain a full 3-D point
  70.  * cloud of the area around the sensor.
  71.  * Libraries and example code are included that interface with all of the
  72.  * system's components including:
  73.  * The Sick LMS 1xx family of laser range finders
  74.  * The Animatics Smart Motor used to point the laser
  75.  */
  76.  
  77. #include "testSweepLaserInterface/motorInterface.h"
  78. #include "testSweepLaserInterface/sickLMS115Interface.h"
  79. #include <signal.h>
  80. #include <iostream>
  81. #include <fstream>
  82. #include <math.h>
  83.  
  84. /// Macro for outputting error messages
  85. #define errOut std::cerr << "ERROR!!:" << __FILE__ << ':' << __LINE__ << ' '
  86. /// Macro for outputting warning messages
  87. #define warnOut std::cerr << "WARNING!!:" << __FILE__ << ':' << __LINE__ << ' '
  88. /// Macro for outputting informational messages
  89. #define infoOut std::cout
  90.  
  91. bool doneG; // Global flag indicating when the application should terminate
  92.  
  93. /**
  94. *******************************************************************************
  95. * Called whenever the user presses Ctrl-c.  It signals the
  96. * application to stop by setting doneG = true;
  97. *******************************************************************************
  98. * @param[in]      sig   The signal the app received
  99. *******************************************************************************
  100. * @return  none
  101. *******************************************************************************
  102. * @note   sets doneG to true
  103. ******************************************************************************/
  104. void mcExitHandler(int sig)
  105. {
  106.   signal(SIGINT, SIG_DFL);
  107.   doneG = true;
  108. }
  109.  
  110. /**
  111. *******************************************************************************
  112. * This function calculates the offset between the smart motor and Sick
  113. * encoder. Because the Sick laser does not do proper quadrature decoding,
  114. * the Sick encoder readings are 1/4 the smart motor's. Also, because
  115. * the encoder is a relative encoder, there is also an offset between the
  116. * two readings. The function calculates the value that should be subtracted
  117. * from the Sick laser's encoder reading so that a 0 smart motor encoder reading
  118. * corresponds to a 0 Sick laser encoder reading.
  119. *******************************************************************************
  120. * @param[in]      smartMotorEncoder   The value of the smart motor's encoder
  121. * @param[in]            sickEncoder   The value of the Sick's encoder
  122. *******************************************************************************
  123. * @return  The function returns the value that should be subtracted from all
  124. *          subsequent Sick encoder readings
  125. *******************************************************************************
  126. * @note   The Sick laser does not do quadrature decoding.
  127. ******************************************************************************/
  128. int calculateSickEncoderTransform(int smartMotorEncoder, int sickEncoder)
  129. {
  130.   // Sick laser does not do quadrature encoding, so its encoder values are 1/4 the smart motor's encoder values
  131.   int sickEncoderTransformVal  = ((sickINT16)(sickEncoder << 2)) - (sickINT16)smartMotorEncoder;///4;
  132.   return sickEncoderTransformVal;
  133. }
  134.  
  135. /**
  136. *******************************************************************************
  137. * This function takes the raw encoder values from the Sick laser and transforms
  138. * them so that a 0 value on the smart motor encoder corresponds to a 0 value
  139. * on the Sick encoder.
  140. *******************************************************************************
  141. * @param[in]            sickEncoder    The encoder value received from the Sick
  142. * @param[in]   sickEncoderTransform    The value to subtract from the sickEncoder
  143. *******************************************************************************
  144. * @return  The transformed Sick encoder value
  145. *******************************************************************************
  146. * @note   The Sick outputs a 14 bit encoder value.
  147. *******************************************************************************
  148. * @sa calculateSickEncoderTransform
  149. ******************************************************************************/
  150. int sickEncoderTransform(int sickEncoder, int sickEncoderTransform)
  151. {
  152.   /* Oddly, it seems that the Sick only outputs a 14 bit encoder value? In this
  153.    * case, the sickEncoder value must be sign extended if there is a 1 in the
  154.    * 14th bit.
  155.    */
  156.   //if (sickEncoder & 0x3000) {
  157.   //  sickEncoder = sickEncoder | 0xFFFFF000;
  158.   //}
  159.   //sickEncoder -= sickEncoderTransform;
  160.   sickINT16 encoder;
  161.   encoder = sickEncoder << 2;
  162.   encoder -= (sickINT16)sickEncoderTransform;
  163.   //sickEncoder = encoder - sickEncoderTransform;
  164.   sickEncoder = encoder;
  165.   return sickEncoder;
  166. }
  167.  
  168. /**
  169. *******************************************************************************
  170. * This is the main loop for the sweepLaserInterface application. It opens the
  171. * communications with the smart motor and Sick laser, receives the scan data
  172. * from the laser and logs it to file.
  173. *******************************************************************************
  174. * @param[in]      argc   The number of arguments received
  175. * @param[in]      argv   The argument values
  176. *******************************************************************************
  177. * @return  0 on success, -1 on failure
  178. ******************************************************************************/
  179. int main(int argc, char *argv[])
  180. {
  181.   const char *port;
  182.   CMotorInterface motorInterface;
  183.   std::ofstream logOut;
  184.   CSickLMS115Interface sickInterface;
  185.   double timestamp;
  186.   TSickLMS111ScanData scanData;
  187.   int i;
  188.   bool success;
  189.  
  190.   signal(SIGINT, mcExitHandler);
  191.    
  192.   doneG = false;
  193.    
  194.   logOut.open("laserLog.log");
  195.   logOut << "%% 1) timestamp "
  196.     "2) measure# "
  197.     "3) status "
  198.     "4) syncPhaseOffset (ticks) "
  199.     "5) angleStepsPerRev (ticks) "
  200.     "6) startAngle (ticks) "
  201.     "7) endAngle (ticks) "
  202.     "8) numPoints "
  203.     "9) measLayer+echo "
  204.     "10) flags "
  205.     "11) horizAngle (ticks) "
  206.     "12) radialDist (cm) "
  207.     "13) echoPulseWidth (cm) "
  208.     "9) - 13) repeated for numPoints...\n";
  209.   char *ipAddress;
  210.   if (argc < 2) {
  211.     ipAddress = "192.168.1.11";
  212.   } else {
  213.     ipAddress = argv[1];
  214.   }
  215.   if (argc < 3) {
  216.     port = "/dev/ttyUSB0";
  217.   } else {
  218.     port = argv[2];
  219.   }
  220.   infoOut << "opening Tcp port " << ipAddress << '\n';
  221.   try {
  222.     sickInterface.initializeTcp(ipAddress);
  223.     sickInterface.queryScanConfig();
  224.   } catch (CTcpIpSocket::ETcpIpSocket &e2) {
  225.     infoOut << "Failed to open sick IP socket\n";
  226.     return(-1);
  227.   }
  228.   infoOut << "opening serial port " << port << '\n';
  229.   try {
  230.     motorInterface.open(port);
  231.   } catch (ESMSerial &exception) {
  232.     errOut << "Failed to open smart motor serial port\n";
  233.     return(-1);
  234.   }
  235.  
  236.   int position, oldPosition, positionSame;
  237.   try {
  238.     infoOut << "Homing smart motor\n";
  239.     if (!motorInterface.homeMotor()) {
  240.       errOut << "Failed to home smart motor\n";
  241.       return(-1);
  242.     }
  243.     // Wait for position to settle
  244.     positionSame = oldPosition = 0;
  245.     do {
  246.       position = motorInterface.getPosition();
  247.       infoOut << position << ' ' << oldPosition << '\n';
  248.       if (oldPosition == position) {
  249.     positionSame++;
  250.       } else {
  251.     positionSame = 0;
  252.       }
  253.       oldPosition = position;
  254.     } while (positionSame < 10);
  255.   } catch (ESMSerial &exception) {
  256.     errOut << "Failed to home smart motor\n";
  257.     return(-1);
  258.   }
  259.   infoOut << "Final Position = " << position << '\n';
  260.   // Get a single sick measurement
  261.   sickInterface.startSingleMeasurement();
  262.   success = sickInterface.getNextMeasurement(timestamp, scanData);
  263.   if (!success) {
  264.     errOut << "Failed to read the first laser scan\n";
  265.     return -1;
  266.   }
  267.   // Calculate the offset between the sick encoder and the sweep motor encoder
  268.   int sickEncoderTransformVal;
  269.   sickEncoderTransformVal = calculateSickEncoderTransform(position, scanData.sickEncoder[0].encoderPosition);
  270.   infoOut << "sick encoder transform = " << position << " - " << scanData.sickEncoder[0].encoderPosition << " = " << sickEncoderTransformVal << '\n';
  271.  
  272.   // Start the motor sweeping
  273.   motorInterface.setStart(-M_PI/2);
  274.   motorInterface.setEnd(M_PI/2);
  275.   motorInterface.setSpeed(M_PI/2);
  276.   motorInterface.startSweeping();
  277.  
  278.   sickInterface.startMeasurementMode();
  279.   // Start collecting measurements.
  280.   // Depending on how fast your processing occurs, you
  281.   // can either set the laser into continuous measurement mode or request measurements
  282.   // one at a time. In continuous measurement mode you just
  283.   // continuously call sickInterface.getNextMeasurement(...) to collect the data
  284.   // However, if you cannot process the continuous data fast enough, you are better off
  285.   // requesting one measurement at a time using sickInterface.startSingleMeasurement(...)
  286.   // and then calling sickInterface.getNextMeasurement(...) to receive the measurement
  287.   // data.
  288. #ifdef CONTINOUS_MEASUREMENT
  289.   sickInterface.startContinuousMeasurement(true);
  290. #endif
  291.   //for (i = 0; i < 10000; i++) {
  292.   while (!doneG) {
  293. #ifndef CONTINOUS_MEASUREMENT
  294.     sickInterface.startSingleMeasurement();
  295. #endif
  296.     success = sickInterface.getNextMeasurement(timestamp, scanData);
  297.     if (!success) {
  298.       doneG = true;
  299.     } else {
  300.       // compensate for encoder offset
  301.       for (i = 0; i < scanData.numberEncoders; i++) {
  302.     infoOut << "encoder (Raw) = " << scanData.sickEncoder[i].encoderPosition << '\n';
  303.     scanData.sickEncoder[i].encoderPosition = sickEncoderTransform(scanData.sickEncoder[i].encoderPosition, sickEncoderTransformVal);
  304.       }
  305.       logOut << std::fixed << timestamp << ' ';
  306.       logOut << scanData << '\n';
  307.       infoOut << '\n';
  308.       infoOut << "messageCounter = " << scanData.messageCounter << '\n';
  309.       infoOut << "scanCounter = " << scanData.scanCounter << '\n';
  310.       if (scanData.numberEncoders <= 0) {
  311.     errOut << "No encoder data from laser! Use SOPAS to verify incremental encoder configuration\n";
  312.     doneG = true;
  313.       }
  314.       // Output the raw encoder values.
  315.       // The Sick does not calculate the quadrature number of ticks, so its number of encoder ticks is
  316.       // 1/4 the number of smart motor ticks. To calculate the encoder angle in radians, use the formula
  317.       // sickEncoderRadians = encoderPosition/(encoderTicksPerRevolution/4)*2*M_PI
  318.       for (i = 0; i < scanData.numberEncoders; i++) {
  319.     infoOut << "encoder position " << ' ' << scanData.sickEncoder[i].encoderPosition << '\n';
  320.     infoOut << "encoder speed " << ' ' << scanData.sickEncoder[i].encoderSpeed << '\n';
  321.       }
  322.     } // success
  323.   }
  324.   motorInterface.stopSweeping();
  325.   motorInterface.close();
  326.   //sickInterface.endMeasurementMode();
  327.    
  328.   return 0;
  329. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement