ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

I confirm that michikarg's fix does work.

I was also able to fix the issue 'in code' by gently ripping out the port initialization function from original player's rflex driver, and adding it to ROS rflex_driver.cc. I did not clean the code and now my driver has two redundant initializations.

To save you some time, here is the code I have added (rflex-player.hh):

/*
 * Functions ripped straight from player's rflex driver to fix the issue
 * with port initialization.
 */

#ifndef RFLEX_PLAYER_HH_
#define RFLEX_PLAYER_HH_

#include <rflex/rflex_info.h>
#include <fcntl.h>
#include <termios.h>

#define MAX_NAME_LENGTH                256

enum PARITY_TYPE   { N, E, O };

typedef struct {
  char                       ttyport[MAX_NAME_LENGTH];
  int                        baud;
  enum PARITY_TYPE           parity;
  int                        fd;
  int                        databits;
  int                        stopbits;
  int                        hwf;
  int                        swf;
} RFLEX_Device;

// From rflex-io.cc
int iParity(enum PARITY_TYPE par) {
    if (par == N)
        return (IGNPAR);
    else
        return (INPCK);
}

int iSoftControl(int flowcontrol) {
    if (flowcontrol)
        return (IXON);
    else
        return (IXOFF);
}

int cDataSize(int numbits) {
    switch (numbits) {
    case 5:
        return (CS5);
        break;
    case 6:
        return (CS6);
        break;
    case 7:
        return (CS7);
        break;
    case 8:
        return (CS8);
        break;
    default:
        return (CS8);
        break;
    }
}

int cStopSize(int numbits) {
    if (numbits == 2) {
        return (CSTOPB);
    } else {
        return (0);
    }
}

int cFlowControl(int flowcontrol) {
    if (flowcontrol) {
        return (CRTSCTS);
    } else {
        return (CLOCAL);
    }
}

int cParity(enum PARITY_TYPE par) {
    if (par != N) {
        if (par == O) {
            return (PARENB | PARODD);
        } else {
            return (PARENB);
        }
    } else {
        return (0);
    }
}

int cBaudrate(int baudrate) {
    switch (baudrate) {
    case 0:
        return (B0);
        break;
    case 300:
        return (B300);
        break;
    case 600:
        return (B600);
        break;
    case 1200:
        return (B1200);
        break;
    case 2400:
        return (B2400);
        break;
    case 4800:
        return (B4800);
        break;
    case 9600:
        return (B9600);
        break;
    case 19200:
        return (B19200);
        break;
    case 38400:
        return (B38400);
        break;
    case 57600:
        return (B57600);
        break;
    case 115200:
        return (B115200);
        break;
#ifdef B230400
    case 230400:
        return (B230400);
        break;
#endif

    default:
        return (B9600);
        break;
    }

}

void DEVICE_set_params(RFLEX_Device dev) {
    struct termios ctio;

    tcgetattr(dev.fd, &ctio); /* save current port settings */

    ctio.c_iflag = iSoftControl(dev.swf) | iParity(dev.parity);
    ctio.c_oflag = 0;
    ctio.c_cflag = CREAD | cFlowControl(dev.hwf || dev.swf)
            | cParity(dev.parity) | cDataSize(dev.databits)
            | cStopSize(dev.stopbits);

    ctio.c_lflag = 0;
    ctio.c_cc[VTIME] = 0; /* inter-character timer unused */
    ctio.c_cc[VMIN] = 0; /* blocking read until 0 chars received */

    cfsetispeed(&ctio, (speed_t) cBaudrate(dev.baud));
    cfsetospeed(&ctio, (speed_t) cBaudrate(dev.baud));

    tcflush(dev.fd, TCIFLUSH);
    tcsetattr(dev.fd, TCSANOW, &ctio);

}

int DEVICE_connect_port(RFLEX_Device *dev) {
    if ((dev->fd = open((dev->ttyport), (O_RDWR | O_NOCTTY), 0)) < 0) {
        return (-1);
    }
    DEVICE_set_params(*dev);
    return (dev->fd);
}
// /rflex-io.h

int rflex_open_connection(const char *device_name, int *fd) {
    RFLEX_Device rdev;

    strncpy(rdev.ttyport, device_name, MAX_NAME_LENGTH);
    rdev.baud = 115200;
    rdev.databits = 8;
    rdev.parity = N;
    rdev.stopbits = 1;
    rdev.hwf = 0;
    rdev.swf = 0;

    printf("trying port %s\n", rdev.ttyport);
    if (DEVICE_connect_port(&rdev) < 0) {
        fprintf(stderr, "Can't open device %s\n", rdev.ttyport);
        return -1;
    }

    *fd = rdev.fd;
    return 0;
}

#endif /* RFLEX_PLAYER_HH_ */

Then include the above into rflex_driver.cc and replace (in rflex_driver.cc):

fd = open(device_name, O_RDWR | O_NONBLOCK);
if (fd == -1) {

for

if (rflex_open_connection(device_name, &fd) < 0) {

If someone wants to go through the code and find what it does differently, then you should pay attention to DEVICE_set_params(). The part fixes the problem (removing the call makes the lag reappear). This is on my todo list, but not as urgent as other things.