Differences between revisions 2 and 3
Revision 2 as of 2026-02-18 21:08:47
Size: 6356
Comment:
Revision 3 as of 2026-02-18 21:15:03
Size: 6570
Comment:
Deletions are marked like this. Additions are marked like this.
Line 47: Line 47:
  || Maximum resolution || {{{659×494}}} || {{{5328×4608}}} ||
  || Maximum frame rate || {{{120}}} || {{{~4.8}}} ||

Consideration to use Basler a2A series

  • KAGRA uses acA640-120gm cameras as the GigE system. Cameras are controlled by pylon-camera-server developed in LIGO. When considering the use of a Basler cameras with pylon-camera-server also for TCam, a2A5328-4gmPRO was listed up as a candidate that satisfies the specification requirements. We then verified the compatibility between a2A5328-4gmPRO and pylon-camera-server.

Conclusion

  • There was no compatibility between a2A5328-4gmPRO as SDK/GenlCam 2.x and pylon-camera-server as SDK/GenlCam 1.x.

  • The best solution from the view point of human resources is to find another camera as SDK/GenlCam 1.x which satisfies the specification requirements.
  • It's possible to modify pylon-camera-server, but many changes and great efforts are required.

    • Modifying pylon-camera-server to make compatibility with both 1.x and 2.x is not so fruitful because 3.x and 4.x already exist.

    • So, the 2nd best solution may be to fork pylon-camera-server as pylon-camera-server2 which is compatible only with 2.x if a2A5328-4gmPRO is really used at the very limited places.

First trial

  • Config file was prepared as /kagra/camera/pylon-camera-config/K1-CAM-TEST0.ini. Different settings are only resolution (5328x4608 instead of 640x480) and frame rate (4fps instead of 25fps) as follows.

    width=5328
    height=4608
    framerate_numerator=4
  • Camera server can be launched by following command.
    > /kagra/camera/pylon-camera-service start TEST0
  • EPICS IOC was running but camera images cannot be received by camera_client because pylon-camera-server showed a following error.
    Feb 18 15:42:55 k1cam2 systemd[750]: Started pylon-camera-server@K1-CAM-TEST0.service - Basler 2D GigE camera RTP H264 UDP server.
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: Obtained request pad src_0 for appsink branch.
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: Obtained request pad src_1 for udpsink branch.
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: Starting main loop.
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: cas warning: Configured TCP port was unavailable.
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: cas warning: Using dynamically assigned TCP port 38533,
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: cas warning: but now two or more servers share the same UDP port.
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: cas warning: Depending on your IP kernel this server may not be
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: cas warning: reachable with UDP unicast (a host's IP in EPICS_CA_ADDR_LIST)
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: The camera is connected.
    Feb 18 15:42:55 k1cam2 pylon-camera-server[2132807]: Attaching camera.
    Feb 18 15:42:56 k1cam2 pylon-camera-server[2132807]: Opening camera.
    Feb 18 15:42:56 k1cam2 pylon-camera-server[2132807]: Device Model Name: a2A5328-4gmPRO
    Feb 18 15:42:57 k1cam2 pylon-camera-server[2132807]: Parameter not found in CStringParameter::GetValue. (No node attached.)
  • Accessing camera device was succeeded, but camera property cannot be obtained at the beginning of the server launching.

Details

  • Differences that affect the use of pylon-camera-server

    acA640-120gm

    a2A5328-4gmPRO

    Maximum resolution

    659×494

    5328×4608

    Maximum frame rate

    120

    ~4.8

    SDK/GenlCam version

    1.x

    2.x

    Class members

    camera.GevCurrentIPAddress

    device (*1)

    camera.DeviceID 

    camera.DeviceSerialNumber

    camera.AcquisitionFrameRateAbs

    camera.AcquisitionFrameRate

    camera.ResultingFrameRateAbs

    camera.ResultingFrameRate

    camera.ExposureTimeRaw

    camera.ExposureTime

    camera.GainRaw

    camera.Gain

  • Some of different class members are used in the main infinite-loop as follows, so it's difficult to insert version check for each call of member class.
    while (1) {
        ~
        ~
        if (epics_exposure_time_raw_set > 0) {
            g_print("Setting exposure time: %i\n", epics_exposure_time_raw_req);
            camera.ExposureTimeRaw.TrySetValue((int64_t) epics_exposure_time_raw_req, Pylon::IntegerValueCorrection_Nearest);
            exposure_time_raw_set = 0;
        }
        exposure_time_raw = camera.ExposureTimeRaw.GetValue();
        ~
        ~
    }
  • A wrapper class defined at the out of main loop as follows is required for all methods in all different classes because the class type is also different.

    std::function<void(double)> setExposure;
    std::function<double(void)> getExposure;
    
    GenApi::INodeMap& nodemap = camera.GetNodeMap();
    if (GenApi::CIntegerPtr(nodemap.GetNode("ExposureTimeRaw")).IsValid()) {
        GenApi::CIntegerPtr node = nodemap.GetNode("ExposureTimeRaw");
        setExposure = [node](double v) {
            node->SetValue((int64_t)v);
        };
        getExposure = [node]() -> double {
            return (double)node->GetValue();
        };
    }
    else if (GenApi::CFloatPtr(nodemap.GetNode("ExposureTime")).IsValid()) {
        GenApi::CFloatPtr node = nodemap.GetNode("ExposureTime");
        setExposure = [node](double v) {
            node->SetValue(v);
        };
        getExposure = [node]() -> double {
            return node->GetValue();
        };
    }
  • Then, we can keep a cycle speed of the main loop as follows.
    while (1) {
        ~
        ~
        if (epics_exposure_time_raw_set > 0) {
            g_print("Setting exposure time: %f\n", epics_exposure_time_raw_req);
            setExposure(epics_exposure_time_raw_req);
            exposure_time_raw_set = 0;
        }
        exposure_time_raw = getExposure();
        ~
        ~
    }
  • For (*1), replacing method directly seems to work fine like as follows.

       if (version=1) x = camera.GevCurrentIPAddress.GetValue());
       elif (version=2) x = device.GevIpAddress()

KAGRA/Subgroups/DGS/Projects/Cam/BaslerV2Camera (last edited 2026-02-18 21:15:03 by TakahiroYamamoto)