Skip to content

Conversation

@henrypinkard
Copy link
Contributor

@henrypinkard henrypinkard commented Mar 12, 2025

New Camera API

This PR implements a new camera API based on the GenICam standard features naming convention v2.7. It also includes a reference implementation of the API on a Basler camera. Associated tests for new functionality and backwards compatibility are available here

Dependencies

This PR should be merged after:

Overview

The new API converts GenICam features to their respective implementations:

  • ICommands become methods (e.g., TriggerSoftware)
  • IEnumeration, IFloat, IBoolean (as strings "0"/"1"), and IInteger become standard properties

Required Methods in device API

virtual bool IsNewAPIImplemented() = 0;
virtual int TriggerSoftware() = 0;
virtual int AcquisitionArm(int frameCount) = 0;
virtual int AcquisitionStart() = 0;
virtual int AcquisitionStop() = 0;
virtual int AcquisitionAbort() = 0;

Additions to core API

void triggerCamera() throw (CMMError);
void triggerCamera(const char* cameraLabel) throw CMMError);
void acquisitionStart() throw (CMMError);
void acquisitionStart(const char* cameraLabel) throw (CMMError);
void acquisitionArm(int frameCount) throw (CMMError);
void acquisitionArm(const char* cameraLabel, int frameCount) throw (CMMError);
void acquisitionStop() throw (CMMError);
void acquisitionStop(const char* cameraLabel) throw (CMMError);
void acquisitionAbort() throw (CMMError);
void acquisitionAbort(const char* cameraLabel) throw (CMMError);
bool isAcquisitionRunning() throw (CMMError);
bool isAcquisitionRunning(const char* cameraLabel) throw (CMMError);

Standard properties

Additional functionality is implemented through standard properties following the GenICam naming convention:

TriggerSelector
TriggerMode
TriggerSource
TriggerActivation
TriggerDelay
ExposureMode
ExposureTime
AcquisitionBurstFrameCount
LineSelector
LineMode
LineInverter
LineSource
LineStatus
AcquisitionFrameRate
AcquisitionFrameRateEnable
AcquisitionStatusSelector
AcquisitionStatus
TriggerOverlap
EventSelector
EventNotification

These properties are opt-out for new-API camera device adapters; device adapters must explicitly declare skipped properties during initialization.

Two additional non-GenICam standard properties for rolling shutter exposure/light sheet readout: RollingShutterActiveLines and RollingShutterLineOffset

@jondaniels I haven't used this feature myself and don't have a camera. These properties may need refinement or should perhaps be pushed to a future PR.

Backwards compatibility

This API maintains full backwards compatibility:

  • Existing cameras inherit from CLegacyCameraBase or COldAPICameraBase
  • New cameras inherit from CNewAPICameraBase
  • CameraInstance handles conversion between old-style core calls (core.snapImage, core.startSequenceAcquisition, etc) and new-style calls (core.acquisitionArm, core.acquisitionStart) to old or new style cameras.

All standard properties are also opt-in for existing cameras without requiring full migration to the new API. This means old style cameras can, for example, standardize the names of their hardware triggering properties without having to do a full migration. In many cases, I think this can be done fully backwards compatibly by reusing a property handler (eg OnTriggerType) and have the functionality under both standard and legacy non-standard names.

Usage notes

The required methods of the API map fairly closely to the old one. A couple small differences to point out:

  • All data is acquired through the acquisitionStart function (ie no difference between snap and sequences)
  • acquisitionStart always returns immediately. Unfortunately, there doesn't seem to be any reliable GenICam way to receive a callback when exposure or a sequence is finished. This means the device adapter still must call GetCoreCallback()->acqFinished()
  • When using the new style API, all data should be read out via the buffer (eg core.popImage or getLastImage, not getImage).
  • ArmAcquisition(int numImages) takes the number of images that will be acquired (or 0 for continuous acquisition). This allows them to fully prepare before any hardware (ie shutter) changes state, including pre-allocating buffer slots (once this feature is enabled with the new buffer api). Since all preparation should take place here, there is not need to call GetCoreCallback()->PrepareForAcq(this) in acquisitionStart(), though this can be included for backwards compatibility

Events

GenIStyle camera events are not sufficiently reliable for critical operations. For example, ExposureEnd events cannot be used to close shutters as delivery is not guaranteed (and this indeed was unreliable on my testing with a Basler cameras).

A new core callback method has been added to support GenICam-style events from cameras to nonetheless provide non-critical GenICam-style updates.

When merged, the following PRs should also be merged

Notes

  • Potential conflicts with new image buffer PR New image buffer #570 may require resolution as both modify sequence acquisition functionality. I can help merge changes between branches once we determine which PR will merge to main first.

@jondaniels
Copy link
Contributor

Two additional non-GenICam standard properties for rolling shutter exposure/light sheet readout: RollingShutterActiveLines and RollingShutterLineOffset

Thinking about cameras I have used in MM that support light sheet mode you would set 2 parameters:

  1. The number of lines active at any one time -- maps cleanly to RollingShutterActiveLines
  2. The speed of the rolling shutter moving across the sensor or equivalently the per-row time. Different cameras have different limitations on the allowable rolling speeds (min, max, quantization, etc.) and the allowable settings may depend on a settable readout speed. I'm not sure what to call this and would be happy if others had ideas.

In my experience with rolling shutter cameras, temporal offsets are usually handled externally by the user by e.g. adjusting the speed of the element that is synchronized with the rolling shutter. But I think they could be separately specified with camera properties (e.g. a camera might support a user-settable delay between camera trigger and actual exposure start).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants