From b45a9aabc220801e05ad5493f5571580a65b8f63 Mon Sep 17 00:00:00 2001 From: Andy Sorge <124544413+asorge29@users.noreply.github.com> Date: Fri, 20 Feb 2026 02:22:23 -0800 Subject: [PATCH 01/33] feat: init CameraManager to interface with Spinnaker SDK --- .github/CODEOWNERS | 7 +- src/guppy_vision/CMakeLists.txt | 28 +++++- src/guppy_vision/src/camera_manager.cpp | 114 ++++++++++++++++++++++++ src/guppy_vision/src/camera_manager.hpp | 40 +++++++++ 4 files changed, 184 insertions(+), 5 deletions(-) create mode 100644 src/guppy_vision/src/camera_manager.cpp create mode 100644 src/guppy_vision/src/camera_manager.hpp diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index eea392a..7c2dec8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -5,7 +5,10 @@ Dockerfile @B0gos src/guppy @cole-wilson src/guppy_control @cole-wilson +src/guppy_description @cole-wilson + src/guppy_can @andy-sorge src/guppy_teleop @andy-sorge -src/guppy_state @ryden-handsaker -src/guppy_description @cole-wilson \ No newline at end of file +src/guppy_vision @andy-sorge + +src/guppy_state @ryden-handsaker \ No newline at end of file diff --git a/src/guppy_vision/CMakeLists.txt b/src/guppy_vision/CMakeLists.txt index 7b1ec59..04565c5 100644 --- a/src/guppy_vision/CMakeLists.txt +++ b/src/guppy_vision/CMakeLists.txt @@ -7,9 +7,31 @@ endif() # find dependencies find_package(ament_cmake REQUIRED) -# uncomment the following section in order to fill in -# further dependencies manually. -# find_package( REQUIRED) + +# Spinnaker paths +set(SPINNAKER_INCLUDE_DIR /opt/spinnaker/include) +set(SPINNAKER_LIBRARY /opt/spinnaker/lib/libSpinnaker.so) + +# Create imported library target +add_library(Spinnaker::Spinnaker SHARED IMPORTED) + +set_target_properties(Spinnaker::Spinnaker PROPERTIES + IMPORTED_LOCATION ${SPINNAKER_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES ${SPINNAKER_INCLUDE_DIR} +) + +add_executable(ack + src/ack.cpp) + +add_executable(camera_utils src/camera_utils.cpp) + +target_link_libraries(ack + Spinnaker::Spinnaker +) + +target_link_libraries(camera_utils + Spinnaker::Spinnaker +) if(BUILD_TESTING) find_package(ament_lint_auto REQUIRED) diff --git a/src/guppy_vision/src/camera_manager.cpp b/src/guppy_vision/src/camera_manager.cpp new file mode 100644 index 0000000..4ff29b1 --- /dev/null +++ b/src/guppy_vision/src/camera_manager.cpp @@ -0,0 +1,114 @@ +#include "camera_manager.hpp" + +using namespace camera_manager; + +CameraManager::CameraManager() { + system = System::GetInstance(); + camList = system->GetCameras(); +} + +CameraManager::~CameraManager() { + cout << "Attempting graceful exit." << endl; + + camList.Clear(); + system->ReleaseInstance(); + + cout << "Successfully exited gracefully." << endl; +} + +void CameraManager::takePicture(CameraPtr pCam) { + INodeMap& nodeMapTLDevice = pCam->GetTLDeviceNodeMap(); + pCam->Init(); + INodeMap& nodeMap = pCam->GetNodeMap(); + + cout << "Acquiring single image from " << nodeMapTLDevice.GetDeviceName() << endl; + + pCam->BeginAcquisition(); + + gcstring deviceSerialNumber(""); + CStringPtr ptrStringSerial = nodeMapTLDevice.GetNode("DeviceSerialNumber"); + deviceSerialNumber = ptrStringSerial->GetValue(); + + ImageProcessor processor; + processor.SetColorProcessing(SPINNAKER_COLOR_PROCESSING_ALGORITHM_HQ_LINEAR); + + ImagePtr pResultImage = pCam->GetNextImage(1000); + + const size_t width = pResultImage->GetWidth(); + + const size_t height = pResultImage->GetHeight(); + + cout << "Grabbed image: width = " << width << ", height = " << height << endl; + + ImagePtr convertedImage = processor.Convert(pResultImage, PixelFormat_RGB8); + + convertedImage->Save("saved.png"); + + pResultImage->Release(); + pCam->EndAcquisition(); + +} + +int CameraManager::setStreamMode(CameraPtr pCam, StreamMode mode) +{ + int result = 0; + + // Retrieve Stream nodemap + const INodeMap& sNodeMap = pCam->GetTLStreamNodeMap(); + + // The node "StreamMode" is only available for GEV cameras. + // Skip setting stream mode if the node is inaccessible. + const CEnumerationPtr ptrStreamMode = sNodeMap.GetNode("StreamMode"); + if (!IsReadable(ptrStreamMode) || !IsWritable(ptrStreamMode)) + { + return 0; + } + + gcstring streamMode; + switch (mode) + { + case STREAM_MODE_PGRLWF: + streamMode = "LWF"; + break; + case STREAM_MODE_SOCKET: + streamMode = "Socket"; + break; + case STREAM_MODE_TELEDYNE_GIGE_VISION: + default: + streamMode = "TeledyneGigeVision"; + } + + // Retrieve the desired entry node from the enumeration node + const CEnumEntryPtr ptrStreamModeCustom = ptrStreamMode->GetEntryByName(streamMode); + if (!IsReadable(ptrStreamModeCustom)) + { + // Failed to get custom node + cout << "Stream mode " + streamMode + " not available. Aborting..." << endl; + return -1; + } + // Retrieve the integer value from the entry node + const int64_t streamModeCustom = ptrStreamModeCustom->GetValue(); + + // Set integer as new value for enumeration node + ptrStreamMode->SetIntValue(streamModeCustom); + + // Print out the current stream mode + cout << endl << "Stream Mode set to " + ptrStreamMode->GetCurrentEntry()->GetSymbolic() << "..." << endl; + + return 0; +} + +int main(int argc, char *argv[]) { + + CameraManager manager; + + const unsigned int numCameras = manager.camList.GetSize(); + + cout << "Discovered " << numCameras << " cameras." << endl; + + CameraManager::takePicture(manager.camList[0]); + + cout << "Exiting." << endl; + + return 0; +} \ No newline at end of file diff --git a/src/guppy_vision/src/camera_manager.hpp b/src/guppy_vision/src/camera_manager.hpp new file mode 100644 index 0000000..926d8fb --- /dev/null +++ b/src/guppy_vision/src/camera_manager.hpp @@ -0,0 +1,40 @@ +#ifndef GUPPY_VISION_CAMERA_UTILS_HPP +#define GUPPY_VISION_CAMERA_UTILS_HPP + +#include +#include +#include +#include + +using namespace Spinnaker; +using namespace Spinnaker::GenApi; +using namespace Spinnaker::GenICam; +using namespace std; + +enum StreamMode +{ + STREAM_MODE_TELEDYNE_GIGE_VISION, // windows + STREAM_MODE_PGRLWF, // legacy windows + STREAM_MODE_SOCKET, // macos and linux +}; + +namespace camera_manager { + + class CameraManager { + + public: + CameraManager(); + ~CameraManager(); + + SystemPtr system; + CameraList camList; + + static int setStreamMode(CameraPtr pCam, StreamMode mode); + + static void takePicture(CameraPtr pCam); + + }; + +} + +#endif //GUPPY_VISION_CAMERA_UTILS_HPP \ No newline at end of file From 34c091f269bbf589ec288250d1555c85f8492b79 Mon Sep 17 00:00:00 2001 From: Andy Sorge <124544413+asorge29@users.noreply.github.com> Date: Sat, 28 Feb 2026 17:58:36 -0800 Subject: [PATCH 02/33] basic camera feed --- .idea/.gitignore | 10 - .idea/codeStyles/Project.xml | 15 +- .idea/dictionaries/project.xml | 7 - .idea/editor.xml | 247 +----------------------- .idea/guppy.iml | 8 - .idea/jsonSchemas.xml | 26 --- .idea/misc.xml | 6 - .idea/modules.xml | 8 - .idea/vcs.xml | 3 + .idea/workspace.xml | 145 ++++++++++++++ src/guppy_vision/CMakeLists.txt | 34 ++-- src/guppy_vision/package.xml | 3 + src/guppy_vision/src/camera_manager.cpp | 5 +- src/guppy_vision/src/camera_pub.cpp | 72 +++++++ 14 files changed, 254 insertions(+), 335 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/dictionaries/project.xml delete mode 100644 .idea/guppy.iml delete mode 100644 .idea/jsonSchemas.xml delete mode 100644 .idea/modules.xml create mode 100644 .idea/workspace.xml create mode 100644 src/guppy_vision/src/camera_pub.cpp diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index ab1f416..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Ignored default folder with query files -/queries/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 81469bd..4c195d2 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,7 +1,6 @@ -