alliedvision / VimbaPython

Old Allied Vision Vimba Python API. The successor to this API is VmbPy
BSD 2-Clause "Simplified" License
93 stars 40 forks source link

Can't find TriggerSource? #7

Closed ttamttam closed 4 years ago

ttamttam commented 4 years ago

see Vimba Python Manual 1.0.0, page 17.

Trying to switch to cam.TriggerSource.set('Software') without success, because I can't find cam.TriggerSoftware.run()?

I just grepped for 'trigger' in the source code:

/src/vimbapython$ ag -i trigger
Tests/real_cam_tests/feature_test.py
443:            # Trigger change handler and wait for callback execution.
574:            # Trigger change handler and wait for callback execution.
697:            # Trigger change handler and wait for callback execution.

Tests/basic_tests/interface_test.py
163:        # are triggered then called Outside of the with block.

Tests/basic_tests/vimba_test.py
111:        # are triggered then called Outside of the with block.

Examples/event_handling.py
147:            # Acquire a single Frame to trigger events.

Examples/action_commands.py
131:            # Prepare Camera for ActionCommand - Trigger
140:            cam.TriggerSelector.set('FrameStart')
141:            cam.TriggerSource.set('Action0')
142:            cam.TriggerMode.set('On')

Best regards

NiklasKroeger-AlliedVision commented 4 years ago

The access to camera features by using attributes of the Camera object is implemented in such a way, that the available camera features are loaded when the camera connection is opened. This is done because different cameras can expose different features. Creating the feature objects during opening allows the user to have more "pythonic" code by accessing featues with cam.TriggerSource.set("Software") instead of cam.get_feature_by_name("TriggerSource").set("Software"). That is why you won't find implementations for every feature in the VimbaPython source code. The features you want to access (TriggerSource and TriggerSoftware) should however be available. And your attempts at accessing them look fine.

I am not sure what it is exactly that you want to achieve. But in order to demonstrate a way of using software triggers to grab single images I made some changes to the asynchronous_grap.py example. You can find that version here.

The main change is that in setup_camera I set the AcquisitionMode to SingleFrame so I would only trigger a single image. TriggerSource is set to SoftwareTrigger and the TriggerMode is turned On so the camera actually listens for them.

cam.AcquisitionMode.set("SingleFrame")
cam.TriggerSource.set("Software")
cam.TriggerMode.set("On")

Next I defined a class to run the software triggering in a separate thread. This makes it easy to stop the thread from the outside by using the stop method that sets a threading.Event.

class SoftwareTriggerThread(threading.Thread):
    def __init__(self, cam: Camera):
        threading.Thread.__init__(self)

        self.cam = cam
        self.killswitch = threading.Event()

    def stop(self):
        self.killswitch.set()

    def run(self):
        # with Vimba.get_instance(): # still opened in main thread. So it can be left out in THIS example. Generally this is required
        # with self.cam: # still opened in main thread. So it can be left out in THIS example. Generally this is required
        while not self.killswitch.isSet():
            print("RUN TRIGGER HERE", flush=True)
            self.cam.TriggerSoftware.run()
            time.sleep(1) # Just to make it easier to follow terminal output
            print("REARMING FOR NEXT TRIGGER", flush=True)
            self.cam.AcquisitionStart.run()
            time.sleep(1) # Just to make it easier to follow terminal output

Lastly I simply have to create the thread and start it in order to generate software triggers every two seconds. This is done in the main function after the frame_handler is registered and the camera was told to start streaming.

cam.start_streaming(handler=frame_handler, buffer_count=10)

software_trigger_thread = SoftwareTriggerThread(cam)
software_trigger_thread.start()
input()
software_trigger_thread.stop()
software_trigger_thread.join()

With this you should see the following output in your terminal: /////////////////////////////////////////// /// Vimba API Asynchronous Grab Example /// ///////////////////////////////////////////

Press to stop Frame acquisition.

RUN TRIGGER HERE
Camera(id=DEV_1AB22D01BBB8) acquired Frame(id=0, status=FrameStatus.Complete, buffer=0x23153fd5040)
REARMING FOR NEXT TRIGGER
RUN TRIGGER HERE
Camera(id=DEV_1AB22D01BBB8) acquired Frame(id=1, status=FrameStatus.Complete, buffer=0x231544bb040)
REARMING FOR NEXT TRIGGER
...

As before the acquisition can be stopped by pressing enter. The software trigger should run every two seconds and the frames should be acquired accordingly.

I hope this helps. If you have further questions feel free to reopen the issue. But as the features are available once the camera is opened, I would not consider this an issue with VimbaPython and will therefore close this for now.