VR-Forces Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
exampleCigiExtension

Table of Contents

Overview

This example creates an accessory that installs itself into DtCigiDriver objects and hooks into signals that are triggered when particular CIGI messages are received.

Expected Result

The following should be printed to the console window:

Received a CIGI Component Control Message
 -- Instance ID: 2
Received a CIGI Wave Control Message
 -- Wave ID: 1
 -- Wave Height: 5
Received a CIGI Message of an Unknown Type

If VR-Vantage is connected with CIGI Version 4.0, 4096 will also be printed.

Example details

The CIGI driver emits signals when a CIGI message is received. An accessory can be installed, that listens to particular CIGI messages and does some type of processing when they are received. Much of this example is like exampleAccessory, except the accessory listens to the session created signal from the DtCigiDriver.

void DtCigiAccessory::install(DtDriver* driver)
{
DtCigiDriver* cd = dynamic_cast<DtCigiDriver*>(driver);
if(cd)
{
mySessionCreatedConnection = cd->signal_sessionCreated.connect(
boost::bind(&DtCigiAccessory::slot_onSimCreated, this, boost::placeholders::_1));
}
}

When the session is created, the accessory waits for the CIGI driver to be connected.

void DtCigiAccessory::slot_onSimCreated(DtCigiConnection* connection)
{
connection->signal_connected.connect(
boost::bind(&DtCigiAccessory::slot_onSimConnected, this, connection));
connection->signal_toBeDisconnected.connect(
boost::bind(&DtCigiAccessory::slot_onSimAboutToBeDisconnected, this, connection));
}

On connection, a DtCigiExtender object is created (much like the DtPrintVisualizer of exampleAccessory).

void DtCigiAccessory::slot_onSimConnected(DtCigiConnection* connection)
{
if(connection)
{
DtCigiExtender* vis = new DtCigiExtender(*connection);
// Register the CIGI extender instance with the sim connection
// This passes memory management responsibility to the connection
connection->registerInstance("DtCigiExtender", vis);
}
}

The DtCigiExtender class listens for component control, wave control, and custom CIGI messages, and prints out the contents of known messages. The constructor connects to the appropriate signals.

DtCigiExtender::DtCigiExtender( DtCigiConnection& connection )
: DtVirtualBaseClass()
, myConnection( connection )
{
myConnections += DtCigiSignalProcessor::instance( connection ).signal_componentControlReceived.connect(
boost::bind( &DtCigiExtender::slot_componentControlReceived, this, boost::placeholders::_1 ) );
myConnections += DtCigiSignalProcessor::instance( connection ).signal_waveControlReceived.connect(
boost::bind( &DtCigiExtender::slot_waveControlReceived, this, boost::placeholders::_1 ) );
myConnections += DtCigiSignalProcessor::instance( connection ).signal_unrecognizedPacketReceived.connect(
boost::bind( &DtCigiExtender::slot_customPacketReceived, this, boost::placeholders::_1 ) );
// You must register your packet with the CIGI incoming packet manager, to process
// unknown, non CIGI/MAK packet IDs. This can be done through the CIGI IG Session.
// Create a packet class similar to the DiGuy custom CIGI packets.
// For V3 and V4 observe the following numbering restrictions, per the standard:
// Cigi_uint16 minUserPacketID = myConnection.getCigiVersion().CigiMajorVersion < 4 ? 201 : 0x1000;
// Cigi_uint16 maxUserPacketID = myConnection.getCigiVersion().CigiMajorVersion < 4 ? 255 : 0xfffe;
// For example :
CustomV4Packet * myPacket = new CustomV4Packet();
myConnection.networkIO().session().RegisterUserPacket( myPacket, 0x1000, true, false );
}

The methods are called when the particular type of CIGI message is received.

void DtCigiExtender::slot_componentControlReceived( CigiBaseCompCtrl& msg )
{
if(myConnection.getCigiVersion().CigiMajorVersion == 3)
{
CigiCompCtrlV3_3 * compCtrlMsgV3 = static_cast<CigiCompCtrlV3_3*>(&msg);
std::cout << "Received a CIGI Component Control Message" << std::endl;
std::cout << " -- Instance ID: " << (int)compCtrlMsgV3->GetInstanceID() << std::endl;
}
else if(myConnection.getCigiVersion().CigiMajorVersion == 4)
{
CigiCompCtrlV4 * compCtrlMsgV4 = static_cast<CigiCompCtrlV4*>(&msg);
std::cout << "Received a CIGI Component Control Message" << std::endl;
std::cout << " -- Instance ID: " << (int)compCtrlMsgV4->GetInstanceID() << std::endl;
}
}

void DtCigiExtender::slot_waveControlReceived( CigiBaseWaveCtrl& msg )
{
if(myConnection.getCigiVersion().CigiMajorVersion == 3)
{
CigiWaveCtrlV3* waveCtrlMsgV3 = static_cast<CigiWaveCtrlV3*>(&msg);
std::cout << "Received a CIGI Wave Control Message" << std::endl;
std::cout << " -- Wave ID: " << (int)waveCtrlMsgV3->GetWaveID() << std::endl;
std::cout << " -- Wave Height: " << waveCtrlMsgV3->GetWaveHt() << std::endl;
}
else if(myConnection.getCigiVersion().CigiMajorVersion == 4)
{
CigiWaveCtrlV4* waveCtrlMsgV4 = static_cast<CigiWaveCtrlV4*>(&msg);
std::cout << "Received a CIGI Wave Control Message" << std::endl;
std::cout << " -- Wave ID: " << (int)waveCtrlMsgV4->GetWaveID() << std::endl;
std::cout << " -- Wave Height: " << waveCtrlMsgV4->GetWaveHt() << std::endl;
}
}

In the case of custom messages, the CigiBasePacket will need to be casted to a user-defined type so that the data can be extracted.

void DtCigiExtender::slot_customPacketReceived( CigiBasePacket& msg )
{
std::cout << "Received a CIGI Message of an Unknown Type" << std::endl;
if(myConnection.getCigiVersion().CigiMajorVersion == 4)
{
CustomV4Packet * customPacketTest = dynamic_cast<CustomV4Packet*>(&msg);
if(customPacketTest)
{
std::cout << customPacketTest->GetPacketID() << std::endl;
}
}
}

Building the Example

VR-Vantage includes pre-built versions of the example plug-in. To build it yourself, follow the instructions at Building VR-Vantage Examples, Applications, and Plug-ins.

Running the Example

This example is a plug-in. You can run it by running ./bin64/exampleCigiExtension_stealth.bat (on Windows) or ./bin64/exampleCigiExtension_stealth.sh (on Linux). For more information about running examples, please see Running Applications and Examples. Once VR-Stealth is started, open the Simulation Connections page and choose the CIGI Connections tab. Select a CIGI Version, a Driver Mode of Asynchronous, and set the IG Network Interface Address to 127.0.0.1 (the remaining options can be left as defaults). Press the 'Connect' button. Open a Cygwin or other window that can run a 3.x Python script. Change directory in this window to ./tools/CigiUtilities/pyCigi<3|4>. From here you can run pyCigiV<3|4>-NT-ExampleCigiExtensionTest.py. You should see the output indicated above in the console window. Alternatively, if you are familiar with the Host Emulator utility (./tools/CigiHostEmulator<3|4>) you can choose a Synchronous Driver Mode in the CIGI connections tab instead, and send Component Control and Wave Control messages from there (but you won't be able to send an unknown packet type).

Example Source Files


exampleCigiExtensionPlugin.cxx

/*********************************************************************
** Copyright (c) 2024 MAK Technologies, Inc.
** All rights reserved.
*********************************************************************/
#include <vrvCore/DtDe.h>
#include <boost/bind/bind.hpp>
using namespace makVrv;
static vrvSignalsLib::connection postInitializeConnection;
{
// We're done with the signal, so disconnect from it
postInitializeConnection.disconnect();
// Add the print accessory to the accessory manager. It will get the option
// to install itself into any DtDriver objects that are created.
}
void init(DtDe& de)
{
// Ensure that init only gets called once
// (not strictly necessary here, but this is good practice in general)
// We only want to create the accessory if we're running in master mode:
if (de.isInMasterMode())
{
// The accessory must be created after the DE's initialization is
// finished, to make sure all the objects it uses exist.
postInitializeConnection = de.signal_postInitialize.connect(boost::bind(
&loadAccessory, &de));
}
}
{
// Setup the plugin. Normally, the init function and functionality
// should be in its own library.
{
init(*de);
return true;
}
return false;
}

DtCigiAccessory.h

/*********************************************************************
** Copyright (c) 2023 MAK Technologies, Inc.
** All rights reserved.
*********************************************************************/
#pragma once
namespace makVrv
{
class DtCigiConnection;
class DtCigiAccessory : public DtBaseAccessory
{
public:
virtual ~DtCigiAccessory();
virtual void install(DtDriver* driver);
virtual void uninstall(DtDriver* baseConn);
virtual bool isCompatible(DtDriver* driver);
protected:
virtual void slot_onSimCreated(DtCigiConnection* connection);
virtual void slot_onSimConnected(DtCigiConnection* connection);
virtual void slot_onSimAboutToBeDisconnected(DtCigiConnection* connection);
protected:
vrvSignalsLib::connection mySessionCreatedConnection;
};
}

DtCigiExtender.h

/*********************************************************************
** Copyright (c) 2023 MAK Technologies, Inc.
** All rights reserved.
*********************************************************************/
#pragma once
class CigiBaseCompCtrl;
class CigiBaseWaveCtrl;
class CigiBasePacket;
namespace makVrv
{
class DtCigiExtender : public DtVirtualBaseClass
{
public:
DtCigiExtender(DtCigiConnection& connection);
virtual void slot_componentControlReceived(CigiBaseCompCtrl&);
virtual void slot_waveControlReceived( CigiBaseWaveCtrl&);
virtual void slot_customPacketReceived(CigiBasePacket&);
protected:
DtCigiConnection& myConnection;
DtSignalConnectionManager myConnections;
};
}

DtCigiAccessory.cxx

/*********************************************************************
** Copyright (c) 2024 MAK Technologies, Inc.
** All rights reserved.
*********************************************************************/
#include "DtCigiAccessory.h"
#include "DtCigiExtender.h"
#include <boost/bind/bind.hpp>
#include <iostream>
namespace makVrv
{
:DtBaseAccessory()
{
}
DtCigiAccessory::~DtCigiAccessory()
{
}
void DtCigiAccessory::install(DtDriver* driver)
{
DtCigiDriver* cd = dynamic_cast<DtCigiDriver*>(driver);
if(cd)
{
mySessionCreatedConnection = cd->signal_sessionCreated.connect(
boost::bind(&DtCigiAccessory::slot_onSimCreated, this, boost::placeholders::_1));
}
}
void DtCigiAccessory::uninstall(DtDriver* baseConn)
{
//std::cout << "Accessory unInstall" << std::endl;
DtCigiDriver* vld = dynamic_cast<DtCigiDriver*>(baseConn);
if(vld)
{
mySessionCreatedConnection.disconnect();
}
}
bool DtCigiAccessory::isCompatible(DtDriver* driver)
{
DtCigiDriver* dd = dynamic_cast<DtCigiDriver*>(driver);
if(dd)
{
return true;
}
return false;
}
void DtCigiAccessory::slot_onSimCreated(DtCigiConnection* connection)
{
connection->signal_connected.connect(
boost::bind(&DtCigiAccessory::slot_onSimConnected, this, connection));
connection->signal_toBeDisconnected.connect(
boost::bind(&DtCigiAccessory::slot_onSimAboutToBeDisconnected, this, connection));
}
void DtCigiAccessory::slot_onSimConnected(DtCigiConnection* connection)
{
if(connection)
{
DtCigiExtender* vis = new DtCigiExtender(*connection);
// Register the CIGI extender instance with the sim connection
// This passes memory management responsibility to the connection
connection->registerInstance("DtCigiExtender", vis);
}
}
void DtCigiAccessory::slot_onSimAboutToBeDisconnected(DtCigiConnection* sim)
{
if(sim)
{
// Remove the print visualizer instance from the sim connection
sim->registerInstance("DtCigiExtender", 0);
}
}
}

DtCigiExtender.cxx

/*********************************************************************
** Copyright (c) 2024 MAK Technologies, Inc.
** All rights reserved.
*********************************************************************/
#include "DtCigiExtender.h"
#include <CigiCompCtrlV3_3.h>
#include <CigiCompCtrlV4.h>
#include <CigiWaveCtrlV3.h>
#include <CigiWaveCtrlV4.h>
#include <CigiIGSession.h>
#include <CigiIncomingMsg.h>
#include <boost/bind/bind.hpp>
#include <iostream>
namespace makVrv
{
class CustomV4Packet : public CigiBasePacket
{
public:
CustomV4Packet() :
CigiBasePacket(),
packSize( 8 ),
packID( 0x1000 )
{
PacketID = packID;
PacketSize = packSize;
Version = 4;
MinorVersion = 0;
}
virtual int Pack( CigiBasePacket* Base, Cigi_uint8* Buff, void* Spec ) const
{
PackPointer CDta;
CDta.c = Buff;
// Packet ID (2 bytes)
*CDta.s++ = packID;
// Size (2 bytes)
*CDta.s++ = packSize;
// Entity ID (4 bytes)
*CDta.l++ = 13375;
return packSize;
}
virtual int Unpack( Cigi_uint8 * Buff, bool Swap, void *Spec )
{
return 8;
}
virtual int GetTruePacketSize( CigiBaseVariableSizePckt &refPacket ) { return 8; }
Cigi_uint16 packSize;
Cigi_uint16 packID;
};
DtCigiExtender::DtCigiExtender( DtCigiConnection& connection )
: DtVirtualBaseClass()
, myConnection( connection )
{
myConnections += DtCigiSignalProcessor::instance( connection ).signal_componentControlReceived.connect(
boost::bind( &DtCigiExtender::slot_componentControlReceived, this, boost::placeholders::_1 ) );
myConnections += DtCigiSignalProcessor::instance( connection ).signal_waveControlReceived.connect(
boost::bind( &DtCigiExtender::slot_waveControlReceived, this, boost::placeholders::_1 ) );
myConnections += DtCigiSignalProcessor::instance( connection ).signal_unrecognizedPacketReceived.connect(
boost::bind( &DtCigiExtender::slot_customPacketReceived, this, boost::placeholders::_1 ) );
// You must register your packet with the CIGI incoming packet manager, to process
// unknown, non CIGI/MAK packet IDs. This can be done through the CIGI IG Session.
// Create a packet class similar to the DiGuy custom CIGI packets.
// For V3 and V4 observe the following numbering restrictions, per the standard:
// Cigi_uint16 minUserPacketID = myConnection.getCigiVersion().CigiMajorVersion < 4 ? 201 : 0x1000;
// Cigi_uint16 maxUserPacketID = myConnection.getCigiVersion().CigiMajorVersion < 4 ? 255 : 0xfffe;
// For example :
CustomV4Packet * myPacket = new CustomV4Packet();
myConnection.networkIO().session().RegisterUserPacket( myPacket, 0x1000, true, false );
}
DtCigiExtender::~DtCigiExtender()
{
// nothing else to do
}
void DtCigiExtender::slot_componentControlReceived( CigiBaseCompCtrl& msg )
{
if(myConnection.getCigiVersion().CigiMajorVersion == 3)
{
CigiCompCtrlV3_3 * compCtrlMsgV3 = static_cast<CigiCompCtrlV3_3*>(&msg);
std::cout << "Received a CIGI Component Control Message" << std::endl;
std::cout << " -- Instance ID: " << (int)compCtrlMsgV3->GetInstanceID() << std::endl;
}
else if(myConnection.getCigiVersion().CigiMajorVersion == 4)
{
CigiCompCtrlV4 * compCtrlMsgV4 = static_cast<CigiCompCtrlV4*>(&msg);
std::cout << "Received a CIGI Component Control Message" << std::endl;
std::cout << " -- Instance ID: " << (int)compCtrlMsgV4->GetInstanceID() << std::endl;
}
}
void DtCigiExtender::slot_waveControlReceived( CigiBaseWaveCtrl& msg )
{
if(myConnection.getCigiVersion().CigiMajorVersion == 3)
{
CigiWaveCtrlV3* waveCtrlMsgV3 = static_cast<CigiWaveCtrlV3*>(&msg);
std::cout << "Received a CIGI Wave Control Message" << std::endl;
std::cout << " -- Wave ID: " << (int)waveCtrlMsgV3->GetWaveID() << std::endl;
std::cout << " -- Wave Height: " << waveCtrlMsgV3->GetWaveHt() << std::endl;
}
else if(myConnection.getCigiVersion().CigiMajorVersion == 4)
{
CigiWaveCtrlV4* waveCtrlMsgV4 = static_cast<CigiWaveCtrlV4*>(&msg);
std::cout << "Received a CIGI Wave Control Message" << std::endl;
std::cout << " -- Wave ID: " << (int)waveCtrlMsgV4->GetWaveID() << std::endl;
std::cout << " -- Wave Height: " << waveCtrlMsgV4->GetWaveHt() << std::endl;
}
}
void DtCigiExtender::slot_customPacketReceived( CigiBasePacket& msg )
{
std::cout << "Received a CIGI Message of an Unknown Type" << std::endl;
if(myConnection.getCigiVersion().CigiMajorVersion == 4)
{
CustomV4Packet * customPacketTest = dynamic_cast<CustomV4Packet*>(&msg);
if(customPacketTest)
{
std::cout << customPacketTest->GetPacketID() << std::endl;
}
}
}
}

[<< Examples] [Home] [Top of Page]


Document ID: Generated on Thu Oct 23 22:29:17 EDT 2025 from SVN revision 280951
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)