Nxlib function isn't responding?

General Information

  • Product: C57-6-M
  • Serial Number: 244888
  • Ensenso SDK Version: 4.0.1502
  • Operating System: Windows 10 64bit
  • C++ Interface
  • Data Attachments
    • Profiler log

Problem / Question

I am capturing images using the hardware trigger.(TriggerMode:FallingEdge)
I’m creating a C++ program that repeatedly executes the following doCapture() function.

void doCapture()
{
	NxLibCommand trigger(cmdTrigger);
	trigger.parameters()[itmSubset] = valAll;
	trigger.execute();
	NxLibCommand retrieve(cmdRetrieve);
	retrieve.parameters()[itmTimeout] = -1;
	retrieve.parameters()[itmCameras] = m_serial;
	retrieve.execute(static_cast<bool>(false));

	while(1){
		if (retrieve.finished()) {
			bool rc2 = retrieve.result()[m_serial][itmRetrieved].asBool();
			if (rc2) {
				break;
			}
		}
	}
	retrieve.parameters()[itmTimeout] = 1000;
	retrieve.parameters()[itmCameras] = m_serial_C;
	retrieve.execute();
}

void hoge(){
	while(1){
		doCapture();
	    nxLibSetString(&error, "/Execute/Command", "ComputeDisparityMap");
	    nxLibWaitForType(&error, "/Execute/Command", NxLibItemTypeNull, 1);
	    nxLibGetBinaryInfo(&error, path, &bin_widthDspa, &bin_heightDspa,         &bin_channelCountDspa, &bin_bytesPerElementDspa, &bin_isFloatDspa, 0);
	    nxLibSetString(&error, "/Execute/Command", "ComputePointMap");
	    nxLibWaitForType(&error, "/Execute/Command", NxLibItemTypeNull, 1);
	    ・・・・
	}
}

It usually works fine, but occasionally the program freezes.
It seems like the nxlib function within the doCapture() isn’t responding.
Could you please look at the ensensolog at the following URL and tell me what situations cause the program to freeze?
I’ve uploaded the ensensolog when the system froze after working normally for a while.

tmp_NxTreeEdit-20260311.enslog (1.45 GiB)

settings-20260311.json (231 Bytes)

Best regards,
K.N,

Hi,

the while loop waiting for the Retrieved flag will never stop when the transmission fails for some reason. Ideally this shouldn’t happen. But it can in practice, so your program should be prepared for it.

Unfortunately, the log contains some gaps where data was discarded before it was fetched. There was a lot of logging data produced due to the way your are polling the Retrieved flag with very high frequency. So I cannot tell for sure whether there actually was some problem during transmission in your case, but the transmission looks very reliable. There are no lost packets or anything in the transmissions that are present in the log.

We can improve the logic of the code to minimize polling and prepare it for errors. Also see the guide on hardwarer triggers for some code examples.

There are the following options:

  • If you know the expected time between hardware triggers you can use that to specify a timeout for the Retrieve command. This is the easiest way to ensure no infinite loops and that you get notified of any errors that might be happening.
  • Otherwise you can specify a Timeout of 0 to the Retrieve command to use it for polling. In this case, ideally the doCapture function would have another way of noticing that a hardware trigger should have occurred to cancel the polling loop.
1 Like

Hi Daniel

First, thanks a lot for your quick response!

The interval for hardware triggers cannot be specified.
Therefore, I consulted this community previously

(Aborting a capture command waiting for a trigger),
and after some back-and-forth, I arrived at this code.

Is there a way to keep the while loop as is and collect logs that will help identify the cause?

Currently, the Retrieve command has a timeout value of -1. What is the difference between this and specifying 0?

The while loop within doCapture() in the code I initially posted is actually processed as follows in the actual code:

while(1){
	if (retrieve.finished()) {
		bool rc2 = retrieve.result()[m_serial][itmRetrieved].asBool();
		if (rc2) {
			break;
		}
	}
	if(cancel_Button_ON()){
		retrieve.cancel();
		while (true) {
			if (retrieve.finished()) {
				return(1);
			}
		}
	}
}

The goal is to react to hardware triggers as quickly as possible and to exit the while loop waiting for finish() at the desired timing.

Could you please give me some advice on the above?

Best regards,
K.N,

Is there a way to keep the while loop as is and collect logs that will help identify the cause?

To get complete logs it would be better to limit the frequency of the polling. Also to save some CPU time.

Currently, the Retrieve command has a timeout value of -1. What is the difference between this and specifying 0?

I would prefer the variant with timeout 0, since it simplifies canceling. You can simply exit the function without any further cleanup. But timeout -1 and canceling the command as in your snippet is also possible. You just have to be more careful about the error handling and cleanup.

if (retrieve.finished()) {
    bool rc2 = retrieve.result()[m_serial][itmRetrieved].asBool();
    if (rc2) {
        break;
    }
}

This does not check the command result. When the command exits with an error, it will be finished, but Retrieved is false, so you end up in an infinite loop.

A better variant would be something like this:

if (retrieve.finished()) {
    // Throws an exception when the command failed.
    retrieve.assertSuccessful();

    // You can check the Retrieved flag here, but it is redundant. When you get
    // here and the command exited successfully, an image should have been
    // retrieved since the command was executed for a single camera.
    assert(retrieve.result()[m_serial][itmRetrieved].asBool());

    break;
}
1 Like

Hi Daniel

Q1.

To get complete logs it would be better to limit the frequency of the polling.
Also to save some CPU time.

In a situation where we don’t know when the target will turn off the sensor, I don’t think we can limit the polling frequency to maintain the cycle time. Is there a better way?

Q2.

I would prefer the variant with timeout 0, since it simplifies canceling.

If I set the timeout to 0, how should I write the following cancellation code?

if(cancel_Button_ON()){
		retrieve.cancel();
		while (true) {
			if (retrieve.finished()) {
				return(1);
			}
		}
	}

Q3.

// Throws an exception when the command failed.
    retrieve.assertSuccessful();

If a command fails when using `assertSuccessful`, can I try acquiring images from the camera again?

Or should I give up and wait for the next trigger? What kinds of exceptions might occur, and how should I handle each of them?

Since the trigger could occur as frequently as every 8 seconds, if processing takes too long, I’d like to consider the image unacceptable for now and wait for the next trigger.

Best regards,
K.N,

In a situation where we don’t know when the target will turn off the sensor, I don’t think we can limit the polling frequency to maintain the cycle time. Is there a better way?

I would just introduce a small sleep. The way you did it, polling will happen hundreds of times per second, which is probably not necessary.

If I set the timeout to 0, how should I write the following cancellation code?

The code could look something like this (this is an extension of the example code I linked above):

NxLibCommand retrieve(cmdRetrieve);
while (true) {
	retrieve.parameters()[itmTimeout] = 0;
	retrieve.execute();
	if (retrieve.result()[serial][itmRetrieved].asBool()) {
		// A new image has been received and copied into the raw image node
		break;
	}

	if(cancel_Button_ON()) {
		return 1;
	}
}

If a command fails when using assertSuccessful, can I try acquiring images from the camera again?

Yes. To be safe you should execute the Trigger command again, although in most cases this will be a noop.

What kinds of exceptions might occur, and how should I handle each of them?

The command documentation lists some errors that could occur. Although this list isn’t complete and other errors could also happen which are described in their error text.

1 Like

I would just introduce a small sleep. The way you did it, polling will happen hundreds of times per
second, which is probably not necessary.

Q1. If I want to add a short sleep time, would it be something like this?

	while(1){
		//Sleep
		std::this_thread::sleep_for(std::chrono::microseconds(10));
		//Sleep-end
		if (retrieve.finished()) {
			bool rc2 = retrieve.result()[m_serial][itmRetrieved].asBool();
			if (rc2) {
				break;
			}
		}
		if(cancel_Button_ON()){
			retrieve.cancel();
			while (true) {
				if (retrieve.finished()) {
					return(1);
				}
			}
		}
	}

Q2.

NxLibCommand retrieve(cmdRetrieve);
while (true) {
	retrieve.parameters()[itmTimeout] = 0;
	retrieve.execute();
	if (retrieve.result()[serial][itmRetrieved].asBool()) {
		// A new image has been received and copied into the raw image node
		break;
	}

	if(cancel_Button_ON()) {
		return 1;
	}
}

Regarding the sample code you provided above, what would the code look like if I used “retrieve.assertSuccessful();” or"assert(retrieve.result()[m_serial][itmRetrieved].asBool());"?

Setting `retrieve.parameters()[itmTimeout]` to 0 will likely cause a TimeOut exception in `retrieve.assertSuccessful();`.

Best regards,
K.N,

Q1. If I want to add a short sleep time, would it be something like this?

Yes, although 10us is still very fast.

what would the code look like if I used “retrieve.assertSuccessful();”

In this variant, assertSuccessful() is not necessary, since it is already done as part of the execute().

Setting retrieve.parameters()[itmTimeout] to 0 will likely cause a TimeOut exception in retrieve.assertSuccessful();.

Yes, you might have to ignore that error when using the Timeout 0 variant.

As I said, if you want to keep the long-running command you can also take it and apply the improved error handling from comment #4.

1 Like

Hi Daniel

Thank you for your reply.

I will try experimenting with both the method you suggested: setting TimeOut to -1 and setting TimeOut to 0. I will report back once I have the results.

Regarding my experiment,I would like to ask if you have any sample code that uses assertSuccessful() to recover after an exception occurs when TimeOut is -1?

I would like to use it as a reference when creating the process to retrieve again after an exception occurs.

Best regards,
K.N,

Hi Daniel

Q1.As an experiment to set the TimeOut of the retrieve command to 0, I added the following code, which I was taught, to my software.

	NxLibCommand retrieve(cmdRetrieve);
	while (true) {
		retrieve.parameters()[itmTimeout] = 0;
		retrieve.execute();
		if (retrieve.result()[serial][itmRetrieved].asBool()) {
			// A new image has been received and copied into the raw image node
			break;
		}

		if(cancel_Button_ON()) {
			return 1;
		}
	}

However, every time I run retrieve.execute() the following exception occurs:

// The execution failed.
NXLIB_APIERROR(ExecutionFailed, 17);

Is there some setting or process missing?
Or is my situation different from what you expected?

Could you please give me some advice on the above?

Best regards,
K.N,

Hi K.N,

it seems there is currently a bug in the NxLib which can cause the Retrieve command to throw a CaptureTimeout exception even when the timeout is set to 0. We’re already looking into this issue.

As a workaround that should function reliably, you could implement the capture logic like this:

void doCapture()
{	
	try {
		NxLibCommand trigger(cmdTrigger);
		trigger.parameters()[itmSubset] = valAll;
		trigger.execute();
		
		NxLibCommand retrieve(cmdRetrieve);
		retrieve.rememberParameters(true);
		retrieve.parameters()[itmTimeout] = 100; // wait for 100 milliseconds per iteration
		retrieve.parameters()[itmCameras] = m_serial;
		
		int returnCode = 0;
		while (true) {
			if (cancel_Button_ON()) {
				return;
			}

			retrieve.execute(&returnCode, true);

			if (returnCode == NxLibExecutionFailed &&
				retrieve.result()[itmErrorSymbol].asString() == errCaptureTimeout) {
				// no image received yet, keep trying
				continue;
			} else if (returnCode != NxLibOperationSucceeded) {
				// something went wrong -> throw exception
				retrieve.assertSuccessful();
			} else if (retrieve.result()[m_serial][itmRetrieved].asBool()) {
				// image received successfully
			} else {
				// command successful but no image received (should not happen)
			}
			break;
		}
	} catch (NxLibException& e) {
		// exception handling
		if (e.isCommandExecutionFailure()) {
			std::string errorSymbol = e.getCommandErrorSymbol();
			std::string errorText = e.getCommandErrorText();
			std::cerr << "The execution of a command failed with error symbol \'" << errorSymbol << "\' " << std::endl;
			std::cerr << "and error text: " << errorText << std::endl;
		} else {
			std::cerr << "The NxLib API error " << e.getErrorCode() << " occurred when accessing the item at \'"
					  << e.getItemPath() << "\' with error text: " << e.getErrorText() << std::endl;
		}
	}
}

This approach uses the Retrieve commands own timeout to limit the polling rate to reduce the CPU usage.

Hope this helps!

Best regards,
Peter

1 Like

Hi Peter

Thank you for your reply.

I tried the code you provided.

The result is that when I press the hardware trigger switch, the blue LED lights up, but the retrieve process doesn’t complete successfully.

No matter how many times I press the hardware trigger switch, only the blue LED lights up.
I collected the log at that time.

tmp_NxTreeEdit20260320-RetrieveNonfinish.zip (9.8 MB)

could you please take a look and give me some advice?

Best regards,
K.N,

Hi K.N,

After digging a bit deeper into this issue, I discovered additional problems with our current implementation of the hardware trigger mode for cameras that support FlexView.

To give some insight into how it works internally: we run a dedicated thread for each camera that waits for a complete FlexView image set. However, this thread is currently being terminated as soon as any retrieve command fails, and it only restarts when a new trigger command is issued.

We’re planning to address and fix this issue in the next release.

In the meantime, I’ve slightly updated my original example so that it works with the current version of NxLib:

try {
	bool retrigger = true;
	while (retrigger) {
		retrigger = false;

		NxLibCommand trigger(cmdTrigger);
		trigger.parameters()[itmSubset] = valAll;
		trigger.execute();

		NxLibCommand retrieve(cmdRetrieve);
		retrieve.parameters()[itmTimeout] = 30000;
		retrieve.parameters()[itmCameras] = m_serial;
		retrieve.execute(false);
		while (true) {
			std::this_thread::sleep_for(std::chrono::milliseconds(100));
			if (cancel_Button_ON()) {
				retrieve.cancel();
			}

			if (!retrieve.finished()) {
				continue;
			}

			if (retrieve.successful()) {
				// image received successfully
			} else {
				std::string const errSymbol = retrieve.result()[itmErrorSymbol].asString();
				if (errSymbol == errCaptureTimeout) {
					// no image received yet, retrigger to restart flex view thread
					retrigger = true;
				} else if (errSymbol == errOperationCanceled) {
					// retrieve was canceled
				} else {
					// something went wrong -> throw exception
					retrieve.assertSuccessful();
				}
			}
			break;
		}
	}
} catch (NxLibException& e) {
	// exception handling
	if (e.isCommandExecutionFailure()) {
		std::string errorSymbol = e.getCommandErrorSymbol();
		std::string errorText = e.getCommandErrorText();
		std::cerr << "The execution of a command failed with error symbol \'" << errorSymbol << "\' " << std::endl;
		std::cerr << "and error text: " << errorText << std::endl;
	} else {
		std::cerr << "The NxLib API error " << e.getErrorCode() << " occurred when accessing the item at \'"
		          << e.getItemPath() << "\' with error text: " << e.getErrorText() << std::endl;
	}
}

In this version, the retrieve command is executed with a very large timeout, but it can be canceled at any time using the cancel button.

Sorry for the confusion caused by this behavior and the earlier explanation. We appreciate your patience while we sort this out and improve the implementation in the upcoming release.

Best regards,
Peter

1 Like

Hi Peter

Thank you for your reply.

I’m currently reinstalling the camera in a different location, so I can’t test it right away.

I’ll check it as soon as the environment is ready.

By the way, when is

scheduled to take place?

Best regards,
K.N,

Right now our release cycle has two feature freezes per year, one in May and one in November. Including the finalization and release testing phase this results in public releases around June/July and another one in December/January. So from now the next would be the May release cycle.

1 Like

Hi Rainer

Thank you for your reply.

Along with checking the code that Peter taught me,
I would also like to wait for the next version update.

Best regards,
K.N,