Currently job artifacts in CI/CD pipelines on LRZ GitLab never expire. Starting from Wed 26.1.2022 the default expiration time will be 30 days (GitLab default). Currently existing artifacts in already completed jobs will not be affected by the change. The latest artifacts for all jobs in the latest successful pipelines will be kept. More information: https://gitlab.lrz.de/help/user/admin_area/settings/continuous_integration.html#default-artifacts-expiration

Commit 7080e882 authored by CAMP C++ Builder's avatar CAMP C++ Builder
Browse files

added support for multiple device names

parent 49d18265
......@@ -24,12 +24,8 @@
#include "streamingoigtldemo.h"
#include "tgt/event/keyevent.h"
#include "core/datastructures/imagedata.h"
#include "core/classification/geometry1dtransferfunction.h"
#include "core/classification/tfgeometry1d.h"
namespace campvis {
StreamingOIGTLDemo::StreamingOIGTLDemo(DataContainer* dc)
......@@ -51,7 +47,7 @@ namespace campvis {
_renderTargetID.setValue("combine");
_igtlClient.p_address.setValue("127.0.0.1");
_igtlClient.p_targetImageID.setValue("combine");
_igtlClient.p_targetImagePrefix.setValue("combine");
_canvasSize.s_changed.connect<StreamingOIGTLDemo>(this, &StreamingOIGTLDemo::onRenderTargetSizeChanged);
}
......
......@@ -24,8 +24,8 @@
#include "openigtlinkclient.h"
#include "transformdata.h"
#include "positiondata.h"
#include "../datastructures/transformdata.h"
#include "../datastructures/positiondata.h"
#include <igtlTransformMessage.h>
#include <igtlPositionMessage.h>
......@@ -44,17 +44,14 @@ namespace campvis {
, p_deviceName("ServerDeviceName", "Device Name (empty to accept all)")
, p_connect("Connect", "Connect to Server")
, p_receiveImages("ReceiveImages", "Receive IMAGE Messages", false)
, p_targetImageID("targetImageName", "Target Image ID", "OpenIGTLinkClient.output", DataNameProperty::WRITE)
, p_targetImagePrefix("targetImageName", "Target Image Prefix", "IGTL.image.")
, p_receiveTransforms("ReceiveTransforms", "Receive TRANSFORM Messages", true)
, p_targetTransformID("targetTransformName", "Target Transform ID", "OpenIGTLinkClient.transform", DataNameProperty::WRITE)
, p_targetTransformPrefix("targetTransformPrefix", "Target Transform Prefix", "IGTL.transform.")
, p_imageOffset("ImageOffset", "Image Offset in mm", tgt::vec3(0.f), tgt::vec3(-10000.f), tgt::vec3(10000.f), tgt::vec3(0.1f))
, p_voxelSize("VoxelSize", "Voxel Size in mm", tgt::vec3(1.f), tgt::vec3(-100.f), tgt::vec3(100.f), tgt::vec3(0.1f))
, p_receivePositions("ReceivePositions", "Receive POSITION Messages", true)
, p_targetPositionID("targetPositionsID", "Target Position ID", "OpenIGTLinkClient.position", DataNameProperty::WRITE)
, p_targetPositionPrefix("targetPositionsPrefix", "Target Position Prefix", "IGTL.position.")
{
_lastReceivedTransform = 0;
_lastReceivedImageMessage = 0;
addProperty(p_address, VALID);
addProperty(p_port, VALID);
addProperty(p_deviceName, VALID);
......@@ -63,12 +60,12 @@ namespace campvis {
addProperty(p_receiveTransforms, INVALID_RESULT | INVALID_PROPERTIES);
addProperty(p_receiveImages, INVALID_RESULT | INVALID_PROPERTIES);
addProperty(p_targetTransformID, VALID);
addProperty(p_targetImageID, VALID);
addProperty(p_targetTransformPrefix, VALID);
addProperty(p_targetImagePrefix, VALID);
addProperty(p_imageOffset, VALID);
addProperty(p_voxelSize, VALID);
addProperty(p_receivePositions, INVALID_RESULT | INVALID_PROPERTIES);
addProperty(p_targetPositionID, VALID);
addProperty(p_targetPositionPrefix, VALID);
}
OpenIGTLinkClient::~OpenIGTLinkClient() {
......@@ -76,7 +73,7 @@ namespace campvis {
}
void OpenIGTLinkClient::init() {
p_connect.s_clicked.connect(this, &OpenIGTLinkClient::onBtnConnectClicked);
p_connect.s_clicked.connect(this, &OpenIGTLinkClient::connectToServer);
}
void OpenIGTLinkClient::deinit() {
......@@ -88,25 +85,24 @@ namespace campvis {
if(p_receiveTransforms.getValue())
{
tgt::mat4 * newTransform = _lastReceivedTransform.fetch_and_store(nullptr);
if(newTransform) {
TransformData * td = new TransformData(*newTransform);
_transformMutex.lock();
for(auto it = _receivedTransforms.begin(), end = _receivedTransforms.end(); it != end; ++it) {
TransformData * td = new TransformData(it->second);
data.addData(p_targetTransformID.getValue(), td);
delete newTransform; //was allocated in the receiver thread - not needed anymore
data.addData(p_targetTransformPrefix.getValue() + it->first, td);
LDEBUG("Transform data put into container. ");
}
_receivedTransforms.clear();
_transformMutex.unlock();
}
if(p_receiveImages.getValue())
{
_lastReceivedImageMessageMutex.lock();
igtl::ImageMessage::Pointer imageMessage = _lastReceivedImageMessage;
_lastReceivedImageMessageMutex.unlock();
if(imageMessage)
_imageMutex.lock();
for(auto it = _receivedImages.begin(), end = _receivedImages.end(); it != end; ++it)
{
igtl::ImageMessage::Pointer imageMessage = it->second;
WeaklyTypedPointer wtp;
wtp._pointer = new uint8_t[imageMessage->GetImageSize()];
LDEBUG("Image has " << imageMessage->GetNumComponents() << " components and is of size " << imageMessage->GetImageSize());
......@@ -135,40 +131,47 @@ namespace campvis {
tgt::vec3 imageOffset(0.f);
tgt::vec3 voxelSize(1.f);
tgt::ivec3 size_i(1);
imageMessage->GetSpacing(voxelSize.elem);
imageMessage->GetDimensions(size_i.elem);
tgt::svec3 size(size_i);
tgt::svec3 size(size_i);
imageMessage->GetOrigin(imageOffset.elem);
size_t dimensionality = (size_i[2] == 1) ? ((size_i[1] == 1) ? 1 : 2) : 3;
ImageData* image = new ImageData(dimensionality, size, wtp._numChannels);
ImageRepresentationLocal::create(image, wtp);
image->setMappingInformation(ImageMappingInformation(size, p_imageOffset.getValue(), voxelSize * p_voxelSize.getValue()));
data.addData(p_targetImageID.getValue(), image);
data.addData(p_targetImagePrefix.getValue() + it->first, image);
}
_receivedImages.clear();
_imageMutex.unlock();
}
if(p_receivePositions.getValue())
{
_lastReceivedPositionMutex.lock();
PositionData * pd = new PositionData(_lastReceivedPosition, _lastReceivedQuaternion);
_lastReceivedPositionMutex.unlock();
data.addData(p_targetPositionID.getValue(), pd);
_positionMutex.lock();
for(auto it = _receivedPositions.begin(), end = _receivedPositions.end(); it != end; ++it)
{
PositionData * pd = new PositionData(it->second._position, it->second._quaternion);
data.addData(p_targetPositionPrefix.getValue() + it->first, pd);
}
_receivedPositions.clear();
_positionMutex.unlock();
}
validate(INVALID_RESULT);
}
void OpenIGTLinkClient::updateProperties(DataContainer& dataContainer) {
p_targetImageID.setVisible(p_receiveImages.getValue());
p_targetImagePrefix.setVisible(p_receiveImages.getValue());
p_imageOffset.setVisible(p_receiveImages.getValue());
p_voxelSize.setVisible(p_receiveImages.getValue());
p_targetTransformID.setVisible(p_receiveImages.getValue() || p_receiveTransforms.getValue());
p_targetTransformPrefix.setVisible(p_receiveImages.getValue() || p_receiveTransforms.getValue());
}
void OpenIGTLinkClient::onBtnConnectClicked() {
void OpenIGTLinkClient::connectToServer() {
if(_socket && _socket->GetConnected()) {
LWARNING("Already connected!");
......@@ -181,17 +184,24 @@ namespace campvis {
if (r != 0)
{
LERROR("Cannot connect to the server " << p_address.getValue());
LERROR("Cannot connect to the server " << p_address.getValue() << ":" << p_port.getValue());
_socket = nullptr;
return;
}
LINFO("Connected to server!");
LINFO("Connected to server " << p_address.getValue() << ":" << p_port.getValue());
start(); //start receiving data in a new thread
validate(INVALID_RESULT);
}
void OpenIGTLinkClient::disconnect() {
stop();
_socket = nullptr;
LINFO("Disconnected.");
}
int OpenIGTLinkClient::ReceiveTransform(igtl::Socket * socket, igtl::MessageHeader::Pointer& header)
{
LDEBUG("Receiving TRANSFORM data type.");
......@@ -211,14 +221,15 @@ namespace campvis {
if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK
{
tgt::mat4 * mtx = new tgt::mat4;
// Retrieve the transform data (this cast is a bit dubious but should be ok judging from the class internals)
transMsg->GetMatrix(*reinterpret_cast<igtl::Matrix4x4*>(mtx->elem));
igtl::PrintMatrix(*reinterpret_cast<igtl::Matrix4x4*>(mtx->elem));
tgt::mat4 mtx;
// Retrieve the transform data (this cast is a bit dubious but should be ok judging from the respective class internals)
transMsg->GetMatrix(*reinterpret_cast<igtl::Matrix4x4*>(mtx.elem));
igtl::PrintMatrix(*reinterpret_cast<igtl::Matrix4x4*>(mtx.elem));
std::cerr << std::endl;
tgt::mat4 * toDelete = _lastReceivedTransform.fetch_and_store(mtx);
if(toDelete) delete toDelete;
_transformMutex.lock();
_receivedTransforms[transMsg->GetDeviceName()] = mtx;
_transformMutex.unlock();
invalidate(INVALID_RESULT);
return 1;
......@@ -246,14 +257,19 @@ namespace campvis {
if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK
{
_lastReceivedPositionMutex.lock();
positionMsg->GetPosition(_lastReceivedPosition.elem);
positionMsg->GetQuaternion(_lastReceivedQuaternion.elem);
_lastReceivedPositionMutex.unlock();
PositionMessageData pmd;
positionMsg->GetPosition(pmd._position.elem);
positionMsg->GetQuaternion(pmd._quaternion.elem);
std::cerr << "position = (" << _lastReceivedPosition[0] << ", " << _lastReceivedPosition[1] << ", " << _lastReceivedPosition[2] << ")" << std::endl;
std::cerr << "quaternion = (" << _lastReceivedQuaternion[0] << ", " << _lastReceivedQuaternion[1] << ", "
<< _lastReceivedQuaternion[2] << ", " << _lastReceivedQuaternion[3] << ")" << std::endl << std::endl;
_positionMutex.lock();
_receivedPositions[positionMsg->GetDeviceName()] = pmd;
_positionMutex.unlock();
std::cerr << "position = (" << pmd._position[0] << ", " << pmd._position[1] << ", " << pmd._position[2] << ")" << std::endl;
std::cerr << "quaternion = (" << pmd._quaternion[0] << ", " << pmd._quaternion[1] << ", "
<< pmd._quaternion[2] << ", " << pmd._quaternion[3] << ")" << std::endl << std::endl;
invalidate(INVALID_RESULT);
return 1;
......@@ -282,9 +298,9 @@ namespace campvis {
if (c & igtl::MessageHeader::UNPACK_BODY) // if CRC check is OK
{
// put the message pointer into our locked buffer
_lastReceivedImageMessageMutex.lock();
_lastReceivedImageMessage = imgMsg;
_lastReceivedImageMessageMutex.unlock();
_imageMutex.lock();
_receivedImages[imgMsg->GetDeviceName()] = imgMsg;
_imageMutex.unlock();
// Retrieve the image data
int size[3]; // image dimension
......@@ -298,13 +314,13 @@ namespace campvis {
imgMsg->GetSpacing(spacing);
imgMsg->GetSubVolume(svsize, svoffset);
tgt::mat4 * mtx = new tgt::mat4;
tgt::mat4 mtx;
// Retrieve the transform data (this cast is a bit dubious but should be ok judging from the class internals)
imgMsg->GetMatrix(*reinterpret_cast<igtl::Matrix4x4*>(mtx->elem));
std::cerr << std::endl;
tgt::mat4 * toDelete = _lastReceivedTransform.fetch_and_store(mtx);
if(toDelete) delete toDelete;
imgMsg->GetMatrix(*reinterpret_cast<igtl::Matrix4x4*>(mtx.elem));
_transformMutex.lock();
_receivedTransforms[imgMsg->GetDeviceName()] = mtx;
_transformMutex.unlock();
std::cerr << "Device Name : " << imgMsg->GetDeviceName() << std::endl;
std::cerr << "Scalar Type : " << scalarType << std::endl;
......@@ -317,7 +333,8 @@ namespace campvis {
std::cerr << "Sub-Volume offset : ("
<< svoffset[0] << ", " << svoffset[1] << ", " << svoffset[2] << ")" << std::endl << std::endl;
igtl::PrintMatrix(*reinterpret_cast<igtl::Matrix4x4*>(mtx->elem));
igtl::PrintMatrix(*reinterpret_cast<igtl::Matrix4x4*>(mtx.elem));
std::cout << std::endl;
invalidate(INVALID_RESULT);
return 1;
......@@ -335,7 +352,7 @@ namespace campvis {
headerMsg = igtl::MessageHeader::New();
ts = igtl::TimeStamp::New();
while (!_stopExecution)
while (!_stopExecution && _socket)
{
// Initialize receive buffer
headerMsg->InitPack();
......@@ -345,6 +362,7 @@ namespace campvis {
if (r == 0)
{
_socket->CloseSocket();
_socket = nullptr;
LINFO("Socket Connection closed.");
break;
}
......@@ -432,6 +450,8 @@ namespace campvis {
_socket->Skip(headerMsg->GetBodySizeToRead(), 0);
}
}
_socket->CloseSocket();
if(_socket)
_socket->CloseSocket();
_socket = nullptr;
}
}
\ No newline at end of file
......@@ -26,6 +26,7 @@
#define OPENIGTLINKCLIENT_H__
#include <string>
#include <map>
#include <igtlOSUtil.h>
#include <igtlClientSocket.h>
......@@ -48,8 +49,10 @@
namespace campvis {
/**
* Experimental demo implementation how to receive MHD files via CAMPCom, convert it to
* CAMPVis ImageData and store it into the DataContainer.
* OpenIGTLink Client processor. Connects to a specified server and receives all OpenIGTLink messages.
* Processes the messages according to the currently set properties p_receiveTransform, p_receivePositions
* and p_receiveImage and puts them into the received data into the respective data containers.
* This Class contains modified code from the OpenIGTLink ReceiveClient example.
*/
class OpenIGTLinkClient : public AbstractProcessor, public Runnable {
public:
......@@ -84,19 +87,19 @@ namespace campvis {
BoolProperty p_receiveImages; ///< toggle receiving IMAGE messages
DataNameProperty p_targetImageID; ///< image ID for read image
StringProperty p_targetImagePrefix; ///< image ID prefix for read image
BoolProperty p_receiveTransforms; ///< toggle receiving TRANSFORM messages
DataNameProperty p_targetTransformID; ///< data ID for read transformation
StringProperty p_targetTransformPrefix; ///< data ID prefix for read transformation
Vec3Property p_imageOffset; ///< Image Offset in mm
Vec3Property p_voxelSize; ///< Voxel Size in mm
BoolProperty p_receivePositions; ///< toggle receiving IMAGE messages
DataNameProperty p_targetPositionID; ///< image ID for read image
StringProperty p_targetPositionPrefix; ///< image ID prefix for read images
/**
* Updates the data container with the latest received frame/transformation
* Updates the data container with the latest received transformation/position/image data
* \param dataContainer DataContainer to work on
*/
virtual void updateResult(DataContainer& dataContainer);
......@@ -104,30 +107,44 @@ namespace campvis {
/// \see AbstractProcessor::updateProperties
virtual void updateProperties(DataContainer& dataContainer);
/// Callback slot for connect button
void onBtnConnectClicked();
/// Callback slot for connect button. can also be called from outside.
void connectToServer();
/// Callback slot for disconnect button. can also be called from outside.
void disconnect();
static const std::string loggerCat_;
protected:
int OpenIGTLinkClient::ReceiveTransform(igtl::Socket * socket, igtl::MessageHeader::Pointer& header);
int OpenIGTLinkClient::ReceivePosition(igtl::Socket * socket, igtl::MessageHeader::Pointer& header);
int ReceiveImage(igtl::Socket * socket, igtl::MessageHeader::Pointer& header);
/// Stores received data from a POSITION Message
struct PositionMessageData {
tgt::vec3 _position;
tgt::vec4 _quaternion;
};
/// Implements the \a Runnable::run() method to execute a new thread. The new thread will
/// go into a receive loop to receive the OpenIGTLink messages asynchronously
virtual void run();
/// Receive a TRANSFORM message from the OpenIGTLink socket and put the data into the local buffers
int ReceiveTransform(igtl::Socket * socket, igtl::MessageHeader::Pointer& header);
/// Receive a POSITION message from the OpenIGTLink socket and put the data into the local buffers
int ReceivePosition(igtl::Socket * socket, igtl::MessageHeader::Pointer& header);
/// Receive a IMAGE message from the OpenIGTLink socket and put into the local buffers
int ReceiveImage(igtl::Socket * socket, igtl::MessageHeader::Pointer& header);
//connection
igtl::ClientSocket::Pointer _socket;
//data
tbb::atomic<tgt::mat4 *> _lastReceivedTransform; ///< the last transform that has been received by the igtl worker thread
igtl::ImageMessage::Pointer _lastReceivedImageMessage; ///< last received igtl image message
tbb::mutex _lastReceivedImageMessageMutex; ///< mutex to control access to the _lastReceivedImageMessage pointer
std::map<std::string, tgt::mat4> _receivedTransforms; ///< the transforms that has been received by the igtl worker thread, mapped by device name
std::map<std::string, igtl::ImageMessage::Pointer> _receivedImages; ///< the image messages received by the igtl worker thread, mapped by device name
std::map<std::string, PositionMessageData> _receivedPositions; ///< position message data received by the igtl worker thread, mapped by device name
tbb::mutex _lastReceivedPositionMutex; ///< mutex to control access to _lastReceivedPosition and _lastReceivedQuaternion
tgt::vec3 _lastReceivedPosition; ///< last received position in the position message
tgt::vec4 _lastReceivedQuaternion; ///< last received quaternion/orientation in the position message
tbb::mutex _transformMutex; ///< mutex to control access to the _receivedTransforms pointer
tbb::mutex _imageMutex; ///< mutex to control access to the _receivedImages pointer
tbb::mutex _positionMutex; ///< mutex to control access to _receivedPositions
static const std::string loggerCat_;
};
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment