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

Getting external callbacks (SDK) called in a ROS node

asked 2015-02-05 04:33:56 -0500

altella gravatar image

updated 2015-02-09 05:21:27 -0500

gvdhoorn gravatar image

Hello all;

I am trying to integrate a new sensor in a robot. This sensor provides an SDK and the way of acquiring its data is by using a callback, everytime that there are data available, the callback is called. Inside the callback it is possible to access the data. The program with the SDK has been tested and works fine, accesing the sensor callback. The problem comes when trying to integrate all thi code in ROS. ROS is attending to its framework and callbacks, and the sensor callback is not being executed. Due to the characteristics of the SDK of the sensor, I can not call the callback explicitly when I want to collect data. The library is a Windows SDK, there is not a Linux Version, so, we are using WinROS with this node...

Is there any way to make ROS attend callbacks that are not from its own environment??

UPDATE. CODE ATTACHED

#include<smart_ray/smart_ray.h>

void smartRayControlCb(const std_msgs::BoolConstPtr &msg)
{

    if(msg->data)
    {
        initSmartRaySensor();
        //captura
        startSmartRayCapture();
    }
    else
    {
        stopSmartRaySensor();
    }

}


int CBunknownCommand(CAMDESC* cd) 
{

    char msg[260];
    sprintf (msg, "unknown data received. command no: 0x%02x", cd->command); 

    return 0;

}

int CBstatusMsg (CAMDESC* cd, int msgType, int msgdata1, int msgdata2, char *msg)
{
    int Laserlight;
    int Laserstatus;
    int digIn[4];
    int digOut[2];
    int FPS;

    if(msg==NULL) //No message data available
        return -1;

    if (msgType == MSGTYPE_CONNECTION) //Ethernet connection messages
    {
        if(msgdata1 == CAMERA_CONNECTED) // TCP/IP connection established
        {
            printf("%s.\n",msg);
            sensor.connectionstate = STATE_CAMERA_CONNECTED;
            return(0);
        }
        else // disconnected
        {
            printf("%s.\n",msg);
            sensor.connectionstate = STATE_CAMERA_CLOSED;
            return(0);
        }
    }
    else if (msgType == MSGTYPE_INFO)   // Info messages
    {
        printf("%s.\n",msg);
        return(0);
    }
    else if (msgType == MSGTYPE_ERROR)  // Error messages
    {
        printf("%s",msg);
        return(1);
    }
    // Sensor IO and general data (sensor sends this every 200ms) 
    else if (msgType == MSGTYPE_DATA && msgdata1 == DATATYPE_IO)
    {
        digIn[0] = cd->digio_in[0];
        digIn[1] = cd->digio_in[1];
        digIn[2] = cd->digio_in[2];
        digIn[3] = cd->digio_in[3];
        // Digital output status (via CAMDESC* cd e.g. cd->digio_out[0] = DigOut0)
        digOut[0] = cd->digio_out[0];
        digOut[1] = cd->digio_out[1];
        // Laser Status (enabled - disabled) 
        Laserstatus = cd->laser_status;
        // Laser light on/off
        Laserlight = cd->laserlight;
        // Frames per second (current/last INTERNAL! framerate of the sensor)
        FPS = cd->fps;
    }

    return 0;
}

int CBprofileImageCallback (CAMDESC* cd, int dattyp, int startX, int height, int width, void* pdata)
{
    int i=0;
    int k=0;
    unsigned short* data = NULL;
    //~ unsigned short* pDataProf = NULL;
    //~ unsigned short* pDataInten = NULL;

    std::vector<int16_t> pDataProf;
    std::vector<int16_t> pDataInten;
    //memory reservation
    //~ pDataProf = (unsigned short *)malloc(width*height*sizeof(unsigned short));
    //~ pDataInten = (unsigned short *)malloc(width*height*sizeof(unsigned short));

    // data contents depends on settings of parameter in PROFILE_SETUP and ACQUIRE module
    data = (unsigned short*) pdata;
    // data includes just contour info
    if (dattyp == DATATYPE_PROFILE)
    {
        for (i=0;i<width*height;i++)
        {
            pDataProf.push_back(data[i]);
        }
    }

    else if (dattyp == DATATYPE_INTENSITY)
    {
        for (i=0;i<width*height;i++)
        {
            pDataInten.push_back(data[i]);
        }
    }
    // data includes contour AND intensity info
    // and must be separated
    else if (dattyp == DATATYPE_PROFILE_PLUS_INTENSITY)
    {
        for (i=0;i<width*height;i ...
(more)
edit retag flag offensive close merge delete

Comments

1

Could you post some example code of your node with the callback that does not get called?

BennyRe gravatar image BennyRe  ( 2015-02-05 05:26:51 -0500 )edit

Code posted...there you can have a look at the "Non-ROS" callbacks, which are not working...

altella gravatar image altella  ( 2015-02-06 06:34:56 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
3

answered 2015-02-05 05:39:35 -0500

gvdhoorn gravatar image

updated 2015-02-06 08:15:03 -0500

The first answer to Significance of ros::spinOnce() will probably help you. Also: roscpp/Overview/Callbacks and Spinning from roscpp.


Edit:

int main(int argc, char** argv)
{   
    ...

    ros::spin();

    return 0;
}

The ros::spin() will never return, and is probably why your other callbacks aren't being serviced. As you can read in the Significance of ros::spinOnce() answer, replacing it with something like:

int main(int argc, char** argv)
{
    ...

    ros::Rate loop_rate(10);

    while (ros::ok() && smart_ray_ok())
    {
        // let the smart ray event loop do its thing
        process_smart_ray_events()

        // let ros do its things
        ros::spinOnce();

        // sleep some (only if needed)
        loop_rate.sleep();
    }

Will give the smart ray SDK a chance to process its incoming data (and call the registered UserCB).

As I have no experience with that particular SDK, I cannot say what smart_ray_ok() and process_smart_ray_events() should really be (or if they even exist), that is something you'll have to figure out yourself.

As an alternative to the above, you could use an AsyncSpinner, which would remove the need for the while loop and the ros::spinOnce(). See the linked roscpp/Overview/Callbacks and Spinning page for more information on that.

edit flag offensive delete link more

Comments

Hello all; Thanks for the tips. The thing is that I cannot explicitily call the data acquistion function in the SmartRay Library. It is a free running callback, and the problem is that it is not being called....

altella gravatar image altella  ( 2015-02-09 02:50:08 -0500 )edit

Well without access to the smartray sdk I can only speculate. Are you sure you have actually started the smart ray processing loop? Are your events / samples getting through/generated? There might also be some incompatibility between ROS and the sdk, but again, that is speculation.

gvdhoorn gravatar image gvdhoorn  ( 2015-02-09 03:08:48 -0500 )edit

Also: you could see whether just converting to the while loop with ros::spinOnce() and the loop_rate.sleep() avoids any thread starvation issues. I doubt it though, as afaik, the select() call is a cancellation point (from this).

gvdhoorn gravatar image gvdhoorn  ( 2015-02-09 03:11:07 -0500 )edit

ok... things to check. In fact, the SDK is only for windows, and we are using winROS...so, I do not feel confident at all. Tanks for your quick responses.

altella gravatar image altella  ( 2015-02-09 03:29:52 -0500 )edit

@altella: I've taken the liberty to rephrase the question's title. I think it better reflects what is going on. Also: could you add which version of WinROS you are using (based on Groovy, Hydro or Indigo)?

gvdhoorn gravatar image gvdhoorn  ( 2015-02-09 05:22:26 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2015-02-05 04:33:56 -0500

Seen: 354 times

Last updated: Feb 09 '15