Commit 7080e882 authored by Jakob Weiss's avatar Jakob Weiss
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_;
};
}
......
Supports Markdown
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