From 1191270e9e769f41435d590727cd2a8022c0f42f Mon Sep 17 00:00:00 2001 From: Johnathon Selstad Date: Tue, 6 Aug 2024 19:16:55 -0700 Subject: [PATCH] Update PyOpticam to the Latest Optitrack+Nanobind --- .gitignore | 4 +- CMakeLists.txt | 2 +- README.md | 2 +- cmake-modules/FindOTCSDK.cmake | 10 +- examples/optitrack_thread.py | 16 ++- examples/video_viewer.py | 77 +++++------ pyproject.toml | 2 +- setup.py | 2 +- src/pyopticam/__init__.py | 2 +- src/pyopticam_ext.cpp | 239 +++++++++++++++++---------------- 10 files changed, 183 insertions(+), 173 deletions(-) diff --git a/.gitignore b/.gitignore index 84b1a01..ad71c49 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,6 @@ calib_images* Rigel* Europa* local* -*.dll \ No newline at end of file +*.dll +.venv +.vs \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 38482e2..f4a574e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,6 @@ nanobind_add_module( NB_STATIC # Build static libnanobind (the extension module itself remains a shared library) src/pyopticam_ext.cpp ) -target_link_libraries(pyopticam_ext PRIVATE "C:/Program Files (x86)/OptiTrack/Camera SDK/lib/CameraLibrary2015x64S.lib") +target_link_libraries(pyopticam_ext PRIVATE "C:/Program Files (x86)/OptiTrack/CameraSDK/lib/CameraLibrary2019x64S.lib") install(TARGETS pyopticam_ext LIBRARY DESTINATION .) diff --git a/README.md b/README.md index a664a96..1e857bb 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Installation 2. Install the [Optitrack Camera SDK](https://optitrack.com/software/camera-sdk/) to: `C:/Program Files (x86)/OptiTrack/Camera SDK` 3. Clone this repository 4. Navigate to the top-level `pyopticam` directory and run `pip install -e . ` (Do not upgrade pip, use pip version `21.1.1`) -5. Find `C:/Program Files (x86)/OptiTrack/Camera SDK/lib/CameraLibrary2015x64S.dll` and copy it to `pyopticam/src/pyopticam` +5. Find `C:/Program Files (x86)/OptiTrack/CameraSDK/lib/CameraLibrary2019x64S.dll` and copy it to `pyopticam/src/pyopticam` Afterwards, make sure your Optitrack cameras are accessible on the network, and try the `video_viewer.py` or the `marker_viewer.py` example. diff --git a/cmake-modules/FindOTCSDK.cmake b/cmake-modules/FindOTCSDK.cmake index d73f97a..9caf30c 100644 --- a/cmake-modules/FindOTCSDK.cmake +++ b/cmake-modules/FindOTCSDK.cmake @@ -1,11 +1,11 @@ find_path(OTCSDK_ROOT_DIR NAMES include/camera.h - HINTS "C:/Program Files (x86)/OptiTrack/Camera SDK" + HINTS "C:/Program Files (x86)/OptiTrack/CameraSDK" NO_CMAKE_PATH) find_path(OTCSDK_INCLUDE_DIR NAMES cameralibrary.h - HINTS "C:/Program Files (x86)/OptiTrack/Camera SDK/include" + HINTS "C:/Program Files (x86)/OptiTrack/CameraSDK/include" NO_CMAKE_PATH) #message(STATUS "OTCSDK ROOT DIR PATH ${NP_CAMERASDK}") @@ -15,13 +15,13 @@ message(STATUS "OTCSDK ROOT DIR ${OTCSDK_ROOT_DIR}") message(STATUS "OTCSDK INCLUDE DIR ${OTCSDK_INCLUDE_DIR}") -find_library(OTCSDK_IMPORT_LIB CameraLibrary2015x64S HINTS "${OTCSDK_ROOT_DIR}/lib") -find_file(OTCSDK_SHARED_LIB NAMES "CameraLibrary2015x64S.dll" HINTS "${OTCSDK_ROOT_DIR}/lib") +find_library(OTCSDK_IMPORT_LIB CameraLibrary2019x64S HINTS "${OTCSDK_ROOT_DIR}/lib") +find_file(OTCSDK_SHARED_LIB NAMES "CameraLibrary2019x64S.dll" HINTS "${OTCSDK_ROOT_DIR}/lib") message(STATUS "OTCSDK IMPORT LIBRARY DIR ${OTCSDK_IMPORT_LIB}") message(STATUS "OTCSDK SHARED LIBRARY DIR ${OTCSDK_SHARED_LIB}") -include_directories("C:/Program Files (x86)/OptiTrack/Camera SDK/include") +include_directories("C:/Program Files (x86)/OptiTrack/CameraSDK/include") include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OTCSDK DEFAULT_MSG OTCSDK_ROOT_DIR OTCSDK_INCLUDE_DIR OTCSDK_IMPORT_LIB OTCSDK_SHARED_LIB) diff --git a/examples/optitrack_thread.py b/examples/optitrack_thread.py index f91da32..3e17318 100644 --- a/examples/optitrack_thread.py +++ b/examples/optitrack_thread.py @@ -60,7 +60,7 @@ def __init__(self, mode=m.eVideoMode.MJPEGMode, exposure=50, delay_strobe=False, print("Creating Sync Object...") self.sync = m.cModuleSync.Create() for i in range(len(self.camera_array)): - self.sync.AddCamera(self.camera_array[i], 0) + self.sync.AddCamera(self.camera_array[i]) else: self.sync = None @@ -105,17 +105,19 @@ def fetch_frame(self): new_frame = np.nan_to_num(new_frame, nan=0.0) else: current_framegroup = m.GetFrameGroup(self.sync) - new_frame = np.zeros((current_framegroup.Count(), 512, 640), dtype=np.uint8) - m.FillTensorFromFrameGroup(current_framegroup, new_frame) + new_frame = np.zeros((current_framegroup.Count(), self.camera_array[0].Height(), self.camera_array[0].Width()), dtype=np.uint8) + m.FillTensorFromFrameGroup(self.camera_array[0], current_framegroup, new_frame) self.current_frame = new_frame self.newFrame = True def run(self): print("Beginning Optitrack Receive Thread!") - while(self.should_run and time.time() - self.deadmansSwitch < 4.0): + while(self.should_run):# and time.time() - self.deadmansSwitch < 6.0): self.fetch_frame() + print("Should Run:", self.should_run, "Deadman Switch:", time.time() - self.deadmansSwitch) + if self.sync: self.sync.RemoveAllCameras() m.cModuleSync.Destroy(self.sync) @@ -124,9 +126,9 @@ def run(self): if self.camera_array[i].State() == m.eCameraState.Initialized: print("Stopping Camera", i, "...") #camera_array[i].Stop(True) - print("Stopped Camera", i," Releasing Camera...") - self.camera_array[i].Release() - print("Released Camera!") + print("Stopped Camera", i)#" Releasing Camera...") + #self.camera_array[i].Release() + #print("Released Camera!") m.CameraManager.X().Shutdown() diff --git a/examples/video_viewer.py b/examples/video_viewer.py index 1456328..ec4812e 100644 --- a/examples/video_viewer.py +++ b/examples/video_viewer.py @@ -11,45 +11,46 @@ ffmpeg_recording = False fake = np.zeros((16, 16), dtype=np.uint8) -num_cams = 8 +num_cams = 1 output_width = int(640 / 2) #output_height = int(512 * num_cams / 2) # Dependent on the number of cameras; see below -print("Starting to retrieve frame groups...") -keypress = cv2.waitKey(1) -while(not (keypress & 0xFF == ord('q'))): - if optitrack.newFrame: - image_frame = optitrack.read() - num_cams = image_frame.shape[0] - output_height = int(512 * num_cams / 2) - if image_frame.shape[1] > 1: - image_frame = np.reshape(image_frame, (-1, image_frame.shape[2])) - #image_frame = np.vstack((np.hstack((image_frame[0], image_frame[1], image_frame[2], image_frame[3])), - # np.hstack((image_frame[4], image_frame[5], image_frame[6], image_frame[7])))) - image_frame = cv2.resize(image_frame, (output_width, output_height)) - - if (keypress & 0xFF == ord('w')): - if not ffmpeg_recording: - ffmpeg_process = mp4_thread.ffmpegThread("OptitrackOutput.mp4", width=output_width, height=output_height)#image_frame.shape[1], height=image_frame.shape[0]) - ffmpeg_process.start() - ffmpeg_recording = True - else: - print("Killing FFMPEG process...") - ffmpeg_process.end_encoding() - ffmpeg_recording = False - - if ffmpeg_recording: - ffmpeg_process.add_image(image_frame) - cv2.imshow("CameraFrame", image_frame) - +try: + print("Starting to retrieve frame groups...") keypress = cv2.waitKey(1) - -if ffmpeg_recording: - print("Killing FFMPEG process...") - ffmpeg_process.end_encoding() - ffmpeg_recording = False - -optitrack.stop() - -cv2.destroyAllWindows() -print("Fin!") + while(not (keypress & 0xFF == ord('q'))): + if optitrack.newFrame: + image_frame = optitrack.read() + num_cams = image_frame.shape[0] + output_height = int(512 * num_cams / 2) + if image_frame.shape[1] > 1: + image_frame = np.reshape(image_frame, (-1, image_frame.shape[2])) + #image_frame = np.vstack((np.hstack((image_frame[0], image_frame[1], image_frame[2], image_frame[3])), + # np.hstack((image_frame[4], image_frame[5], image_frame[6], image_frame[7])))) + #image_frame = cv2.resize(image_frame, (output_width, output_height)) + + if (keypress & 0xFF == ord('w')): + if not ffmpeg_recording: + ffmpeg_process = mp4_thread.ffmpegThread("OptitrackOutput.mp4", width=output_width, height=output_height)#image_frame.shape[1], height=image_frame.shape[0]) + ffmpeg_process.start() + ffmpeg_recording = True + else: + print("Killing FFMPEG process...") + ffmpeg_process.end_encoding() + ffmpeg_recording = False + + if ffmpeg_recording: + ffmpeg_process.add_image(image_frame) + cv2.imshow("CameraFrame", image_frame) + + keypress = cv2.waitKey(1) +finally: + if ffmpeg_recording: + print("Killing FFMPEG process...") + ffmpeg_process.end_encoding() + ffmpeg_recording = False + + optitrack.stop() + + cv2.destroyAllWindows() + print("Fin!") diff --git a/pyproject.toml b/pyproject.toml index d1a5cbc..e24c242 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ requires = [ "wheel", "scikit-build", "cmake>=3.17", - "nanobind==0.0.9", + "nanobind", "ninja; platform_system!='Windows'" ] diff --git a/setup.py b/setup.py index f121390..a27b901 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ setup( name="pyopticam", - version="0.0.1", + version="0.0.2", author="Johnathon Selstad", author_email="john.selstad@ultraleap.com", description="A nanobind wrapper for NaturalPoint's Optitrack Camera SDK", diff --git a/src/pyopticam/__init__.py b/src/pyopticam/__init__.py index fe162ef..cfca455 100644 --- a/src/pyopticam/__init__.py +++ b/src/pyopticam/__init__.py @@ -1 +1 @@ -from .pyopticam_ext import GetCameraList, eVideoMode, eImagerGain, eCameraState, eOptimization, sStatusLightColor, cCameraLibraryStartupSettings, cModuleSync, FrameGroup, Modes, DroppedFrameInfo, GetFrameGroup, FillTensorFromFrameGroup, GetFrameGroupObjectArray, GetSlowFrameArray, Frame, Camera, CameraManager, CameraEntry, CameraList, HardwareKeyList, HubList, HardwareDeviceList, CameraManagerListener, cUID +from .pyopticam_ext import GetCameraList, eVideoMode, eImagerGain, eCameraState, eOptimization, sStatusLightColor, cCameraLibraryStartupSettings, FrameGroup, Modes, GetFrameGroup, FillTensorFromFrameGroup, GetFrameGroupObjectArray, GetSlowFrameArray, Frame, Camera, CameraManager, CameraEntry, CameraList, HardwareKeyList, HubList, HardwareDeviceList, CameraManagerListener, cUID, cModuleSync diff --git a/src/pyopticam_ext.cpp b/src/pyopticam_ext.cpp index 4b88385..6e446cf 100644 --- a/src/pyopticam_ext.cpp +++ b/src/pyopticam_ext.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -33,13 +33,13 @@ NB_MODULE(pyopticam_ext, m) { float *tracked_object_data = new float[8 * 255 * 3];// { 1, 2, 3, 4, 5, 6, 7, 8 }; size_t tracked_object_shape[3] = { 8, 255, 3 }; nb::capsule tracked_object_deleter(tracked_object_data, [](void *p) noexcept { delete[] (float *) p; }); - nb::tensor tensor = nb::tensor(tracked_object_data, 3, tracked_object_shape, /* owner = */ tracked_object_deleter); + nb::ndarray ndarray = nb::ndarray(tracked_object_data, 3, tracked_object_shape, /* owner = */ tracked_object_deleter); // Zero out the marker memory for(int i = 0; i < 8 * 255 * 3; i++){ tracked_object_data[i] = 0.0f; } //printf("[INFO] About to get FrameGroup!\n"); - FrameGroup* frameGroup = sync -> GetFrameGroup(); + std::shared_ptr frameGroup = sync->GetFrameGroup(); //printf("[INFO] Retrieved FrameGroup!\n"); bool invalid_frame_group = frameGroup == nullptr || frameGroup->Count() == 0; while(invalid_frame_group){ @@ -62,7 +62,7 @@ NB_MODULE(pyopticam_ext, m) { for(int i = 0; i < count; i++){ //printf("[INFO] About to read SubFrame %i\n", i); - Frame* frame = frameGroup->GetFrame(i); + std::shared_ptr frame = frameGroup->GetFrame(i); if(!(frame->IsInvalid())){ //printf("[INFO] Getting Subframe Size\n"); int objCount = frame->ObjectCount(); @@ -76,47 +76,44 @@ NB_MODULE(pyopticam_ext, m) { } else { //printf("[WARNING] Subframe was Empty or Invalid! From camera: %i\n", frame->GetCamera()->Serial()); } - frame->Release(); } }else{ printf("[WARNING] Framegroup is a nullptr or has an invalid number of cameras!\n"); } - frameGroup->Release(); nanobind::gil_scoped_acquire acquire; - return tensor; + return ndarray; }); - m.def("GetSlowFrameArray", [](nb::tensor< - int32_t, nb::shape, - nb::c_contig, nb::device::cpu> serials){//nb::list serials){ + m.def("GetSlowFrameArray", [](nb::ndarray, nb::c_contig, nb::device::cpu> serials){//nb::list serials){ nanobind::gil_scoped_release release; //printf("[INFO] Creating Dummy Data!\n"); uint8_t *stand_in_data = new uint8_t[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; size_t stand_in_shape[3] = { 8, 1, 1 }; nb::capsule stand_in_deleter(stand_in_data, [](void *p) noexcept { delete[] (uint8_t *) p; }); - nb::tensor tensor = nb::tensor(stand_in_data, 3, stand_in_shape, /* owner = */ stand_in_deleter); + nb::ndarray ndarray = nb::ndarray(stand_in_data, 3, stand_in_shape, /* owner = */ stand_in_deleter); // FrameGroups are null in GrayscaleMode!, Read Frames Individually the Stupid Way! size_t offset = 0; - int count = serials.shape(0); + auto view = serials.view(); + int count = view.shape(0); //printf("[INFO] Count is %i\n", count); uint8_t* full_buffer = nullptr; int height = 0, width = 0; - unsigned int last_address = 0; + size_t last_address = 0; //printf("[INFO] About to get Camera Manager\n"); CameraLibrary::CameraManager* cameraManager = &CameraManager::X(); for(int i = 0; i < count; i++){ //printf("[INFO] About to get Camera %i with serial %i\n", i, serials(i)); - Camera* camera = cameraManager->GetCameraBySerial(serials(i)); + std::shared_ptr camera = cameraManager->GetCameraBySerial(view(i, 0)); //printf("[INFO] About to Check if camera with serial %i is running...\n", serials(i)); if (!camera->IsCameraRunning()) { printf("[WARNING] CAMERA IS NOT RUNNING!\n"); camera->Start(); } - Frame* frame; bool success = false; + std::shared_ptr frame; bool success = false; while(!success){ try { //printf("[INFO] About to read SubFrame %i with serial %i\n", i, serials(i)); - frame = camera->GetLatestFrame();//camera->GetFrame();// + frame = camera->LatestFrame();//camera->GetFrame();// success = true; } catch (...) { // This never gets triggered; it just silently crashes... @@ -126,7 +123,7 @@ NB_MODULE(pyopticam_ext, m) { } if(!(frame->IsInvalid())){ //printf("[INFO] Getting Subframe Size\n"); - int size = frame->GetGrayscaleDataSize(); + int size = frame->GrayscaleDataSize(); //printf("[INFO] SubFrame Size is: %i\n", size); if(offset == 0) { @@ -143,14 +140,13 @@ NB_MODULE(pyopticam_ext, m) { } size_t shape[3] = { count, height, width }; nb::capsule deleter(full_buffer, [](void *p) noexcept { delete[] (uint8_t *) p; }); /// Delete 'full_buffer' when the 'deleter' capsule expires - tensor = nb::tensor(full_buffer, 3, shape, deleter); + ndarray = nb::ndarray(full_buffer, 3, shape, deleter); } if(size > width * height){ printf("[WARNING] Couldn't MemCpy; Count = %i, Offset = %i, Size = %i, Width = %i, Height = %i\n", count, offset, size, width, height); - frame->Release(); break; }else{ - uint8_t* data = frame->GetGrayscaleData(); + const uint8_t* data = frame->GrayscaleData(*camera); // Copy the frame from the Optitrack SDK to our contiguous Numpy-Managed Buffer //printf("[INFO] Starting MemCpy at address: %zu, offset forward by %zu\n", (size_t)data, (size_t)data - last_address); last_address = (size_t)data; @@ -158,28 +154,28 @@ NB_MODULE(pyopticam_ext, m) { offset += size; } } else { - printf("[WARNING] Subframe was Empty or Invalid! From camera: %i\n", frame->GetCamera()->Serial()); + printf("[WARNING] Subframe was Empty or Invalid! From camera: %i\n", camera->Serial()); } - frame->Release(); } //frameGroup->Release(); - if(offset == 0) { printf("[WARNING] No full or valid frames were found in the FrameGroup! Returning Default Tensor...\n"); } + if(offset == 0) { printf("[WARNING] No full or valid frames were found in the FrameGroup! Returning Default ndarray...\n"); } nanobind::gil_scoped_acquire acquire; - return tensor; + return ndarray; }); + m.def("GetFrameGroup", [](cModuleSync* sync) { nanobind::gil_scoped_release release; //FrameGroup* frameGroup = sync -> GetFrameGroup(); //GetFrameGroupSharedPointer();// - std::shared_ptr frameGroup = sync->GetFrameGroupSharedPtr(); + std::shared_ptr frameGroup = sync->GetFrameGroup(); bool invalid_frame_group = !frameGroup || frameGroup == nullptr || frameGroup->Count() == 0; while(invalid_frame_group){ //printf("[INFO] Bad Framegroup; Sleeping...\n"); //Sleep(8); //frameGroup = sync -> GetFrameGroup(); - frameGroup = sync->GetFrameGroupSharedPtr(); + frameGroup = sync->GetFrameGroup(); invalid_frame_group = !frameGroup || frameGroup == nullptr || frameGroup->Count() == 0; //if(invalid_frame_group){ @@ -194,12 +190,13 @@ NB_MODULE(pyopticam_ext, m) { return frameGroup; }); - m.def("FillTensorFromFrameGroup", [](std::shared_ptr frameGroup, nb::tensor tensor) { //,uint8_t, nb::shape<8, 1024, 1280>, nb::c_contig, nb::device::cpu + + m.def("FillTensorFromFrameGroup", [](std::shared_ptr camera, std::shared_ptr frameGroup, nb::ndarray ndarray) { //,uint8_t, nb::shape<8, 1024, 1280>, nb::c_contig, nb::device::cpu nanobind::gil_scoped_release release; //uint8_t *stand_in_data = new uint8_t[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; //size_t stand_in_shape[3] = { 8, 1, 1 }; //nb::capsule stand_in_deleter(stand_in_data, [](void *p) noexcept { delete[] (uint8_t *) p; }); - //nb::tensor tensor = nb::tensor(stand_in_data, 3, stand_in_shape, /* owner = */ stand_in_deleter); + //nb::ndarray ndarray = nb::ndarray(stand_in_data, 3, stand_in_shape, stand_in_deleter); size_t offset = 0; if(frameGroup && frameGroup != nullptr && frameGroup->Count() > 0 ){ @@ -210,28 +207,27 @@ NB_MODULE(pyopticam_ext, m) { //printf("[WARNING] FrameGroup Count = %i\n", count); for(int i = 0; i < count; i++){ - Frame* frame = frameGroup->GetFrame(i); + std::shared_ptr frame = frameGroup->GetFrame(i); if(!(frame->IsInvalid())){ - int size = frame->GetGrayscaleDataSize(); + int size = frame->GrayscaleDataSize(); if(offset == 0) { //stand_in_deleter.release(); height = frame->Height(); width = frame->Width(); while(full_buffer == nullptr){ - full_buffer = (uint8_t*)tensor.data();//(uint8_t*) malloc(size * (count+1)); + full_buffer = (uint8_t*)ndarray.data();//(uint8_t*) malloc(size * (count+1)); if(full_buffer == nullptr){ printf("[ERROR] Failed to allocate memory for full buffer! Trying again...\n"); Sleep(2); } } } - if(size > width * height || tensor.shape(1) < height || tensor.shape(2) < width){ + if(size > width * height || ndarray.shape(1) < height || ndarray.shape(2) < width){ printf("[WARNING] Couldn't MemCpy, wrong shape; Count = %i, Offset = %zi, Size = %i, Width = %i, Height = %i\n", count, offset, size, width, height); - frame->Release(); break; }else{ - uint8_t* data = frame->GetGrayscaleData(); + const uint8_t* data = frame->GrayscaleData(*camera); // Copy the frame from the Optitrack SDK to our contiguous Numpy-Managed Buffer //printf("[WARNING] Starting MemCpy at address: %zu, offset forward by %zu\n", (size_t)data, (size_t)data - last_address); //last_address = (size_t)data; @@ -239,16 +235,15 @@ NB_MODULE(pyopticam_ext, m) { offset += size; } } else { - printf("[WARNING] Subframe was Empty or Invalid! From camera: %i\n", frame->GetCamera()->Serial()); + printf("[WARNING] Subframe was Empty or Invalid!");// From camera : % i\n", frame->GetCamera()->Serial()); } - frame->Release(); } }else{ printf("[WARNING] Framegroup is a nullptr or has an invalid number of cameras!\n"); } //frameGroup->Release(); - if(offset == 0) { printf("[WARNING] No full or valid frames were found in the FrameGroup! Returning Default Tensor...\n"); } - //return tensor; + if(offset == 0) { printf("[WARNING] No full or valid frames were found in the FrameGroup! Returning Default ndarray...\n"); } + //return ndarray; nanobind::gil_scoped_acquire acquire; }); @@ -262,7 +257,7 @@ NB_MODULE(pyopticam_ext, m) { .value("MJPEGMode", Core::eVideoMode::MJPEGMode) .value("VideoMode", Core::eVideoMode::VideoMode) .value("SynchronizationTelemetry", Core::eVideoMode::SynchronizationTelemetry) - .value("VideoModeCount", Core::eVideoMode::VideoModeCount) + //.value("VideoModeCount", Core::eVideoMode::Video) .value("UnknownMode", Core::eVideoMode::UnknownMode); //.export_values(); @@ -287,60 +282,63 @@ NB_MODULE(pyopticam_ext, m) { .value("Disconnected", CameraLibrary::eCameraState::Disconnected) .value("Shutdown", CameraLibrary::eCameraState::Shutdown); - nb::enum_(m, "eOptimization") - .value("ForceTimelyDelivery" , CameraLibrary::cModuleSyncBase::eOptimization::ForceTimelyDelivery) - .value("FavorTimelyDelivery", CameraLibrary::cModuleSyncBase::eOptimization::FavorTimelyDelivery) - .value("ForceCompleteDelivery", CameraLibrary::cModuleSyncBase::eOptimization::ForceCompleteDelivery) - .value("eOptimizationCount", CameraLibrary::cModuleSyncBase::eOptimization::eOptimizationCount); + nb::enum_(m, "eOptimization") + .value("ForceTimelyDelivery" , CameraLibrary::cModuleSync::eOptimization::ForceTimelyDelivery) + .value("FavorTimelyDelivery", CameraLibrary::cModuleSync::eOptimization::FavorTimelyDelivery) + .value("ForceCompleteDelivery", CameraLibrary::cModuleSync::eOptimization::ForceCompleteDelivery) + .value("eOptimizationCount", CameraLibrary::cModuleSync::eOptimization::eOptimizationCount); nb::class_(m, "sStatusLightColor") .def(nb::init()) - .def_readwrite("Red", &sStatusLightColor::Red) - .def_readwrite("Green", &sStatusLightColor::Green) - .def_readwrite("Blue", &sStatusLightColor::Blue); - - nb::class_(m, "cModuleSyncBase") - .def("AddCamera", &CameraLibrary::cModuleSyncBase::AddCamera) - .def("CameraCount", &CameraLibrary::cModuleSyncBase::CameraCount) - .def("GetFrameGroup", &CameraLibrary::cModuleSyncBase::GetFrameGroup) - .def("GetFrameGroupSharedPtr", &CameraLibrary::cModuleSync::GetFrameGroupSharedPtr) - .def("LastFrameGroupMode", &CameraLibrary::cModuleSyncBase::LastFrameGroupMode) - .def("AllowIncompleteGroups", &CameraLibrary::cModuleSyncBase::AllowIncompleteGroups) - .def("SetAllowIncompleteGroups", &CameraLibrary::cModuleSyncBase::SetAllowIncompleteGroups) - .def("SetOptimization", &CameraLibrary::cModuleSyncBase::SetOptimization) - .def("Optimization", &CameraLibrary::cModuleSyncBase::Optimization) - .def("RemoveAllCameras", &CameraLibrary::cModuleSyncBase::RemoveAllCameras) - .def("SetSuppressOutOfOrder", &CameraLibrary::cModuleSyncBase::SetSuppressOutOfOrder) - .def("IsSuppressOutOfOrder", &CameraLibrary::cModuleSyncBase::IsSuppressOutOfOrder); - //.def("FlushFrames", &CameraLibrary::cModuleSyncBase::FlushFrames); - - nb::class_(m, "cModuleSync") + .def_rw("Red", &sStatusLightColor::Red) + .def_rw("Green", &sStatusLightColor::Green) + .def_rw("Blue", &sStatusLightColor::Blue); + + nb::class_(m, "cModuleSync") .def_static("Create", CameraLibrary::cModuleSync::Create, nb::rv_policy::reference) .def_static("Destroy", CameraLibrary::cModuleSync::Destroy) .def("PostFrame", &CameraLibrary::cModuleSync::PostFrame) .def("FrameDeliveryRate", &CameraLibrary::cModuleSync::FrameDeliveryRate) // Virtual + .def("AddCamera", &CameraLibrary::cModuleSync::AddCamera) + .def("CameraCount", &CameraLibrary::cModuleSync::CameraCount) + .def("GetFrameGroup", &CameraLibrary::cModuleSync::GetFrameGroup) + //.def("GetFrameGroupSharedPtr", &CameraLibrary::cModuleSync::GetFrameGroupSharedPtr) + .def("LastFrameGroupMode", &CameraLibrary::cModuleSync::LastFrameGroupMode) + .def("AllowIncompleteGroups", &CameraLibrary::cModuleSync::AllowIncompleteGroups) + .def("SetAllowIncompleteGroups", &CameraLibrary::cModuleSync::SetAllowIncompleteGroups) + .def("SetOptimization", &CameraLibrary::cModuleSync::SetOptimization) + .def("Optimization", &CameraLibrary::cModuleSync::Optimization) + .def("RemoveAllCameras", &CameraLibrary::cModuleSync::RemoveAllCameras) + .def("SetSuppressOutOfOrder", &CameraLibrary::cModuleSync::SetSuppressOutOfOrder) + //.def("IsSuppressOutOfOrder", &CameraLibrary::cModuleSync::Out); + //.def("FlushFrames", &CameraLibrary::cModuleSync::FlushFrames) ; + //nb::class_(m, "cModuleSync") + // + // ; + nb::enum_(m, "Modes") .value("None" , CameraLibrary::FrameGroup::Modes::None) .value("Software", CameraLibrary::FrameGroup::Modes::Software) .value("Hardware", CameraLibrary::FrameGroup::Modes::Hardware) - .value("ModeCount", CameraLibrary::FrameGroup::Modes::ModeCount); + //.value("ModeCount", CameraLibrary::FrameGroup::Modes::ModeCount) + ; - nb::class_(m, "DroppedFrameInfo") - //.def(nb::init()) - .def("Serial", &DroppedFrameInfo::Serial) - .def("UserData", &DroppedFrameInfo::UserData); + //nb::class_(m, "DroppedFrameInfo") + // //.def(nb::init()) + // .def("Serial", &DroppedFrameInfo::Serial) + // .def("UserData", &DroppedFrameInfo::UserData); nb::class_(m, "FrameGroup") .def(nb::init()) .def("Count", &FrameGroup::Count) .def("GetFrame", &FrameGroup::GetFrame, nb::rv_policy::reference) - .def("GetFrameUserData", &FrameGroup::GetFrameUserData) - .def("AddRef", &FrameGroup::AddRef) - .def("Release", &FrameGroup::Release) + //.def("GetFrameUserData", &FrameGroup::GetFrameUserData) + //.def("AddRef", &FrameGroup::AddRef) + //.def("Release", &FrameGroup::Release) .def("AddFrame", &FrameGroup::AddFrame) - .def("Clear", &FrameGroup::Clear) + //.def("Clear", &FrameGroup::Clear) .def("SetMode", &FrameGroup::SetMode) .def("Mode", &FrameGroup::Mode) .def("SetTimeStamp", &FrameGroup::SetTimeStamp) @@ -353,8 +351,8 @@ NB_MODULE(pyopticam_ext, m) { .def("LatestTimeStamp", &FrameGroup::LatestTimeStamp) .def("FrameID", &FrameGroup::FrameID) .def("TimeSpreadDeviation", &FrameGroup::TimeSpreadDeviation) - .def("DroppedFrameCount", &FrameGroup::DroppedFrameCount) - .def("DroppedFrame", &FrameGroup::DroppedFrame) + //.def("DroppedFrameCount", &FrameGroup::DroppedFrameCount) + .def("DroppedFrames", &FrameGroup::DroppedFrames) ; nb::class_(m, "cCameraLibraryStartupSettings") @@ -364,14 +362,14 @@ NB_MODULE(pyopticam_ext, m) { .def("IsDevelopmentEnabled", &cCameraLibraryStartupSettings::IsDevelopmentEnabled); nb::class_(m, "Frame") - .def(nb::init()) + //.def(nb::init()) .def("ObjectCount", &Frame::ObjectCount) .def("FrameID", &Frame::FrameID) .def("FrameType", &Frame::FrameType) .def("MJPEGQuality", &Frame::MJPEGQuality) .def("Object", &Frame::Object) - .def("GetLink", &Frame::GetLink) - .def("GetCamera", &Frame::GetCamera) + //.def("GetLink", &Frame::GetLink) + //.def("GetCamera", &Frame::GetCamera) .def("IsInvalid", &Frame::IsInvalid) .def("IsEmpty", &Frame::IsEmpty) .def("IsGrayscale", &Frame::IsGrayscale) @@ -384,40 +382,41 @@ NB_MODULE(pyopticam_ext, m) { .def("Scale", &Frame::Scale) .def("TimeStamp", &Frame::TimeStamp) .def("IsSynchInfoValid", &Frame::IsSynchInfoValid) - .def("IsTimeCodeValid", &Frame::IsTimeCodeValid) + //.def("IsTimeCodeValid", &Frame::IsTimeCodeValid) .def("IsExternalLocked", &Frame::IsExternalLocked) .def("IsRecording", &Frame::IsRecording) - .def("TimeCode", &Frame::TimeCode) - .def("IMUTelemetryCount", &Frame::IMUTelemetryCount) - .def("IMUTelemetry", &Frame::IMUTelemetry) + //.def("TimeCode", &Frame::TimeCode) + //.def("IMUTelemetryCount", &Frame::IMUTelemetryCount) + //.def("IMUTelemetry", &Frame::IMUTelemetry) .def("HardwareTimeStampValue", &Frame::HardwareTimeStampValue) .def("HardwareTimeStamp", &Frame::HardwareTimeStamp) .def("IsHardwareTimeStamp", &Frame::IsHardwareTimeStamp) .def("HardwareTimeFreq", &Frame::HardwareTimeFreq) .def("MasterTimingDevice", &Frame::MasterTimingDevice) - .def("Release", &Frame::Release) - .def("RefCount", &Frame::RefCount) - .def("AddRef", &Frame::AddRef) + //.def("Release", &Frame::Release) + //.def("RefCount", &Frame::RefCount) + //.def("AddRef", &Frame::AddRef) //.def("Rasterize", &Frame::Rasterize) // Overloads! //.def("Rasterize", &Frame::Rasterize) - .def("CompressedImageSize", &Frame::CompressedImageSize) - .def("GetGrayscaleData", &Frame::GetGrayscaleData) - .def("GetGrayscaleDataSize", &Frame::GetGrayscaleDataSize) + .def("ImageDataSize", &Frame::ImageDataSize) + //.def("GrayscaleData", Frame::GrayscaleData) // <-- TODO: Need to pass in a pointer... + .def("GrayscaleDataSize", &Frame::GrayscaleDataSize) .def("SetObjectCount", &Frame::SetObjectCount) .def("RemoveObject", &Frame::RemoveObject) //.def("HardwareRecording", &Frame::HardwareRecording) ; nb::class_(m, "Camera") - .def(nb::init()) - //.def("Width", &Camera::Width) - //.def("Height", &Camera::Height) - .def("GetFrame", &Camera::GetFrame) + //.def(nb::init()) + .def("Width", &Camera::Width) + .def("Height", &Camera::Height) + .def("LatestFrame", &Camera::LatestFrame) + .def("NextFrame", &Camera::NextFrame) .def("Name", &Camera::Name) .def("Start", &Camera::Start) .def("Stop", &Camera::Stop) .def("IsCameraRunning", &Camera::IsCameraRunning) - .def("Release", &Camera::Release) // Virtual + //.def("Release", &Camera::Release) // Virtual .def("SetNumeric", &Camera::SetNumeric) .def("SetExposure", &Camera::SetExposure) .def("SetThreshold", &Camera::SetThreshold) @@ -479,14 +478,14 @@ NB_MODULE(pyopticam_ext, m) { .def("IsContinuousIRAvailable", &Camera::IsContinuousIRAvailable) // Virtual .def("SetContinuousIR", &Camera::SetContinuousIR) // Virtual .def("ContinuousIR", &Camera::ContinuousIR) // Virtual - .def("IsQuietModeAvailable", &Camera::IsQuietModeAvailable) // Virtual - .def("SetQuietMode", &Camera::SetQuietMode) // Virtual - .def("QuietMode", &Camera::QuietMode) + //.def("IsQuietModeAvailable", &Camera::IsQuietModeAvailable) // Virtual + //.def("SetQuietMode", &Camera::SetQuietMode) // Virtual + //.def("QuietMode", &Camera::QuietMode) .def("SetRinglightEnabledWhileStopped", &Camera::SetRinglightEnabledWhileStopped) // Virtual .def("RinglightEnabledWhileStopped", &Camera::RinglightEnabledWhileStopped) // Virtual .def("IsHardwareFiltered", &Camera::IsHardwareFiltered) // Virtual, Uses Enum .def("SwitchState", &Camera::SwitchState) - .def("Health", &Camera::Health) + //.def("Health", &Camera::Health) .def("GetDistortionModel", &Camera::GetDistortionModel) // Virtual .def("ResetWindow", &Camera::ResetWindow) .def("SetWindow", &Camera::SetWindow) // Virtual @@ -523,7 +522,7 @@ NB_MODULE(pyopticam_ext, m) { .def("TextOverlay", &Camera::TextOverlay) .def("MarkerOverlay", &Camera::MarkerOverlay) //.def("SetName", &Camera::SetName) - .def("IsInitilized", &Camera::IsInitilized) + .def("IsInitialized", &Camera::IsInitialized) .def("IsDisconnected", &Camera::IsDisconnected) .def("State", &Camera::State) .def("UID", &Camera::UID) @@ -533,9 +532,9 @@ NB_MODULE(pyopticam_ext, m) { //.def("DetachInput", &Camera::DetachInput) //.def("TransferInput", &Camera::TransferInput) // Virtual .def("IsCommandQueueEmpty", &Camera::IsCommandQueueEmpty) - .def("ReleaseFrame", &Camera::ReleaseFrame) + //.def("ReleaseFrame", &Camera::ReleaseFrame) //.def("DevicePath", &Camera::DevicePath) - .def("SendCommand", &Camera::SendCommand) // Virtual + //.def("SendCommand", &Camera::SendCommand) // Virtual .def("AttachModule", &Camera::AttachModule) .def("RemoveModule", &Camera::RemoveModule) .def("ModuleCount", &Camera::ModuleCount) @@ -553,7 +552,7 @@ NB_MODULE(pyopticam_ext, m) { .def("SyncFeatures", &Camera::SyncFeatures) // Virtual .def("SetObjectColor", &Camera::SetObjectColor) .def("ObjectColor", &Camera::ObjectColor) - .def("SetGrayscaleFloor", &Camera::SetGrayscaleFloor) // Virtual + .def("SetGrayscaleDecimation", &Camera::SetGrayscaleDecimation) // Virtual //.def("FrameSize", &Camera::FrameSize) // Virtual .def("SetEnablePayload", &Camera::SetEnablePayload) // Virtual @@ -562,11 +561,11 @@ NB_MODULE(pyopticam_ext, m) { .def("CameraTemp", &Camera::CameraTemp) // Virtual .def("IsRinglightTempValid", &Camera::IsRinglightTempValid) // Virtual .def("RinglightTemp", &Camera::RinglightTemp) // Virtual - .def("IsCameraFanSpeedValid", &Camera::IsCameraFanSpeedValid) // Virtual - .def("CameraFanSpeed", &Camera::CameraFanSpeed) // Virtual + //.def("IsCameraFanSpeedValid", &Camera::IsCameraFanSpeedValid) // Virtual + //.def("CameraFanSpeed", &Camera::CameraFanSpeed) // Virtual .def("IsPoEPlusActive", &Camera::IsPoEPlusActive) // Virtual .def("SetLLDPDetection", &Camera::SetLLDPDetection) // Uses Enum - .def("IsLLDPDetectionAvaiable", &Camera::IsLLDPDetectionAvaiable) // Virtual // Uses Enum + .def("IsLLDPDetectionAvailable", &Camera::IsLLDPDetectionAvailable) // Virtual // Uses Enum .def("LLDPDetection", &Camera::LLDPDetection) // Uses Enum .def("MinimumExposureValue", &Camera::MinimumExposureValue) // Virtual .def("MaximumExposureValue", &Camera::MaximumExposureValue) // Virtual @@ -603,7 +602,7 @@ NB_MODULE(pyopticam_ext, m) { .def("IsHardwareTimeStampValueSupported", &Camera::IsHardwareTimeStampValueSupported) // Virtual .def("SetColorEnhancement", &Camera::SetColorEnhancement) // Virtual .def("ColorEnhancement", &Camera::ColorEnhancement) // Virtual - .def("SetPixelIntensityMapping", &Camera::SetPixelIntensityMapping) // Virtual + //.def("SetPixelIntensityMapping", &Camera::SetPixelIntensityMapping) // Virtual ; nb::class_(m, "CameraManager") @@ -623,14 +622,14 @@ NB_MODULE(pyopticam_ext, m) { .def("PrepareForSuspend", &CameraManager::PrepareForSuspend) .def("ResumeFromSuspend", &CameraManager::ResumeFromSuspend) .def("TimeStamp", &CameraManager::TimeStamp) - .def("TimeStampFrequency", &CameraManager::TimeStampFrequency) - .def("ResetTimeStamp", &CameraManager::ResetTimeStamp) + //.def("TimeStampFrequency", &CameraManager::TimeStampFrequency) + //.def("ResetTimeStamp", &CameraManager::ResetTimeStamp) .def("RegisterListener", &CameraManager::RegisterListener) .def("UnregisterListener", &CameraManager::UnregisterListener) .def_static("CameraFactory", CameraManager::CameraFactory) .def("AddCamera", &CameraManager::AddCamera) .def("RemoveCamera", &CameraManager::RemoveCamera) - .def("RemoveVirtualCameras", &CameraManager::RemoveVirtualCameras) + //.def("RemoveVirtualCameras", &CameraManager::RemoveCamera) .def("ScanForCameras", &CameraManager::ScanForCameras) .def("ApplySyncSettings", &CameraManager::ApplySyncSettings) .def("GetSyncSettings", &CameraManager::GetSyncSettings) @@ -685,16 +684,16 @@ NB_MODULE(pyopticam_ext, m) { .def("Count", &HardwareDeviceList::Count) ; - nb::class_(m, "CameraManagerListener") + nb::class_(m, "CameraManagerListener") //.def(nb::init()) - .def("CameraConnected", &CameraManagerListener::CameraConnected) // Virtual - .def("CameraRemoved", &CameraManagerListener::CameraRemoved) // Virtual - .def("SyncSettingsChanged", &CameraManagerListener::SyncSettingsChanged) // Virtual - .def("CameraInitialized", &CameraManagerListener::CameraInitialized) // Virtual - .def("SyncAuthorityInitialized", &CameraManagerListener::SyncAuthorityInitialized) // Virtual - .def("SyncAuthorityRemoved", &CameraManagerListener::SyncAuthorityRemoved) // Virtual - .def("CameraMessage", &CameraManagerListener::CameraMessage) // Virtual - .def("RequestUnknownDeviceImplementation", &CameraManagerListener::RequestUnknownDeviceImplementation) // Virtual + .def("CameraConnected", &cCameraManagerListener::CameraConnected) // Virtual + .def("CameraRemoved", &cCameraManagerListener::CameraRemoved) // Virtual + .def("SyncSettingsChanged", &cCameraManagerListener::SyncSettingsChanged) // Virtual + .def("CameraInitialized", &cCameraManagerListener::CameraInitialized) // Virtual + .def("SyncAuthorityInitialized", &cCameraManagerListener::SyncAuthorityInitialized) // Virtual + .def("SyncAuthorityRemoved", &cCameraManagerListener::SyncAuthorityRemoved) // Virtual + .def("CameraMessage", &cCameraManagerListener::CameraMessage) // Virtual + .def("RequestUnknownDeviceImplementation", &cCameraManagerListener::RequestUnknownDeviceImplementation) // Virtual //.def("ShouldConnectCamera", &CameraManagerListener::ShouldConnectCamera) // Virtual ; @@ -714,4 +713,10 @@ NB_MODULE(pyopticam_ext, m) { .def("isNotEqualTo", &Core::cUID::operator!=) //.def_readonly_static("Invalid", &Core::cUID::kInvalid) ; + + //nb::class_(m, "cTimeCode") + // .def(nb::init()) + // //.def("from_string", &Core::cUID::from_string) + // .def("SetValue", &Core::cTimeCode::) + // ; }