Multiple connections to the same camera

Hi guys,

I am using the class camera below to communicate with a Dalsa gige camera.
I am using this class in this way inside a ROS node and it works fine when I just want to try and get one image periodically. I am using aravis 0.8

    cv::Mat AcquireImageAravis(int exposure, std::string camSerialNo)
    {
        Camera cam2(camSerialNo,false);
        //Camera cam2("S1171401",false);
        cam2.setProperties("EXP_TIME", exposure);
        cv::Mat img = cam2.snapFrame();
        cam2.releaseCamera();
        return img;
    }

Now, I would like to get a live image every second in a seperate ROS node, by snapping an image, converting it to an opencv cv::Mat format as I am currently doing.

My questions are

  • Is there is a better way that what I have described to stream the images by building on the code i have? I still need to send each one as opencv mat.

  • From the initial tests I have done it seems very hit a miss as to whether I can get a connection to the camera when I ‘release’ one connection from one node in ROS to go to a connection in another node in ROS. Is there a best practice for this? Do I need a delay?

  • What happens when you try to connect to a camera and it is already in use? Can you forcefully take control?

#include "Camera.hpp"

        Camera::Camera(bool automode){

       
        camera = arv_camera_new(NULL, NULL);
        if(camera != NULL){
            std::cout << "Initialized ArvCamera@"<<camera << std::endl;
            std::cout << "AUTO Prop Mode : " << automode << std::endl;
            if(!automode){
                disable_auto();
            }
            return;
        }
        camera = NULL;
        return;
    }

    Camera::~Camera(){}

    Camera::Camera(std::string camera_id, bool automode){
        /*
            params : camera_id : type string
            camera_id : e.g. Aravis-GV01, TIS-11714131 (for The Imaging Source <Serial No> Cameras)

            params : automode : type bool
            automode: bool flag to enable or disable auto mode. (automode = true) for enabling auto mode. 
        */
          
        camera = arv_camera_new(camera_id.c_str(), NULL);
        if(camera != NULL){
            std::cout << "Initialized ArvCamera@"<<camera << std::endl;
            std::cout << "AUTO Prop Mode : " << automode << std::endl;
            if(!automode){
                disable_auto();
            }
            return;
        }
        camera = NULL;
        return;
    }

    void Camera::disable_auto(){
        printf("Disable Auto Property\n");
        arv_camera_set_exposure_time_auto(camera, ARV_AUTO_OFF, NULL);
        arv_camera_set_gain_auto(camera, ARV_AUTO_OFF, NULL);

        // write support for other properties
    }

    void Camera::setProperties(std::string property_name, double property_value){
        if(property_name == "GAIN"){
            arv_camera_set_gain(camera, property_value, NULL);
        }else if(property_name == "EXP_TIME"){
            arv_camera_set_exposure_time(camera, property_value, NULL);
        }else if(property_name == "FPS"){
            arv_camera_set_frame_rate(camera, property_value, NULL);
        }
        return ;
    }
    double Camera::getProperties(std::string property_name){
        if(property_name == "EXP_TIME"){
            return arv_camera_get_exposure_time (camera, NULL);
        }
    }



    void Camera::setTrigger(bool val){
        issetTrigger = val;
        if(val){
            arv_camera_set_trigger(camera, "Line1", NULL);
        }
    }
    cv::Mat Camera::snapFrame()
    {
        void *framebuffer;
        framebuffer = NULL;
        IplImage *frame;
        frame = NULL;
        cv::Mat matImage;


        buffer = arv_camera_acquisition (camera, 0, NULL);

        if (ARV_IS_BUFFER (buffer)){
            printf ("Image successfully acquired\n");
            printf (" Converting Image to MAT\n");

            IplImage src;

            size_t buffer_size;
            framebuffer = (void*)arv_buffer_get_data (buffer, &buffer_size);

            cvInitImageHeader( &src, cvSize( 2464, 2056 ), IPL_DEPTH_8U, 1, IPL_ORIGIN_TL, 4 );
            cvSetData(&src, framebuffer, src.widthStep);
            if ( !frame || frame->width != src.width || \
                frame->height != src.height || \
                frame->depth != src.depth || \
                frame->nChannels != src.nChannels) {
                    cvReleaseImage( &frame );
                    frame = cvCreateImage( cvGetSize(&src), src.depth, 1 );
            }
            cvCopy(&src, frame);
            matImage = cv::cvarrToMat(frame);
        }
        else{
            printf ("Failed to acquire a single image\n");
        }


        return matImage;

    }
    void Camera::releaseCamera(){
        g_clear_object (&camera);
        g_clear_object (&buffer);
    }

Hi,

I would suggest to also ask your question on a ROS forum. There is plenty of ROS specific terms in your message and your code examples that I for one do not understand.

For example, what are ROS nodes ? Just class instances in an executable, or separate application instances ?

What do snapFrame() and releaseCamera() ?

Emmanuel.

Hi Emmanuel,

Hope you are keeping well and thanks for the reply.

A ROS node is normally an executable that contains a certain set of functionality and can talks to other nodes over messages.

In my case I have a ‘calibration’ node and ‘findPart’ node

At a high level for the findPart node I need to get an image that is synced with a lighting setup as quickly as I can, convert it to an Opencv format and process the image

For the calibration node it just continuously grabs images and is used to calibrate the camera to the robot. The user just selects the mode on the GUI and that determines which node needs to use the camera

My questions is more about what’s the best practice to share the one camera with the two different nodes from an aravis point of view - don’t worry about ROS - it’s more for context. So I my questions are

  • What is the best way to take control of the camera while potentially another application is using it?

  • Can I force taking control or do I have to get the application that is using the camera to release it first before I can start acquiring?

  • Is there a delay required between releasing the camera from one application and initializing the camera in another application. What’s the most eloquent way of doing this?

  • For real aravis video streaming what are the changes to modify my code in snapFrame()

If you take a look at my original questions you will see the code for the Camera class. In it you will see the functions snapFrame() which takes a single image using aravis, converts the buffer contents to openCV format and returns it.

releaseCamera just clears the aravis camera and the buffer

Hope this makes sense

Hi,

As always in parallel computing, if you want to access the same resource from different contexts, you have to put in place some lock mechanism. Part of it is already there, as a GigeVision can only have one client with controller access. So I guess it should be possible to create 2 instances of ArvCamera, and drop the controller privilege when you don’t need to control it. Please have a look at arv_gv_device_take/leave_control.

No documented delay, it depends on the device.

I don’t get what you mean.

Thanks for the reply Emmanuel. I’ll look into arg_gv_device_take/leave_control