commit c2f29509d15a98c17d040098fb343a9338365101 Author: Grant Terris Date: Sun Aug 4 13:30:46 2019 -0700 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3f031f5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.out \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..a20448b --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,17 @@ +{ + "configurations": [ + { + "name": "Linux", + "includePath": [ + "${workspaceFolder}/**", + "/opt/pleora/ebus_sdk/Ubuntu-x86_64/include/**" + ], + "defines": [], + "compilerPath": "/usr/bin/gcc", + "cStandard": "c11", + "cppStandard": "c++11", + "intelliSenseMode": "clang-x64" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c2453c8 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,29 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Build and Debug", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/FaultFinder.out", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "preLaunchTask": "make", + "miDebuggerPath": "/usr/bin/gdb" + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..0cba2e6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "files.associations": { + "iostream": "cpp" + } +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..2b44cab --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,17 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "make", + "type": "shell", + "command": "make", + "args": [ + "debug" + ], + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/FaultFinder.cpp b/FaultFinder.cpp new file mode 100644 index 0000000..22c3336 --- /dev/null +++ b/FaultFinder.cpp @@ -0,0 +1,30 @@ +#include + +#include "StreamManager.hpp" + +using namespace std; + +int main() +{ + StreamManager mgr; + PvString lConnectionID; + + // If no devies are found, exit. + if (mgr.FindDevice(&lConnectionID).IsFailure()) + { + return -1; + } + + if (mgr.ConnectToDevice(lConnectionID).IsFailure()) + { + return -1; + } + + mgr.OpenStream(lConnectionID); + + mgr.AcquireImages(); + + mgr.Disconnect(); + + return 0; +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9255ba7 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +CXXFLAGS = -c -std=c++11 + +all: FaultFinder.o StreamManager.o + g++ *.o -o FaultFinder.out -L /opt/pleora/ebus_sdk/Ubuntu-x86_64/lib -lPvAppUtils -lPtConvertersLib -lPvBase -lPvBuffer -lPvGenICam -lPvSystem -lPvStream -lPvDevice -lPvTransmitter -lPvVirtualDevice -lPvPersistence -lPvSerial -lPvCameraBridge -lPvGUI -lSimpleImagingLib + +run: all + ./FaultFinder.out + +FaultFinder.o: FaultFinder.cpp + g++ $(CXXFLAGS) -o FaultFinder.o FaultFinder.cpp -I /opt/pleora/ebus_sdk/Ubuntu-x86_64/include + +StreamManager.o: StreamManager.cpp + g++ $(CXXFLAGS) -o StreamManager.o StreamManager.cpp -I /opt/pleora/ebus_sdk/Ubuntu-x86_64/include + +debug: CXXFLAGS += -g +debug: clean all + +clean: + rm -rf *.out *.o \ No newline at end of file diff --git a/StreamManager.cpp b/StreamManager.cpp new file mode 100644 index 0000000..0206cc1 --- /dev/null +++ b/StreamManager.cpp @@ -0,0 +1,272 @@ +#include + +#include +#include +#include +#include +#include + +#include "StreamManager.hpp" + +PvResult StreamManager::FindDevice(PvString *aConnectionID) +{ + PvResult lResult = PvResult(); + const PvDeviceInfo *lSelectedDI = NULL; + PvSystem lSystem; + + lSystem.Find(); + + // Detect, select device. + std::vector lDIVector; + for (uint32_t i = 0; i < lSystem.GetInterfaceCount(); i++) + { + const PvInterface *lInterface = dynamic_cast(lSystem.GetInterface(i)); + if (lInterface != NULL) + { + for (uint32_t j = 0; j < lInterface->GetDeviceCount(); j++) + { + const PvDeviceInfo *lDI = dynamic_cast(lInterface->GetDeviceInfo(j)); + if (lDI != NULL) + { + lDIVector.push_back(lDI); + } + } + } + } + + if (lDIVector.size() == 0) + { + std::cout << "Device not found!" << std::endl; + lResult.SetCode(PV_NOT_FOUND); + return lResult; + } + + lSelectedDI = lDIVector.front(); + + *aConnectionID = lSelectedDI->GetConnectionID(); + + lResult.SetCode(PV_OK); + + return lResult; +} + +PvResult StreamManager::ConnectToDevice(const PvString &aConnectionID) +{ + PvResult lResult; + + // Connect to the GigE Vision or USB3 Vision device + std::cout << "Connecting to device." << std::endl; + lDevice = PvDevice::CreateAndConnect(aConnectionID, &lResult); + if (lDevice == NULL) + { + std::cout << "Unable to connect to device." << std::endl; + } + + return lResult; +} + +PvResult StreamManager::OpenStream(const PvString &aConnectionID) +{ + PvResult lResult; + + if (lDevice == NULL) + { + return lResult; + } + + // Open stream to the GigE Vision or USB3 Vision device + std::cout << "Opening stream from device." << std::endl; + lStream = PvStream::CreateAndOpen(aConnectionID, &lResult); + + if (lStream != NULL) + { + // If this is a GigE Vision device, configure GigE Vision specific streaming parameters + PvDeviceGEV* lDeviceGEV = dynamic_cast(lDevice); + if ( lDeviceGEV != NULL ) + { + PvStreamGEV *lStreamGEV = static_cast(lStream); + + // Negotiate packet size + lDeviceGEV->NegotiatePacketSize(); + + // Configure device streaming destination + lDeviceGEV->SetStreamDestination( lStreamGEV->GetLocalIPAddress(), lStreamGEV->GetLocalPort() ); + } + } + else + { + std::cout << "Unable to stream from device." << std::endl; + } + + return lResult; +} + +void StreamManager::CreateStreamBuffers() +{ + // Reading payload size from device + uint32_t lSize = lDevice->GetPayloadSize(); + + // Use BUFFER_COUNT or the maximum number of buffers, whichever is smaller + uint32_t lBufferCount = (lStream->GetQueuedBufferMaximum() < BUFFER_COUNT) ? + lStream->GetQueuedBufferMaximum() : + BUFFER_COUNT; + + // Allocate buffers + for (uint32_t i = 0; i < lBufferCount; i++) + { + // Create new buffer object + PvBuffer *lBuffer = new PvBuffer; + + // Have the new buffer object allocate payload memory + lBuffer->Alloc(static_cast(lSize)); + + // Add to external list - used to eventually release the buffers + lBufferList.push_back(lBuffer); + } + + // Queue all buffers in the stream + BufferList::iterator lIt = lBufferList.begin(); + while (lIt != lBufferList.end()) + { + lStream->QueueBuffer( *lIt ); + lIt++; + } +} + +void StreamManager::AcquireImages() +{ + if (lDevice == NULL || lStream == NULL) + { + return; + } + + CreateStreamBuffers(); + + // Get device parameters need to control streaming + PvGenParameterArray *lDeviceParams = lDevice->GetParameters(); + + // Map the GenICam AcquisitionStart and AcquisitionStop commands + PvGenCommand *lStart = dynamic_cast(lDeviceParams->Get("AcquisitionStart")); + PvGenCommand *lStop = dynamic_cast(lDeviceParams->Get("AcquisitionStop")); + + // Get stream parameters + PvGenParameterArray *lStreamParams = lStream->GetParameters(); + + // Map a few GenICam stream stats counters + PvGenFloat *lFrameRate = dynamic_cast(lStreamParams->Get("AcquisitionRate")); + PvGenFloat *lBandwidth = dynamic_cast(lStreamParams->Get("Bandwidth")); + + // Enable streaming and send the AcquisitionStart command + std::cout << "Enabling streaming and sending AcquisitionStart command." << std::endl; + lDevice->StreamEnable(); + lStart->Execute(); + + double lFrameRateVal = 0.0; + double lBandwidthVal = 0.0; + + // Acquire images until the user instructs us to stop. + while (true) + { + PvBuffer *lBuffer = NULL; + PvResult lOperationResult; + + // Retrieve next buffer + PvResult lResult = lStream->RetrieveBuffer(&lBuffer, &lOperationResult, 1000); + if (lResult.IsOK()) + { + if (lOperationResult.IsOK()) + { + PvPayloadType lType; + + // + // We now have a valid buffer. This is where you would typically process the buffer. + // ----------------------------------------------------------------------------------------- + // ... + + lFrameRate->GetValue(lFrameRateVal); + lBandwidth->GetValue(lBandwidthVal); + + // If the buffer contains an image, display width and height. + uint32_t lWidth = 0, lHeight = 0; + lType = lBuffer->GetPayloadType(); + + if (lType == PvPayloadTypeImage) + { + // Get image specific buffer interface. + PvImage *lImage = lBuffer->GetImage(); + + // Read width, height. + lWidth = lImage->GetWidth(); + lHeight = lImage->GetHeight(); + std::cout << " W: " << std::dec << lWidth << " H: " << lHeight; + } + else + { + std::cout << " (buffer does not contain image)"; + } + std::cout << " " << lFrameRateVal << " FPS " << ( lBandwidthVal / 1000000.0 ) << " Mb/s \r"; + } + else + { + std::cout << lOperationResult.GetCodeString().GetAscii() << "\r"; + } + + // Re-queue the buffer in the stream object + lStream->QueueBuffer(lBuffer); + } + else + { + // Retrieve buffer failure + std::cout << lResult.GetCodeString().GetAscii() << "\r"; + } + } + + // Tell the device to stop sending images. + std::cout << "Sending AcquisitionStop command to the device" << std::endl; + lStop->Execute(); + + // Disable streaming on the device + std::cout << "Disable streaming on the controller." << std::endl; + lDevice->StreamDisable(); + + // Abort all buffers from the stream and dequeue + std::cout << "Aborting buffers still in stream" << std::endl; + lStream->AbortQueuedBuffers(); + while (lStream->GetQueuedBufferCount() > 0) + { + PvBuffer *lBuffer = NULL; + PvResult lOperationResult; + + lStream->RetrieveBuffer(&lBuffer, &lOperationResult); + } + + FreeStreamBuffers(); +} + +void StreamManager::FreeStreamBuffers() +{ + // Go through the buffer list + BufferList::iterator lIt = lBufferList.begin(); + while (lIt != lBufferList.end()) + { + delete *lIt; + lIt++; + } + + // Clear the buffer list + lBufferList.clear(); +} + +void StreamManager::Disconnect() +{ + if (lStream != NULL) + { + lStream->Close(); + PvStream::Free( lStream ); + } + if (lDevice != NULL) + { + lDevice->Disconnect(); + PvDevice::Free(lDevice); + } +} \ No newline at end of file diff --git a/StreamManager.hpp b/StreamManager.hpp new file mode 100644 index 0000000..d521f38 --- /dev/null +++ b/StreamManager.hpp @@ -0,0 +1,29 @@ +#include + +#include +#include +#include + +#define BUFFER_COUNT (32) +typedef std::list BufferList; + +class StreamManager +{ + +public: + + PvResult FindDevice(PvString *aConnectionID); + PvResult ConnectToDevice(const PvString &aConnectionID); + PvResult OpenStream(const PvString &aConnectionID); + void AcquireImages(); + void Disconnect(); + +private: + + PvDevice *lDevice = NULL; + PvStream *lStream = NULL; + BufferList lBufferList; + + void CreateStreamBuffers(); + void FreeStreamBuffers(); +}; \ No newline at end of file