30 #include "WIGTLinkRemote.h"
31 #include "core/common/WIOTools.h"
32 #include "core/common/WLogger.h"
33 #include "core/dataHandler/WDataSet.h"
34 #include "core/dataHandler/WDataSetScalar.h"
35 #include "core/dataHandler/WGridRegular3D.h"
36 #include "core/dataHandler/WValueSet.h"
37 #include "igtlImageMessage.h"
38 #include "igtlImageMetaMessage.h"
39 #include "igtlOSUtil.h"
40 #include "igtlServerSocket.h"
41 #include "igtlTransformMessage.h"
43 WIGTLinkRemote::WIGTLinkRemote()
44 : checkCRC( false ), port( 0 )
50 WIGTLinkRemote::~WIGTLinkRemote()
69 std::cout <<
"setting up connection to: \"" << hostname <<
":" <<
port <<
"\"" << std::endl;
71 socket = igtl::ClientSocket::New();
72 int r =
socket->ConnectToServer( hostname.c_str(),
port );
75 throw WException(
"Cannot connect to server" );
77 std::cout <<
"connection established" << std::endl;
88 igtl::ServerSocket::Pointer serverSocket;
89 serverSocket = igtl::ServerSocket::New();
90 serverSocket->CreateServer(
port );
95 socket = serverSocket->WaitForConnection( 2000 );
105 igtl::MessageHeader::Pointer headerMsg;
106 headerMsg = igtl::MessageHeader::New();
108 headerMsg->InitPack();
115 WAssert(
socket.IsNotNull(),
"Something failed when setting up the socket" );
121 std::cout <<
"Waiting for data." << std::endl;
122 int r =
socket->Receive( headerMsg->GetPackPointer(), headerMsg->GetPackSize() );
128 std::cout <<
"got something." << std::endl;
130 if( r != headerMsg->GetPackSize() )
136 headerMsg->Unpack(
checkCRC ? 1:0 );
139 if( strcmp( headerMsg->GetDeviceType(),
"TRANSFORM" ) == 0 )
144 else if( strcmp( headerMsg->GetDeviceType(),
"IMAGE" ) == 0 )
146 std::cout <<
"got an image!!!" << std::endl;
153 else if( strcmp( headerMsg->GetDeviceType(),
"POSITION" ) == 0 )
156 socket->Skip( headerMsg->GetBodySizeToRead(), 0 );
158 else if( strcmp( headerMsg->GetDeviceType(),
"STATUS" ) == 0 )
161 socket->Skip( headerMsg->GetBodySizeToRead(), 0 );
166 socket->Skip( headerMsg->GetBodySizeToRead(), 0 );
169 catch(
const std::exception &e )
185 socket = igtl::ClientSocket::Pointer();
197 igtl::TransformMessage::Pointer transMsg;
198 transMsg = igtl::TransformMessage::New();
199 transMsg->SetMessageHeader( headerMsg );
200 transMsg->AllocatePack();
202 socket->Receive( transMsg->GetPackBodyPointer(), transMsg->GetPackBodySize() );
205 int c = transMsg->Unpack(
checkCRC ? 1:0 );
206 if( c & igtl::MessageHeader::UNPACK_BODY )
209 igtl::Matrix4x4 matrix;
210 transMsg->GetMatrix( matrix );
213 igtl::PrintMatrix( matrix );
219 igtl::ImageMessage::Pointer imgMsg;
220 imgMsg = igtl::ImageMessage::New();
221 imgMsg->SetMessageHeader( headerMsg );
222 imgMsg->AllocatePack();
225 socket->Receive( imgMsg->GetPackBodyPointer(), imgMsg->GetPackBodySize() );
228 int c = imgMsg->Unpack(
checkCRC ? 1:0 );
230 if( c & igtl::MessageHeader::UNPACK_BODY )
238 imgMsg->GetDimensions( size );
239 imgMsg->GetSpacing( spacing );
240 imgMsg->GetSubVolume( svsize, svoffset );
241 imgMsg->GetMatrix( mat );
244 for(
int i = 0; i < 4; ++i )
246 for(
int j = 0; j < 4; ++j )
248 owmat( i, j ) = mat[ i ][ j ];
253 std::shared_ptr< WValueSetBase > valueSet =
createValueSet( imgMsg );
265 std::cerr <<
"decoding image failed" << std::endl;
267 return WDataSetScalarSPtr ();
278 igtl::TransformMessage::Pointer transMsg;
279 transMsg = igtl::TransformMessage::New();
280 transMsg->SetDeviceName( name.c_str() );
281 igtl::Matrix4x4 igtlMatrix;
282 for(
int i = 0; i < 4; ++i )
284 for(
int j = 0; j < 4; ++j )
286 igtlMatrix[ i ][ j ] = matrix( i, j );
289 transMsg->SetMatrix( igtlMatrix );
293 socket->Send( transMsg->GetPackPointer(), transMsg->GetPackSize() );
299 int convertTypeOWtoIGTL(
int type )
303 case igtl::ImageMessage::TYPE_INT8:
305 case igtl::ImageMessage::TYPE_UINT8:
307 case igtl::ImageMessage::TYPE_INT16:
309 case igtl::ImageMessage::TYPE_UINT16:
311 case igtl::ImageMessage::TYPE_INT32:
313 case igtl::ImageMessage::TYPE_UINT32:
324 igtl::ImageMetaMessage::Pointer imgMetaMsg;
325 imgMetaMsg = igtl::ImageMetaMessage::New();
327 imgMetaMsg->SetDeviceName(
"OpenWalnut" );
330 for(
size_t i = 0; i < dataSets.size(); ++i )
332 igtl::ImageMetaElement::Pointer imgMeta;
333 imgMeta = igtl::ImageMetaElement::New();
334 imgMeta->SetName( dataSets[ i ]->getFilename().c_str() );
335 imgMeta->SetDeviceName( dataSets[ i ]->getFilename().c_str() );
336 imgMeta->SetModality(
"UNKNOWN_MODALITY" );
337 imgMeta->SetPatientName( dataSets[ i ]->getFilename().c_str() );
338 imgMeta->SetPatientID(
"PATIENT_ID_0" );
340 igtl::TimeStamp::Pointer ts0;
341 ts0 = igtl::TimeStamp::New();
342 ts0->SetTime( 123456.78 );
344 imgMeta->SetTimeStamp( ts0 );
345 std::shared_ptr < WGridRegular3D > g3dr( std::dynamic_pointer_cast < WGridRegular3D > ( dataSets[ i ]->getGrid() ) );
346 imgMeta->SetSize( g3dr->getNbCoordsX(), g3dr->getNbCoordsY(), g3dr->getNbCoordsZ() );
347 imgMeta->SetScalarType( convertTypeOWtoIGTL( dataSets[ i ]->getValueSet()->getDataType() ) );
348 imgMetaMsg->AddImageMetaElement( imgMeta );
352 socket->Send( imgMetaMsg->GetPackPointer(), imgMetaMsg->GetPackSize() );
358 size_t getRawSizeT( std::shared_ptr < WValueSetBase > valueSet )
361 std::shared_ptr < WValueSet < type > > v = std::dynamic_pointer_cast < WValueSet < type > >( valueSet );
362 WAssert( v,
"Type cast failed" );
363 return valueSet->rawSize() *
sizeof( type );
367 const void* getRawPtrT( std::shared_ptr < WValueSetBase > valueSet )
370 std::shared_ptr < WValueSet < type > > v;
371 v = std::dynamic_pointer_cast < WValueSet < type > >( valueSet );
372 WAssert( v,
"Type cast failed" );
373 const void* ptr = v->rawData();
374 WAssert( ptr != 0,
"Trying to query raw data, got null pointer" );
378 size_t getRawSize( std::shared_ptr < WValueSetBase > valueSet )
380 int type = valueSet->getDataType();
381 #define CASE( A ) case A: return getRawSizeT < A > ( valueSet );
384 CASE( W_DT_UNSIGNED_CHAR );
386 CASE( W_DT_SIGNED_SHORT );
387 CASE( W_DT_SIGNED_INT );
394 CASE( W_DT_FLOAT128 );
396 throw WException(
"Not implemented for given data type" );
401 const void* getRawPtr( std::shared_ptr < WValueSetBase > valueSet )
403 int type = valueSet->getDataType();
404 #define CASE( A ) case A: return getRawPtrT < A > ( valueSet );
407 CASE( W_DT_UNSIGNED_CHAR );
409 CASE( W_DT_SIGNED_SHORT );
410 CASE( W_DT_SIGNED_INT );
417 CASE( W_DT_FLOAT128 );
419 throw WException(
"Not implemented for given data type" );
427 std::shared_ptr< WValueSetBase > valueSet = dataSetScalar->getValueSet();
431 switch( valueSet->getDataType() )
434 scalarType = igtl::ImageMessage::TYPE_FLOAT32;
437 scalarType = igtl::ImageMessage::TYPE_FLOAT64;
440 scalarType = igtl::ImageMessage::TYPE_UINT16;
443 scalarType = igtl::ImageMessage::TYPE_UINT32;
445 case W_DT_UNSIGNED_CHAR:
446 scalarType = igtl::ImageMessage::TYPE_UINT8;
449 scalarType = igtl::ImageMessage::TYPE_INT8;
453 throw WException(
"Unsupported scalar type: not supported by igtl?" );
455 case W_DT_SIGNED_INT:
456 scalarType = igtl::ImageMessage::TYPE_INT32;
458 case W_DT_SIGNED_SHORT:
459 scalarType = igtl::ImageMessage::TYPE_INT16;
463 throw WException(
"Unsupported scalar type" );
470 case W_DT_COMPLEX128:
471 case W_DT_COMPLEX256:
472 throw WException(
"Complex types are not supported, yet" );
475 throw WException(
"W_DT_NONE should never occur as a type." );
478 throw WException(
"W_DT_ALL should never occur as a type." );
485 std::shared_ptr < WGridRegular3D > g3dr( std::dynamic_pointer_cast < WGridRegular3D > ( dataSetScalar->getGrid() ) );
486 size[ 0 ] = g3dr->getNbCoordsX();
487 size[ 1 ] = g3dr->getNbCoordsY();
488 size[ 2 ] = g3dr->getNbCoordsZ();
490 int svsize[ 3 ] = { size[ 0 ], size[ 1 ], size[ 2 ]};
491 int svoffset[] = { 0, 0, 0 };
493 igtl::ImageMessage::Pointer imgMsg = igtl::ImageMessage::New();
494 imgMsg->SetDimensions( size );
495 imgMsg->SetSpacing( g3dr->getOffsetX(), g3dr->getOffsetY(), g3dr->getOffsetZ() );
496 imgMsg->SetDeviceName(
"OpenWalnut" );
497 imgMsg->SetSubVolume( svsize, svoffset );
498 imgMsg->SetScalarType( scalarType );
499 imgMsg->AllocateScalars();
501 size_t rawsize = Ugly::getRawSize( valueSet );
502 std::cout <<
"Transfering " << rawsize <<
" = " << imgMsg->GetImageSize() <<
" bytes of data." << std::endl;
503 memcpy( imgMsg->GetScalarPointer(), Ugly::getRawPtr( valueSet ), rawsize );
505 igtl::Matrix4x4 matrix;
506 igtl::IdentityMatrix( matrix );
507 imgMsg->SetMatrix( matrix );
510 socket->Send( imgMsg->GetPackPointer(), imgMsg->GetPackSize() );
516 std::shared_ptr<WValueSetBase> valueSet;
518 imgMsg->GetDimensions( size );
519 size_t sz = size[ 0 ] * size[ 1 ] * size[ 2 ];
520 #define CASE( igtltype, ctype, owtype )\
523 std::shared_ptr < std::vector < ctype > > values( new std::vector < ctype >( sz ) );\
524 memcpy( ( void* )&( ( *values )[ 0 ] ), imgMsg->GetScalarPointer(), sizeof( ctype ) * sz );\
525 valueSet.reset( new WValueSet < ctype >( 0, 1, values, owtype ) );\
529 switch( imgMsg->GetScalarType() )
531 CASE( igtl::ImageMessage::TYPE_INT8, int8_t, W_DT_INT8 );
532 CASE( igtl::ImageMessage::TYPE_UINT8, uint8_t, W_DT_UINT8 );
533 CASE( igtl::ImageMessage::TYPE_INT16, int16_t, W_DT_INT16 );
534 CASE( igtl::ImageMessage::TYPE_UINT16, uint16_t, W_DT_UINT16 );
535 CASE( igtl::ImageMessage::TYPE_INT32, int32_t, W_DT_SIGNED_INT );
536 CASE( igtl::ImageMessage::TYPE_UINT32, uint32_t, W_DT_UINT32 );
Class to encapsulate boost::condition_variable_any.
This data set type contains scalars as values.
A grid that has parallelepiped cells which all have the same proportion.
std::shared_ptr< WGridRegular3DTemplate > SPtr
Convenience typedef for a std::shared_ptr< WGridRegular3DTemplate >.
void createSocketAndWaitForConnection(uint32_t port)
Use this as a server that waits for client connections.
igtl::ClientSocket::Pointer socket
Points to the socket used by this connection.
void receiveTransform(igtl::MessageHeader::Pointer headerMsg)
Receive a transform.
std::shared_ptr< WCondition > receiversCondition
condition to notify receivers that new data is waiting
bool checkCRC
true if we check CRC sums in incoming packets
void sendTransform(const std::string &name, const WMatrix< double > &matrix)
send a matrix as an igtl transform
std::shared_ptr< WValueSetBase > createValueSet(const igtl::ImageMessage::Pointer &imgMsg)
Internal helper to create a value set from a message.
void readDataLoop()
main loop for reading
std::shared_ptr< WCondition > statusCondition
condition to notify a status change
boost::mutex receiversMutex
mutex has to be locked during access to receiveQueue
uint32_t port
the port for listening connections
WDataSetScalarSPtr receiveImage(igtl::MessageHeader::Pointer headerMsg)
Receive an image.
void injectMessage()
TODO: inject a message in the send queue.
void createSocketAndConnect(std::string server, uint32_t port)
Use this as a client that connects to a remote server.
virtual void threadMain()
the main thread doing passive connections or receiving data
void sendImageMetaData(const std::vector< WDataSetScalarSPtr > &dataSets)
Send metadata of a list of data sets.
void sendImageData(WDataSetScalarSPtr dataSetScalar)
Send image data of a single data set.
void listenLoop()
setup listening socket and listen
std::queue< WDataSetScalarSPtr > receiveQueue
queue of received data sets that should be read by the module
WBoolFlag m_shutdownFlag
Condition getting fired whenever the thread should quit.
Convert a runtime type to a C++ type.