ATC6 after camera boot: enable chunks

Hello,
I am using an ATC6 camera with CVVBB 14.00.002 on windows 10.
Camera is initialised with CVB++ GENTL.

ISSUE: when I reboot the camera, I cannot get the Chunks (timestamp, encoer value) enven though chunk is initialized. To make it work I must open the device, Initialize :

  • Set multipart mode to true,
  • Set ChunkScanLineSelector to “0”
  • Set ChunkModeActive to true
  • Close the device
  • Reopen the device

This is only after camera boot time that I must do it twice. If I don’t do it twice, I have this:


The access mode is non available.

When it is OK, I have this:
Capture-1

Do you have an idea about how I can solve the problem?

Regards,
Mikael.

Excuse me, I’m not really understanding the concrete procedure, you’re describing here. Do you have a minimal working example in CVB++?
Especially that:

(that is clearly not a way to go)

Did you try using the discovery interface and enableing “AttachChunk” node? As already stated here: https://forum.commonvisionblox.com/t/3rd-stack-gentl-no-vin-how-to-get-timestamp/1896/10 or https://forum.commonvisionblox.com/t/using-chunk-data-in-cvb/1895/3

I’m not sure whether you’re helped with that, but there exists a way of reloading user sets for the nodemap configuration. Also not sure whether ATC6 supports that. With that feature, you can save current config, and set it for device boot time.

Hi @Mikael,
@s-woe already described UserSetDefault that will probably help you here.

This is basically not an issue, but expected behaviour as far as I understand the “problem”.
When powering up the C6 he default UserSet is loaded (can be set to the desired UserSet). for the default setting, ChunkMode is set to False, so all ChunkNodes are expected to be “Not Available”. When activating ChunkMode there are no values directly available as it requires an image acquisition for the values to be filled.

Did you try using the discovery interface and enableing “AttachChunk” node?

No, I didn’t. I now added it before open device (like in the example) and it is still the same.

When activating ChunkMode there are no values directly available as it requires an image acquisition for the values to be filled.

Images are grabbing but it is still “Not Available”. It is only available if I close the device and reopen it and do the same configuration.
The issue only occurs after a camera reboot.

When powering up the C6 he default UserSet is loaded (can be set to the desired UserSet)

In that case, after a camera reboot, It works, I open the camera, configure it and grab and I have my chunks.

I’m not sure, whether you are fine with the user set or not.
In case you aren’t:
Please send a minimal working example of your app, I’m struggling finding a way figuring out what goes wrong without seeing what you do exactly.

Hi,
sorry for the delay of my answer.
I will work on a minimal example by the end of the week.
Thanks,
Mikael.

Hi,
I did a small code example.
After a camera reset. I launch the example: impossible to read chunks.

If I restart the same application, it works, I can read chunks.

I think here the camera must start with its factory values.
You will find below the example based on composite image CVB sample.

// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/// \brief  This MultiPart tutorial demonstrates an image acquisition where
///         the received composite contains a Bayer image and a converted
///         RGB8 image.
// ----------------------------------------------------------------------------

#include <iostream>
#include <string>
#include <vector>

#include <cvb/device_factory.hpp>
#include <cvb/global.hpp>
#include <cvb/driver/composite_stream.hpp>
#include <cvb/genapi/node_map_enumerator.hpp>

static const constexpr auto TIMEOUT = std::chrono::milliseconds(3000);
static const constexpr int NUM_ELEMENTS_TO_ACQUIRE = 10;

void PrintOutCompositePurpose(Cvb::CompositePtr composite);
void AnalyseCompositeAt(Cvb::CompositePtr composite, int index);

static std::map<Cvb::WaitStatus, const char*>
WAIT_ERROR_STATES
{
  {Cvb::WaitStatus::Timeout, "timeout"},
  {Cvb::WaitStatus::Abort, "abort"}
};


void SetValue_Int(Cvb::NodeMapPtr& nodemapcam, const char* featurename, int value)
{
    auto node = nodemapcam->Node<Cvb::IntegerNode>(featurename);
    if (node.get())
    {
        node->SetValue(value);
    }
}

void SetValue_Bool(Cvb::NodeMapPtr& nodemapcam, const char* featurename, bool value)
{
    auto node = nodemapcam->Node<Cvb::BooleanNode>(featurename);
    if (node.get())
    {
        node->SetValue(value);
    }
}

void SetValue_Enum(Cvb::NodeMapPtr& nodemapcam, const char* featurename, const char* value)
{
    auto node = nodemapcam->Node<Cvb::EnumerationNode>(featurename);
    if (node.get())
    {
        node->SetValue(value);
    }
}





int main()
{
    try
    {
        // discover transport layers
        auto infoList = Cvb::DeviceFactory::Discover(Cvb::DiscoverFlags::IgnoreVins | Cvb::DiscoverFlags::IgnoreGevSD);

        // can't continue the demo if there's no available device
        if (infoList.empty())
            throw std::runtime_error("There is no available device for this demonstration.");
        bool camfound = false;
        auto token = infoList[0].AccessToken();
        for (auto& dicovereditem : infoList)
        {
            std::string s = dicovereditem.AccessToken().c_str();
            if (strstr(s.c_str(), "192.168.13.1") != nullptr) // IP OF ATC6 ON MY MACHINE
            {
                camfound = true;
                token = dicovereditem.AccessToken();
                // ATTACH CHUNK (ATC6)
                dicovereditem.SetParameter("AttachChunk", "1");

            }
        }



        // instantiate the first device in the discovered list
        auto device = Cvb::DeviceFactory::Open<Cvb::GenICamDevice>(token, Cvb::AcquisitionStack::GenTL);


        //
        //
        auto nodes = device->NodeMap(CVB_LIT("Device"));
        auto vendor = nodes->VendorName();
        auto model = nodes->ModelName();

        // MPN enable multipart
        SetValue_Bool(nodes, "GevSCCFGMultiPart", true);

        // Std::DeviceScanType ->  Linescan3D
        SetValue_Enum(nodes, "Std::DeviceScanType", "Linescan3D");

        // MPN Std::ChunkModeActive
        SetValue_Bool(nodes, "Std::ChunkModeActive", true);

        // MPN Std::ChunkScanLineSelector: force to the first
        SetValue_Int(nodes, "Std::ChunkScanLineSelector", 1);

        // Select RegionSelector : prepare some values and disable regions
        SetValue_Enum(nodes, "Std::RegionSelector", "Region0");
        SetValue_Bool(nodes, "Std::RegionMode", false);
        SetValue_Enum(nodes, "Std::RegionSelector", "Region1");
        SetValue_Bool(nodes, "Std::RegionMode", false);
        SetValue_Enum(nodes, "Std::RegionSelector", "Region2");
        SetValue_Bool(nodes, "Std::RegionMode", false);
        SetValue_Enum(nodes, "Std::RegionSelector", "Region3");
        SetValue_Bool(nodes, "Std::RegionMode", false);

        SetValue_Enum(nodes, "Std::RegionSelector", "Region0");
        SetValue_Int(nodes, "Std::Height", 24);
        SetValue_Int(nodes, "Std::OffsetY", 0);

        SetValue_Enum(nodes, "Std::RegionSelector", "Region1");
        SetValue_Int(nodes, "Std::Height", 24);
        SetValue_Int(nodes, "Std::OffsetY", 32);

        SetValue_Enum(nodes, "Std::RegionSelector", "Region2");
        SetValue_Int(nodes, "Std::Height", 24);
        SetValue_Int(nodes, "Std::OffsetY", 104);

        SetValue_Enum(nodes, "Std::RegionSelector", "Region3");
        SetValue_Int(nodes, "Std::Height", 24);
        SetValue_Int(nodes, "Std::OffsetY", 204);

        SetValue_Enum(nodes, "Std::RegionSelector", "Scan3dExtraction0");
        SetValue_Int(nodes, "Std::Height", 850);
        SetValue_Bool(nodes, "Std::RegionMode", true);

        // only enable Region0
        SetValue_Enum(nodes, "Std::RegionSelector", "Region0");
        SetValue_Bool(nodes, "Std::RegionMode", true);

        // REGION Scan3dExtraction0 and enable Reflectance+Scatter
        SetValue_Enum(nodes, "Std::RegionSelector", "Scan3dExtraction0");
        SetValue_Enum(nodes, "Std::ComponentSelector", "Range");
        SetValue_Bool(nodes, "Std::ComponentEnable", false);
        SetValue_Enum(nodes, "Std::ComponentSelector", "Reflectance");
        SetValue_Bool(nodes, "Std::ComponentEnable", true);
        SetValue_Enum(nodes, "Std::ComponentSelector", "Scatter");
        SetValue_Bool(nodes, "Std::ComponentEnable", true);
        SetValue_Bool(nodes, "Std::RegionMode", true);

        // select extraction method
        SetValue_Enum(nodes, "Std::Scan3dExtractionSelector", "Scan3dExtraction0");
        SetValue_Enum(nodes, "Std::Scan3dExtractionMethod", "Threshold");
        SetValue_Int(nodes, "Cust::Scan3dExtractionThresholdIntensity", 50);
        

        // access the first data stream that belongs to the device and start
        auto dataStream = device->Stream<Cvb::CompositeStream>();


        // pour faire un reset de la comm car si on arrête l'appli en cours d'acquisition, 
        // on a des erreurs timeout d'acquisition à chaque fois que l'on relancait l'appli. 
        // Il fallait charger le VIN dans CVB puis relancer l'appli pour avoir les images.
        // TryDeviceAbort() éviter le problème.
        dataStream->TryDeviceAbort();


        //  Set a ring buffer
        dataStream->RegisterManagedFlowSetPool(8);

        dataStream->Start();

        // acquire data
        for (auto i = 0; i < NUM_ELEMENTS_TO_ACQUIRE; i++)
        {
            Cvb::CompositePtr composite;
            Cvb::WaitStatus waitStatus;
            Cvb::NodeMapEnumerator enumerator;

            std::tie(composite, waitStatus, enumerator) = dataStream->WaitFor(TIMEOUT);



            switch (waitStatus)
            {
            default:
            {
                std::cout << "wait status unknown.\n";
                continue;
            }
            case Cvb::WaitStatus::Abort:
            case Cvb::WaitStatus::Timeout:
            {
                std::cout << "wait status not ok: " << WAIT_ERROR_STATES[waitStatus] << "\n";
                continue;
            }
            case Cvb::WaitStatus::Ok:
                break;
            }

            PrintOutCompositePurpose(composite);
            AnalyseCompositeAt(composite, i);
            try
            {
                auto timestamp = nodes->Node<Cvb::IntegerNode>("Std::ChunkTimestamp");
                std::cout << "ChunkTimestamp:" << timestamp->Value() << " WORKS ONLY THE SECOND LAUNCH APP AFTER REBOOT" << "\n";
            }
            catch (const std::exception& e)
            {
                std::cout << "ChunkTimestamp: ERROR !!!!  (OCCURS AFTER CAMERA REBOOT)" << "\n";
            }

            //Cust::BufferTimestamp
            auto vinnm = enumerator["VinBuffer"];
            auto timestampVin = vinnm->Node<Cvb::IntegerNode>("Timestamp");
            std::cout << "VinTimestamp:" << timestampVin->Value() << " NEVER WORKS WITH ATC6" << "\n";
            timestampVin.reset();
            vinnm.reset();

            std::cout << "\n";
        }

        dataStream->Stop();
        dataStream->TryDeviceAbort();
    }
    catch (const std::exception& e)
    {
        std::cout << e.what() << std::endl;
    }
    return 0;
}

/**
 * @brief evaluates the given composite and passes the string version of the purpose to stdout
 *
 * @param composite Cvb::CompositePtr the composite pointer whose purpose is to be extracted.
 */
void PrintOutCompositePurpose(Cvb::CompositePtr composite)
{
    auto purpose = composite->Purpose();
    std::cout << "Composite purpose: ";
    switch (purpose)
    {
    case Cvb::CompositePurpose::Custom: std::cout << "Custom\n"; break;
    case Cvb::CompositePurpose::Image: std::cout << "Image\n"; break;
    case Cvb::CompositePurpose::ImageList: std::cout << "Image List\n"; break;
    case Cvb::CompositePurpose::MultiAoi: std::cout << "MultiAoi\n"; break;
    case Cvb::CompositePurpose::RangeMap: std::cout << "RangeMap\n"; break;
    case Cvb::CompositePurpose::PointCloud: std::cout << "PointCloud\n"; break;
    case Cvb::CompositePurpose::ImageCube: std::cout << "ImageCube\n"; break;
    default: std::cout << "Unknown\n"; break;
    }
}

/**
 * @brief from a given composite at a certain index prints out information about its content
 *
 * @param composite Cvb::CompositePtr, the composite to analyse
 * @param index int index of the composite for printouts.
 */
void AnalyseCompositeAt(Cvb::CompositePtr composite, int index)
{
    auto numberOfElements = composite->ItemCount();
    if (numberOfElements < 2)
    {
        std::cout << "Number of elements in composite #" << index << " is less than expected (no multipart)\n";
        return;
    }

    std::cout << "Multipart data with " << numberOfElements << " elements\n";

    for (auto j = 0; j < numberOfElements; j++)
    {
        auto element = composite->ItemAt(j);
        if (Cvb::holds_alternative<Cvb::ImagePtr>(element))
        {
            auto image = Cvb::get<Cvb::ImagePtr>(element);
            auto plane0 = image->Plane(0);
            auto dt = plane0.DataType();
            auto h = image->Height();
            auto linearAccess = image->Plane(0).LinearAccess();

            std::cout << "acquired image: " << index << " at memory location: " << (uint64_t)linearAccess.BasePtr() << " datatype: " << dt.BytesPerPixel() <<
                "  xincr:" << linearAccess.XInc() << "  yincr:" << linearAccess.YInc() << "  height:" << h << "  width:" << image->Width() << "\n";
        }
        else
            std::cout << "Element " << j << " in composite " << index << " is not an image" << "\n";
    }
}

I hope you will be able to find the issue.

Regards,
Mikael.

Okay thanks for the sample. I will look at this. In what way do you trigger the device reset?

Hello s-woe,

Okay thanks for the sample. I will look at this. In what way do you trigger the device reset?

To force the cam reset, I go to GenIcamBrowser, open the camera and click on the feature reset. After I fastly close GenIcamBrowser.
Thanks,
Mikael.

While I’m not really sure whether I understand why you’re doing this, I try to get to the essence:

  • you execute the snippet above,
  • when the snippet is finished, you go to the Genicam browser, execute “DeviceReset” node, and finally
  • execute the snippet above again

Do I understand that correctly?

(Just as a side ntoe: You can execute the “DeviceReset” also in software, just as you access any other node in the nodemap already)

Do I understand that correctly?

Yes. I reset the camera, I start the sippet and I don’t get chunks. I must start a second time the snippet to get chunks.

I see. Do you get errors when applying the chunk preferences at the second startup (after device reset) (i.e. “AttachChunk” in the access token at device open or “Std::ChunkModeActive”) when looking at the log, simultaneously? Would you also be so kind to share the exception message you catch while chunk timestamp reading.

1rst startup:
error detail when reading chunks: Node[Std::ChunkTimestamp]: Node is not readable.

I never get any error applying (at 1st or 2nd or … startup):

  • discovereditem.setParameter(“AttachChunk”), “1”);
  • std::ChunkModeActive to true.

Hi,
this seems similar to our problem with C5: https://forum.commonvisionblox.com/t/reading-chunkencodervalue-from-at-c5-2/1471

TL;DR: We also had a problem reading chunks due to camera configuration process, ended up using usersets as well.

Hi,
Yes, I already used this solution and it works. But it is not great for maintenance, if the camera is changed, the guy who changes it must not forget to do the operation.
If we don’t do that, impossible to get chunks after first startup. So impossible to get timestamps (with chunks and the generic timestamp never works with that camera).
This is not great for a camera that price. I hope AT will do something about it.
Mikael.

I will check with my colleague whether there is a thread running with AT fixing that.

In any case, for safety, I would recommend to set the user set in code as well. Workflow:

  1. Check whether userset is loaded (by checking Std::UserSetSelector Node)
    if Factory is loaded (only once):
  2. set settings you want
  3. save settings in user set
  4. Set User set as startup
    else:
    normal task.
1 Like