Ask Your Question
1

Sick LMS-100 topic stops publishing measurements

asked 2011-08-31 03:12:16 -0600

updated 2014-01-28 17:10:19 -0600

ngrennan gravatar image

Hi all,

I am using the RCPRG_laser_drivers pkg to obtain laser measurements from a sick LMS-100 laser and from a sick LMS-151 laser (each laser on a different robot, no connection between them at all).

The thing is that the laser topic stops generating messages after a while ('rostopic echo /LMS1xx/LAS_00' returns nothing when the node fails). In both cases.

Does anybody have experienced this problem?. Any suggestion how to trace this problem?

I am using Diamond Back with Ubuntu 10.04. Some weeks ago I was using CTurtle with the same laser package and I had no problem at all (tested along weeks).

Some tests I've made:

  • You can ping the laser once it starts to fail, even if it is not generating any message from the laser
  • If the node fails, you can kill the node and restart it again, and the flow of messages will start again without problem
  • I've observed that the node cannot recover from a disconnection of the laser. If you disconnect the ethernet cable to the laser, the node cannot reconnect to the laser and keep generating messages once you put the cable back. Only option is to restart the node
  • I've also checked that when the node stops generating messages, there is no disconnection at all (I used a ping -f to the laser while the node was active. Once the node failed, I checked the report of ping -f (Ctrl-C) and said 0% packet loss, so there was no disconnection at all)

Any idea, comment, suggestion, bad joke, will be welcomed (specially the last one... I need jokes now :-(

Best

Ricardo

edit retag flag offensive close merge delete

5 Answers

Sort by » oldest newest most voted
2

answered 2011-09-08 21:35:34 -0600

I think I found some bugs in the RCPRG laser driver. Debugging the code I saw that when laser topic stops being published, the driver gets stuck in a read of zero bytes because the buffer used to store data received from the sensor is already full (10000 bytes) without having received a valid sensor scan packet.

char buf[10000];
    fd_set rfds;
    struct timeval tv;
    int retval, len;
    len = 0;

    do {
        FD_ZERO(&rfds);
        FD_SET(sockDesc, &rfds);

        tv.tv_sec = 0;
        tv.tv_usec = 50000;
        retval = select(sockDesc + 1, &rfds, NULL, NULL, &tv);
        if (retval) {
            len += read(sockDesc, buf + len, 10000 - len);
        }
    } while ((buf[0] != 0x02) || (buf[len - 1] != 0x03));

The problems is more probable to happen when the scan message data includes remission values and angular resolution is set to 0.25º, because a complete message is 8192 bytes. I set the buffer dimension to 20000 and it seems to work but I think that a more elegant solution would be to use a circular buffer. Furthermore I would like to change the exit condition of the while cycle because it doesn't guarantee that the loop breaks in case of receiving a complete scan data msg + some bytes of the next one.

edit flag offensive delete link more
2

answered 2012-03-17 00:32:05 -0600

angel.rodriguez gravatar image

Hi,

I have the same problem, but nothing work for me. Do you have some other ideas?

I will try to reprogram the LMS1xx node for ROS. Did you make some experience with it?

Thank you in advance,

Angel A.

edit flag offensive delete link more

Comments

Please open a new question with your specific issue so that we don't clutter this question with multiple threads of Q&A. Thanks.

DimitriProsser gravatar imageDimitriProsser ( 2012-03-19 03:26:59 -0600 )edit
2

Has this problem been fixed yet?

Sentinal_Bias gravatar imageSentinal_Bias ( 2013-02-14 04:13:54 -0600 )edit
1

answered 2013-04-11 06:22:03 -0600

rohan gravatar image

I had the same problem and I tried the solution given above but nothing worked for me.

I changed the method getData in /RCPRG_laser_drivers/libLMS1xx/build/libLMS1xx/LMS1xx.cpp to the following code

     char raw[DATA_BUF_LEN];
    char buf[DATA_BUF_LEN];
    int len=0;
    if(leftovers.size() > 0) {

        for(int i = 0; i < leftovers.size(); i++) {
            buf[len] = leftovers[i];
            len++;
        }
        leftovers.clear();
    }
    unsigned long start;

    while(true) {
        if(debug)
            std::cout << "inside do while. ";

        fd_set rfds;
        FD_ZERO(&rfds);
        FD_SET(sockDesc, &rfds);

        struct timeval tv;
        tv.tv_sec = 0;
        tv.tv_usec = 50000;

        int retval = select(sockDesc + 1, &rfds, NULL, NULL, &tv); //always return the socket number
        if(debug)
            std::cout << "retval: " << retval << " ";
        int curLen = 0;
        if (retval) {
            curLen = read(sockDesc, raw, DATA_BUF_LEN); // read till this is zero

        }

        bool done = false;
        for(int i = 0; i < curLen; i++) {
            if(raw[i] == 0x03) { 

                leftovers.assign(raw + i + 1, raw + curLen); // copy remaining to leftovers
                done = true;  // this loop is important as it copies the remaining whereas in previous there were leftovers and its never the end so was stuck in the while loop
                break;
            } else { //  we copy till we dont find ETX
                buf[len] = raw[i];
                len++;
            }
        }
        if(debug)
            std::cout << std::endl;
        if(done) {
            break;
        }
    }
    // from here the code is same as before
    buf[len-1]=0;
    char* tok = strtok(buf, " "); 
    tok = strtok(NULL, " "); //Command
    tok = strtok(NULL, " "); //VersionNumber
    tok = strtok(NULL, " "); //DeviceNumber
    tok = strtok(NULL, " "); //Serial number
    tok = strtok(NULL, " "); //DeviceStatus
    tok = strtok(NULL, " "); //MessageCounter
    tok = strtok(NULL, " "); //ScanCounter
    tok = strtok(NULL, " "); //PowerUpDuration
    tok = strtok(NULL, " "); //TransmissionDuration
    tok = strtok(NULL, " "); //InputStatus
    tok = strtok(NULL, " "); //OutputStatus
    tok = strtok(NULL, " "); //ReservedByteA
    tok = strtok(NULL, " "); //ScanningFrequency
    tok = strtok(NULL, " "); //MeasurementFrequency
    tok = strtok(NULL, " ");
    tok = strtok(NULL, " ");
    tok = strtok(NULL, " ");
    tok = strtok(NULL, " "); //NumberEncoders
    int NumberEncoders;
    sscanf(tok, "%d", &NumberEncoders);
    //tok stop getting any data
    for (int i = 0; i < NumberEncoders; i++) {
        tok = strtok(NULL, " "); //EncoderPosition
        tok = strtok(NULL, " "); //EncoderSpeed
    }

    tok = strtok(NULL, " "); //NumberChannels16Bit
    int NumberChannels16Bit;
    sscanf(tok, "%d", &NumberChannels16Bit);
    if (debug)
        printf("NumberChannels16Bit : %d\n", NumberChannels16Bit);
    for (int i = 0; i < NumberChannels16Bit; i++) {
        int type = -1; // 0 DIST1 1 DIST2 2 RSSI1 3 RSSI2
        char content[6];
        tok = strtok(NULL, " "); //MeasuredDataContent
        sscanf(tok, "%s", content);
        if (!strcmp(content, "DIST1")) {
            type = 0;
        } else if (!strcmp(content, "DIST2")) {
            type = 1;
        } else if (!strcmp(content, "RSSI1")) {
            type = 2;
        } else if (!strcmp(content, "RSSI2")) {
            type = 3;
        }
        tok = strtok(NULL, " "); //ScalingFactor
        tok = strtok(NULL, " "); //ScalingOffset
        tok = strtok(NULL, " "); //Starting angle
        tok = strtok(NULL, " "); //Angular step width
        tok = strtok(NULL, " "); //NumberData
        int NumberData;
        sscanf(tok, "%X", &NumberData);
        //std::cout<<"the type is"<<type;
        if (debug)
            printf("NumberData : %d\n", NumberData);

        if (type == 0) {



            data.dist_len1 = NumberData;

        } else if (type == 1) {
            data.dist_len2 = NumberData;
        } else if (type == 2) {
            data.rssi_len1 = NumberData;
        } else if (type == 3) {
            data.rssi_len2 = NumberData;
        }

        for (int i = 0; i < NumberData; i++) {
            int dat;
            tok = strtok(NULL, " "); //data
            sscanf(tok, "%X", &dat);

            if (type == 0) {

                data.dist1[i] = dat;
            } else if (type == 1) {
                data.dist2[i] = dat;
            } else if (type == 2) {
                data.rssi1[i] = dat;
            } else if (type == 3) {
                data.rssi2 ...
(more)
edit flag offensive delete link more
1

answered 2011-08-31 04:09:20 -0600

DimitriProsser gravatar image

I had a similar problem with with LMS111. I discovered that the publish rate on the laser was simply too high. To solve the problem, I loaded the manufacturer's software (a Windows program) and turned down the frequency of the laser. I believe that I dropped it from its default 50Hz to 25Hz. It has worked without fail since then.

To address the disconnection problem, you could add a check to queryStatus() every so often, and if no messages are received, you could disconnect() and then login(). I haven't needed this functionality, but it's just my thought on the matter.

Also, it is not uncommon for the laser to take ~30 seconds to begin publishing to the ROS graph properly. While this only happens once in a while, don't panic if you see it.

~ Brian

edit flag offensive delete link more
0

answered 2011-09-01 19:39:10 -0600

Thank you Brian for your answer. I made the change on the laser configuration and tested the laser along yesterday. It looks like the problem is solved. Thank you for your help!

Ricardo

edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2011-08-31 03:12:16 -0600

Seen: 2,463 times

Last updated: Apr 11 '13