Acquisition stuck when terminating process early

Hi all!

I found that the camera sometimes get’s stuck in acquistion mode, if not aborted correctly.
I added two scripts below that can be used to reproduce the problem (one for the basic acquisition, one for parallel). The steps I execute (for either script):

  1. Start the script, wait until you receive at least an image
  2. Before the scripts finishes, terminate it
  3. Start the script again, and wait for the first image

Step 3 will run indefintly and never receive an image (it also doesnt throw an error), however we can find the device, and connect to it. I have tried to abort/terminate the stream after opening the device in the second run, but this didn’t work. The only way I found to solve this, was by going to genicam-> open the device-> stop the acquisition.

I would like to check, and if needed, terminate the acquistion from within python upon opening the devices, so that I’m sure the acquisition will run properly and the code won’t get stuck.

We are using multiple GO-5000M-PGE (usb3)

What would be the proper approach? Thx in advance!

Basic Script

    import cvb
    import time
            
    # ----------------- Acquire Device ----------------
    def get_device_list():
        discovered_device_list = cvb.DeviceFactory.discover_from_root(flags=cvb.DiscoverFlags.IgnoreVins)
        if discovered_device_list is None or len(discovered_device_list) == 0:
            raise RuntimeError("unable to find any devices. Is any other program using the cameras?")

        return discovered_device_list

    device_list = get_device_list()
    device = device_list[0] # gets the first device

    # ---------------- Do Acquisition ------------------------
    with cvb.DeviceFactory.open(device.access_token) as device:
        
        stream = device.stream
        stream.start()

        #range is high, so you have time to press the stop button
        for i in range(100):
            image, status = stream.wait()
            if status == cvb.WaitStatus.Ok: 
                print("Acquired image: " + str(i))
                #time.sleep(3)
                #raise Exception('random exception to stop the process')


        stream.abort()

Parallel Script

	import time
	import os
	import cvb


	class MyStreamHandler(cvb.SingleStreamHandler):

	    def __init__(self, stream):
	        super().__init__(stream)
	        self.rate_counter = cvb.RateCounter()

	    # called in the interpreter thread to setup additionla stuff.
	    def setup(self, stream):
	        super().setup(stream)
	        print("setup")

	    # called in the interpreter thread to tear down stuff from setup.
	    def tear_down(self, stream):
	        super().tear_down(stream)
	        print("tear_down")

	    # called from the aqusition thread
	    def handle_async_stream(self, stream):
	        super().handle_async_stream(stream)
	        print("handle_async_stream")

	    # called from the aqusition thread
	    def handle_async_wait_result(self, image, status):
	        super().handle_async_wait_result(image, status)
	        self.rate_counter.step()
	        print("New image: " + image.__class__.__name__ + " " + str(image) + " | Status: " + str(status) + " | Buffer Index: " + str(image.buffer_index))

	    # print messurement results
	    def eval(self):
	        print("Acquired with: " + str(self.rate_counter.rate) + " fps")

	       
	        
	def get_device_list():
	    discovered_device_list = cvb.DeviceFactory.discover_from_root(flags=cvb.DiscoverFlags.IgnoreVins)
	    if discovered_device_list is None or len(discovered_device_list) == 0:
	        raise RuntimeError("unable to find any devices. Is any other program using the cameras?")

	    return discovered_device_list


	device_list = get_device_list()
	device = device_list[0] # gets the first device

	with cvb.DeviceFactory.open(device.access_token) as device:
	    with MyStreamHandler(device.stream) as handler:
	        handler.run()
	        time.sleep(4)
	        handler.finish()

Hi @Swaab !

Sorry it took a while to respond - I honestly did not notice the open question sooner as I usuall only skim the top 5 or so.

Can you provide a little more detail on the issue? The precise version of :cvb: that you have installed might be helpful as well as the Python version that you are using.

Thanks and best regards!

Hi @Swaab
also the environment you run your code in might be interesting here.
I found myself with cameras locked in acquisition when using LinqPad and the latest C# wrappers of :cvb:.
In my case it was LinqPad that for some reasons kept the connection open which was fixed with an update if I remember correctly.

Hee, no problem!
Also good point chris.

Extra info:

  • platform: Windows 10
  • python version: 3.8.8
  • CVB version: 13.03.002
  • I’ve started the script both from the terminal, and visual studio

Hi!

Thank you for sharing your software versions.
When I have a look at the CVBpy requirements then I see:

  • Python (CPython 3.5 3.6 3.7) (Windows)

@Chris @illusive Can the Python version 3.8 be the cause?

Thanks!

I had assumed 3.8 would work because of the cp38 inside the package file name.
image

Hi @PBras

with :cvb: 13.03.xxx Python 3.8 should not be the problem (we’ve switched to using this internally last year). Can you point out the location where 3.8 was not listed, please? That should definitely be updated…

Thanks

Hi @illusive

Thank you for your fast reply. I found this in the CvbPy manual:
%CVB%\Doc\CvbPy.chm

Kind regards,
Patrick

@illusive any updates on this?

Hi @Swaab,

I was just pointed to this question. You are right the camera can remain in “Acqusition Active” state if not stopped correctly. This is by intention as we do not reset the the camera on every device open. This would cause other settings to be lost.

I see, this can be problematic if you want to start streaming again. In that case, please ensure that the camera is stopped before starting it again.

stream.start()
stream.try_abort()

This should do as a workaround. Nevertheless I will look into it as the next call to:

stream.start() 

should really start the acquisition or fail (throw) if this is not possibel.

Hi Andreas!

Thx for your reply. Any updates yet?

Currently, we indeed force a abort in between different acquisitions like so:

        self.stream.abort()
        self.device.close()

and then reopen the device and start the stream.
If everything goes well it does run smoothly, but indeed once an error occurs before the abort we get stuck. Curious to hear if you have found a solution for that :slight_smile:

Btw, from you first comment, does that mean you can keep the acquisition active while disconnecting the device, and then grab it again by opening the device? Would that be recommended / a more quicker/cleaner approach?

Hi Swaab,

Andreas is currently not in the office, so I will try to answer your questions.
If I understand correctly the problem with the “stuck” acquisition is that you run into an error while debugging or stop the debugger before the acquisition is stopped on a USB camera. Since the debugger drops the memory the device is not closed properly and keeps an more or less unknown state. This is very unfortunate but not a bug per se. That being said, we will try to find a solution as Andreas mentioned which should improve stability in such a case. Seeing that the fix will be more complicated we are currently favouring the next release (CVB 13.4; 7.1.21) though.

I hope that in the meantime the workaround is sufficient for you. Keeping the device active and disconnecting/connectiong is not favourable under normal circumstances.

Oke, thx for the heads up! Where can I track the state of the next release? Then I will test it once it’s released.

I think you can get an alert on the CVB download topic https://forum.commonvisionblox.com/c/downloads/5. It is planned for release early next month.

1 Like