Advertisement
Guest User

Untitled

a guest
Nov 1st, 2017
267
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 19.23 KB | None | 0 0
  1. #include <string>
  2. #include <ros/ros.h>
  3. #include <sensor_msgs/JointState.h>
  4. #include <tf/transform_broadcaster.h>
  5.  
  6. //integrating LJ code:///////////////////block #1 - start///////////////////////
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <errno.h>
  10. #include "labjackusb.h"
  11.  
  12. //MO Defines how long the Feedback command is
  13. #define FEEDBACK_COMMAND_LENGTH 16
  14.  
  15. //MO Defines how long the Feedback response is
  16. #define FEEDBACK_RESPONSE_LENGTH 12
  17.  
  18. // Takes a buffer and calculates the checksum8 of it.
  19. BYTE calculateChecksum8(BYTE* buffer);
  20.  
  21. // Takes a buffer and length, and calculates the checksum16 of the buffer.
  22. int calculateChecksum16(BYTE* buffer, int len);
  23.  
  24. //******************************/* LabJack Related Helper Functions Protoypes */
  25.  
  26. //MO Demonstrates how to build the feedback packet.
  27. void buildFeedbackBytes(BYTE * sendBuffer);
  28.  
  29. // Demonstrates how to check a response for errors.
  30. int checkResponseForErrors(BYTE * recBuffer);
  31.  
  32. // Demonstrates how to parse the response of Feedback.
  33. double parseFeedbackBytes(BYTE * recBuffer);
  34. //integrating LJ code:///////////////////block #1 - END/////////////////////////
  35.  
  36.  
  37. int main(int argc, char** argv)
  38. {
  39.     //integrating LJ code:///////////////////block #2 - START////////////////////
  40.     //Setup the variables we will need.
  41.     int r = 0; // For checking return values
  42.     HANDLE devHandle = 0; //NOTE: a handle is an alias for a void pointer!
  43.  
  44.     //create two more buffers to hold the feedback send and recieve payload
  45.     BYTE feedbackSendBuffer[FEEDBACK_COMMAND_LENGTH], feedbackRecieveBuffer[FEEDBACK_RESPONSE_LENGTH];
  46.    
  47.     // Open the U3 - they are calling a method which returns a HANDLE data type.
  48.     devHandle = LJUSB_OpenDevice(1, 0, U3_PRODUCT_ID);
  49.    
  50.     //if handle does not point to a U3
  51.     if( devHandle == NULL )
  52.     {
  53.         //this works. If no U3 is plugged I get this error.
  54.         printf("Couldn't open U3. Please connect one and try again.\n");
  55.         exit(-1);
  56.     }
  57.  
  58.     //build the Feedback command
  59.     buildFeedbackBytes(feedbackSendBuffer);
  60.     //integrating LJ code:///////////////////block #2 - END/////////////////////
  61.  
  62.     ros::init(argc, argv, "jimmy_state_publisher");
  63.     ros::NodeHandle n;
  64.     ros::Publisher joint_pub = n.advertise<sensor_msgs::JointState>("joint_states", 1);
  65.     tf::TransformBroadcaster broadcaster;
  66.     ros::Rate loop_rate(30);
  67.  
  68.     //has to be negetive to accuratly reflect my direction of rotation
  69.     const double degreeToRadConst = -(M_PI/180);
  70.  
  71.     // robot state
  72.     //MO COMMENTED OUT//double tilt = 0, tinc = degree, swivel=0, angle=0, height=0, hinc=0.005;/////////////////////////////
  73.     //of the two joints that are initialized to 0 (tilt & swivel), only swivel is
  74.     //continious (which is what my LMS shaft is). So I will keep it at zero and
  75.     // also keep the other variables.
  76.     //double tinc = degree, rotating_lms_shaft_to_body_joint=0, angle=0, height=0, hinc=0.005;
  77.     double rotating_lms_shaft_to_body_joint=0, lmsAngle=0;
  78.    
  79.     //more variables that are my joints
  80.     double body_to_left_drive_wheel_joint=0, body_to_right_drive_wheel_joint=0,
  81.     left_castor_base_to_body_joint=0, left_castor_wheel_to_plate_joint=0,
  82.     right_castor_base_to_body_joint=0, right_castor_wheel_to_plate_joint=0;
  83.  
  84.     // message declarations
  85.     geometry_msgs::TransformStamped odom_trans;
  86.     sensor_msgs::JointState joint_state;
  87.     odom_trans.header.frame_id = "odom";
  88.     //mo commented out//odom_trans.child_frame_id = "axis"; ////////////////////////////////////////////////////////
  89.     //I understand that here we need the base link that forms the robot
  90.     odom_trans.child_frame_id = "body_link";
  91.  
  92.     while (ros::ok()) {
  93.         //update joint_state
  94.         joint_state.header.stamp = ros::Time::now();
  95.         joint_state.name.resize(7); //resize array
  96.         joint_state.position.resize(7); //resize array
  97.         joint_state.name[0] ="rotating_lms_shaft_to_body_joint"; //name of joint
  98.         joint_state.position[0] = rotating_lms_shaft_to_body_joint; //value
  99.         joint_state.name[1] ="body_to_left_drive_wheel_joint";
  100.         joint_state.position[1] = body_to_left_drive_wheel_joint;
  101.         joint_state.name[2] ="body_to_right_drive_wheel_joint";
  102.         joint_state.position[2] = body_to_right_drive_wheel_joint;
  103.         joint_state.name[3] ="left_castor_base_to_body_joint";
  104.         joint_state.position[3] = left_castor_base_to_body_joint;
  105.         joint_state.name[4] ="left_castor_wheel_to_plate_joint";
  106.         joint_state.position[4] = left_castor_wheel_to_plate_joint;
  107.         joint_state.name[5] ="right_castor_base_to_body_joint";
  108.         joint_state.position[5] = right_castor_base_to_body_joint;
  109.         joint_state.name[6] ="right_castor_wheel_to_plate_joint";
  110.         joint_state.position[6] = right_castor_wheel_to_plate_joint;
  111.  
  112.         //integrating LJ code:///////////////////block #3 - START///////////////////
  113.         // This is a function in the driver "labjackusb.c".
  114.         // short story: Write the command to the device.
  115.         // Writes to a device with a 1 second timeout.  If the timeout time elapses and
  116.         // no data is transferred the USB request is aborted and the call returns.
  117.         // Returns the number of bytes written, or 0 on error and errno is set.
  118.         // hDevice (arg 1) = The handle for your device. Handle data type
  119.         // pBuff (arg 2) = The buffer to be written to the device. Byte data type
  120.         // count = The number of bytes to write. unsigned long data type.
  121.         // This function replaces the deprecated LJUSB_BulkWrite, which required the
  122.         // endpoint.
  123.         // LJUSB_Write( handle, sendBuffer, length of sendBuffer )
  124.         //NOTE: the reason it is pointng to the return value of the method is because
  125.         //the return indicates if we had a fault or if we have valid data. If you send
  126.         // a BS command it will time out and go to the next statement....
  127.         r = LJUSB_Write( devHandle, feedbackSendBuffer, FEEDBACK_COMMAND_LENGTH );
  128.  
  129.         //MO check if the system call was successful or not.
  130.         if( r != FEEDBACK_COMMAND_LENGTH )
  131.         {
  132.             printf("#1 An error occurred when trying to write the buffer. The error was: %d\n", errno);
  133.             // *Always* close the device when you error out.
  134.             LJUSB_CloseDevice(devHandle);
  135.             exit(-1);
  136.         }
  137.         //this is a function from the driver labjackusb.c.
  138.         // Short: Read the result from the device.
  139.         // Reads from a device with a 1 second timeout. If the timeout time elapses and
  140.         // no data is transferred the USB request is aborted and the call returns.
  141.         // Returns the number of bytes read, or 0 on error and errno is set.
  142.         // hDevice (arg 1) = The handle for your device. Type Handle
  143.         // pBuff (arg 2) = The buffer to be filled in with bytes from the device. Byte.
  144.         // count (arg 3) = The number of bytes expected to be read. Unsigned long.
  145.         // This function replaces the deprecated LJUSB_BulkRead, which required the
  146.         // endpoint.
  147.         // LJUSB_Read( handle, recBuffer, number of bytes to read)
  148.         r = LJUSB_Read( devHandle, feedbackRecieveBuffer, FEEDBACK_RESPONSE_LENGTH );
  149.  
  150.         //checks to see if the correct number of bytes was recieved (or a value that
  151.         // represents an error code).
  152.         if( r != FEEDBACK_RESPONSE_LENGTH )
  153.         {
  154.             printf("#2 An error occurred when trying to read from the U3. The error was: %d\n", errno);
  155.             LJUSB_CloseDevice(devHandle);
  156.             exit(-1);
  157.         }
  158.    
  159.         //Check the command for errors. Seems pretty straight forward... All the
  160.         // check summing is already coded.
  161.         if( checkResponseForErrors(feedbackRecieveBuffer) != 0 )
  162.         {
  163.             LJUSB_CloseDevice(devHandle);
  164.             exit(-1);
  165.         }
  166.  
  167.         //process the response from the feedback command. For now I am printing it
  168.         // to the screen.
  169.         lmsAngle = parseFeedbackBytes(feedbackRecieveBuffer);
  170.  
  171.         //convert our degree value to radians
  172.         lmsAngle = lmsAngle * degreeToRadConst;
  173.         //integrating LJ code:///////////////////block #3 - END/////////////////////
  174.  
  175.         //update transform - odom to be static offset from the origin
  176.         odom_trans.header.stamp = ros::Time::now();
  177.         odom_trans.transform.translation.x = 1;
  178.         odom_trans.transform.translation.y = 1;
  179.         odom_trans.transform.translation.z = 0;
  180.         odom_trans.transform.rotation = tf::createQuaternionMsgFromYaw(0);
  181.        
  182.  
  183.         //send the joint state and transform
  184.         joint_pub.publish(joint_state);
  185.         broadcaster.sendTransform(odom_trans);
  186.  
  187.         // Create new robot state
  188.         //tilt += tinc;
  189.         //if (tilt<-.5 || tilt>0) tinc *= -1;
  190.         //height += hinc;
  191.         //if (height>.2 || height<0) hinc *= -1;
  192.         //swivel += degree;
  193.         //angle += degree/4;
  194.  
  195.         //repeating what is done above
  196.         //rotating_lms_shaft_to_body_joint += tinc;
  197.         //if (rotating_lms_shaft_to_body_joint<-.5 || rotating_lms_shaft_to_body_joint>0) tinc *= -1;
  198.         //height += hinc;
  199.         //if (height>.2 || height<0) hinc *= -1;
  200.         //rotating_lms_shaft_to_body_joint += degree;
  201.         //angle += degree/4;
  202.        
  203.         rotating_lms_shaft_to_body_joint = lmsAngle;
  204.  
  205.         //publish zeroes to keep everything happy
  206.         body_to_left_drive_wheel_joint=0;
  207.         body_to_right_drive_wheel_joint=0;
  208.         left_castor_base_to_body_joint=0;
  209.         left_castor_wheel_to_plate_joint=0;
  210.         right_castor_base_to_body_joint=0;
  211.         right_castor_wheel_to_plate_joint=0;
  212.    
  213.         // This will adjust as needed per iteration
  214.         loop_rate.sleep();
  215.     }
  216.  
  217.     //integrating LJ code:///////////////////block #4 - START///////////////////
  218.     //Close the device.
  219.     LJUSB_CloseDevice(devHandle);
  220.     //integrating LJ code:///////////////////block #4 - END/////////////////////
  221.  
  222.     return 0;
  223. }
  224.  
  225. //integrating LJ code:///////////////////block #5 - START///////////////////////
  226. // Uses information from section 5.2.5 of the U3 User's Guide to make a Feedback
  227. // packet.
  228. // http://labjack.com/support/u3/users-guide/5.2.5
  229. void buildFeedbackBytes(BYTE * sendBuffer)
  230. {
  231.     int checksum = 0; //MO initialize the integer
  232.    
  233.     // Build up the bytes
  234.     //sendBuffer[0] = Checksum8 //done later on in method
  235.     sendBuffer[1] = 0xF8; //must be 0xF8 according to datasheet
  236.     sendBuffer[2] = 0x05; //
  237.     sendBuffer[3] = 0x00; //must be 0x00 according to datasheet
  238.     //sendBuffer[4] = Checksum16 (LSB)
  239.     //sendBuffer[5] = Checksum16 (MSB)
  240.    
  241.     sendBuffer[6] = 0x00; //echo byte. used make sure results are in order.
  242.  
  243.     /*This is the IOtype which scans all the inputs.*/
  244.     //Mask (bytes 7 to 9) - this is a write mask. If the bit is an output and set
  245.     // to 1, it will be modified. if mask is set to 0 it will only be read. In
  246.     // my case this is not an input so the mask is kind of useless.
  247.     sendBuffer[7] = 29; //IOType PortDirWrite.
  248.     sendBuffer[8] = 0; //mask of FIO are 00000000 - making them all read
  249.     sendBuffer[9] = 0; //mask of EIO are 00000000 - making them all read
  250.     sendBuffer[10] = 0; //mask of CIO are 0000 - making them all read
  251.  
  252.     //direction sets the point as an input or output. 1 is an input, 0 is an output.
  253.     sendBuffer[11] = 0; //all FIO are 00000000 - making 0 to 7 inputs (respectivly).
  254.     sendBuffer[12] = 0; //all EIO are 00000000 - making 0 to 7 inputs (respectivly).
  255.     sendBuffer[13] = 0; //all FIO are 0000 - making 0 to 3 inputs (respectivly).
  256.  
  257.     sendBuffer[14] = 26; //IOType is PortStateRead
  258.     sendBuffer[15] = 0; // padding byte
  259.        
  260.     // Calculate and set the checksum16
  261.     checksum = calculateChecksum16(sendBuffer, FEEDBACK_COMMAND_LENGTH);
  262.     sendBuffer[4] = (BYTE)( checksum & 0xff );
  263.     sendBuffer[5] = (BYTE)( (checksum / 256) & 0xff );
  264.    
  265.     // Calculate and set the checksum8
  266.     sendBuffer[0] = calculateChecksum8(sendBuffer);
  267.    
  268.     // The bytes have been set, and the checksum calculated. We are ready to
  269.     // write to the U3.
  270. }
  271.  
  272. ////////////////////////////////////code from web to convert////////////////////////////////////////////////////
  273.  
  274. // this method came from (in the comments):
  275. //https://www.daniweb.com/programming/software-development/code/216355/gray-code-conversion
  276. //it does an amazing job of conversion from Gray code to Binary!!!!!
  277. unsigned int gray_to_binary(unsigned int bits)
  278. {
  279.  
  280.   bits ^= bits >> 16; // remove if word is 16 bits or less
  281.   bits ^= bits >>  8; // remove if word is 8 bits or less
  282.   bits ^= bits >>  4;
  283.   bits ^= bits >>  2;
  284.   bits ^= bits >>  1;
  285.   return bits;
  286. }
  287.  
  288. //////////////////////////////////////////////////////////////////////
  289.  
  290. // Parses the Feedback packet into something useful.
  291. double parseFeedbackBytes(BYTE * recBuffer)
  292. {
  293.     //store the encoder status in variables of type short. In my machine (W530)
  294.     // they are 4 bytes wide (FFFFFFFF)
  295.     //int fio = recBuffer[9]; //FIO - don't care about it so it's commented out.
  296.     short eio = recBuffer[10]; //EIO - care about bits 0 to 5 (inclusive)
  297.     short cio = recBuffer[11]; //CIO - care about all 4 bits (0 to 3).
  298.  
  299.     /*  //for testing only
  300.     printf("  Results of Feedback:\n");
  301.     printf("  NOTE: 1 == no signal && 0 == signal recieved\n");
  302.     printf("  Result on element 9 (NOT USED - FIO bbbb bbbb) = %02x\n", element9 );
  303.     printf("  Result on element 10 (EIO bbbb bbbb)= %02x\n", element10 );
  304.     printf("  Result on element 11 (CIO bbbb) = %01x\n", element11);
  305.     */
  306.  
  307. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  308.     //CIO3 is 2^9 (MSB), CIO2 is 2^8, CIO1 is 2^7, and CIO0 is 2^6. By multiplying
  309.     //CIO by 0x100 (256 decimal or 2^8) we shift the CIO values 8 bits to the left;
  310.     //this is a prerequisite to concat CIO and EIO
  311.     cio = recBuffer[11];
  312.     //printf("CIO state pre-shift: = %08x\n", cio);///////////TEST ONLY
  313.     cio = cio * 0x100;
  314.     //printf("CIO state post shift: = %08x\n", cio); //////////TEST ONLY
  315.  
  316.     //now that CIO is represented by the 3rd LSB byte, lets concat CIO and EIO.
  317.     //Basically EIO will now occupy the 1st & 2nd LSB byte.
  318.     eio = recBuffer[10];
  319.     //printf("EIO state: = %08x\n", eio);/////////////////////TEST ONLY
  320.     short cioAndEioConcated = cio + eio;
  321.     //printf("CIO + EIO state: = %08x\n", cioAndEioConcated);//////////TEST ONLY
  322.  
  323.     //I got everything working with if statements, but now I am opting to do it
  324.     // with bitwise operators. This shifts all the bits over 2 bits
  325.     short cioAndEioRightShifted = cioAndEioConcated >> 2;
  326.     //printf("cio and eio after bitshifting right 2 bits: %08x\n", cioAndEioRightShifted); /////TEST ONLY
  327.  
  328.     //the final value due to size of short (4 bytes on my machine) looks like
  329.     //this: 00000xxx (where the xxx is the encoder status). I am going to convert
  330.     // all the zeros to F's. This is a prerequisite to make all the lit LEDs on
  331.     //the optocoupler board appear as 1 in the code instead of 0 (current state)
  332.     short cioAndEioPadded = cioAndEioRightShifted + 0xFFFFFC00;
  333.     //printf("Value with leading zeroes to F's: %08x\n", cioAndEioPadded);///////////TEST ONLY
  334.  
  335.     //now I can use the ~ bitwise operator to flip all the 1's to zeros, and zeros
  336.     // to 1's. this will make everything easier as currely an encoder high is
  337.     //shown as a 0... which is frustrating.
  338.     short cioAndEioFinalValue = ~cioAndEioPadded;
  339.     //printf("final value with 1's representing a high: %08x\n", cioAndEioFinalValue);////////TEST ONLY
  340.  
  341.     //At this point I need to convert the Gray code to binary. I found the code
  342.     // that does it in the most efficient way. See method above this one, called
  343.     // gray_to_binary(unsigned int). I have also discovered that when we convert
  344.     //Gray code to binary, the binary is proportional to degrees (as it grows
  345.     // from 0 to 1023, the degrees increase proportionally from 0 to 360).
  346.     short binaryFinalValue = gray_to_binary(cioAndEioFinalValue);
  347.     //printf("binary final value: %08x\n", binaryFinalValue); ////TEST ONLY
  348.  
  349.     //now that we have the binary value, and I verified that the Gray code does
  350.     //convert to binary, and the binary increases proportionally to position.
  351.     double binaryValueAsDouble = binaryFinalValue;
  352.     double degrees = (binaryValueAsDouble * 360) / 1024;
  353.  
  354.     //final output in degrees:
  355.     //printf("The LMS is pointing at: %04f\n\n\n\n\n\n\n", degrees);
  356.  
  357.     return degrees;
  358. }
  359.  
  360.  
  361. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  362.  
  363.  
  364.  
  365.  
  366. //******************************MO - Finish************************************
  367.  
  368. // Checks the response for any errors.
  369. int checkResponseForErrors(BYTE * recBuffer)
  370. {
  371.     if(recBuffer[0] == 0xB8 && recBuffer[1] == 0xB8)
  372.     {
  373.         // If the packet is [ 0xB8, 0xB8 ], that's a bad checksum.
  374.         printf("The U3 detected a bad checksum. Double check your checksum calculations and try again.\n");
  375.         return -1;
  376.     }
  377.     else if (recBuffer[1] != 0xF8 || recBuffer[2] != 0x03 || recBuffer[3] != 0x00)
  378.     {
  379.         //printf("the results of buffer 1: %d \n", recBuffer[1]); //248
  380.         //printf("the results of buffer 2: %d \n", recBuffer[2]); //3
  381.         //printf("the results of buffer 3: %d \n", recBuffer[3]); //0
  382.  
  383.         // Make sure the command bytes match what we expect.
  384.         printf("Got the wrong command bytes back from the U3.\n");
  385.         return -1;
  386.     }
  387.    
  388.     // Calculate the checksums.
  389.     int checksum16 = calculateChecksum16(recBuffer, FEEDBACK_RESPONSE_LENGTH);
  390.     BYTE checksum8 = calculateChecksum8(recBuffer);
  391.    
  392.     if ( checksum8 != recBuffer[0] || recBuffer[4] != (BYTE)( checksum16 & 0xff ) || recBuffer[5] != (BYTE)( (checksum16 / 256) & 0xff ) ) {
  393.         // Check the checksum
  394.         printf("Response had invalid checksum.\n%d != %d, %d != %d, %d != %d\n", checksum8, recBuffer[0], (BYTE)( checksum16 & 0xff ), recBuffer[4], (BYTE)( (checksum16 / 256) & 0xff ), recBuffer[5] );
  395.         return -1;
  396.     }
  397.     else if ( recBuffer[6] != 0 ) {
  398.         // Check the error code in the packet. See section 5.3 of the U3
  399.         // User's Guide for errorcode descriptions.
  400.         printf("Command returned with an errorcode = %d\n", recBuffer[6]);
  401.         return -1;
  402.     }
  403.    
  404.     //all must be ok with the response (checksum passed)    
  405.     return 0;
  406.    
  407. }
  408.  
  409. /* ---------------- Buffer Helper Functions Definitions ---------------- */
  410. // Calculates the checksum8
  411. BYTE calculateChecksum8(BYTE* buffer){
  412.     int i; // For loops
  413.     int temp; // For holding a value while we working.
  414.     int checksum = 0;
  415.    
  416.     for( i = 1; i < 6; i++){
  417.         checksum += buffer[i];
  418.     }
  419.    
  420.     temp = checksum/256;
  421.     checksum = ( checksum - 256 * temp ) + temp;
  422.     temp = checksum/256;
  423.    
  424.     return (BYTE)( ( checksum - 256 * temp ) + temp );
  425. }
  426.  
  427. // Calculates the checksum16
  428. int calculateChecksum16(BYTE* buffer, int len){
  429.     int i;
  430.     int checksum = 0;
  431.    
  432.     for( i = 6; i < len; i++){
  433.         checksum += buffer[i];
  434.     }
  435.    
  436.     return checksum;
  437. }
  438. //integrating LJ code:///////////////////block #5 - END/////////////////////
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement