I am capturing images using the hardware trigger.(TriggerMode:FallingEdge)
I’m creating a C++ program that repeatedly executes the following doCapture() function.
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.
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.
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;
}
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.
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.
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();`.
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.
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?