University of Southern CaliforniaUSC
USC ICT TwitterUSC ICT FacebookUSC ICT YouTube

WSP (World State Protocol) | General SmartBody Discussion | Forum

Avatar

Please consider registering
guest

sp_LogInOut Log In sp_Registration Register

Register | Lost password?
Advanced Search

— Forum Scope —




— Match —





— Forum Options —





Minimum search word length is 3 characters - maximum search word length is 84 characters

sp_Feed Topic RSS sp_TopicIcon
WSP (World State Protocol)
July 5, 2014
2:55 pm
Avatar
Member
Members
Forum Posts: 4
Member Since:
February 12, 2014
sp_UserOfflineSmall Offline

I've seen references here and there to something called WSP, which I gather stands for World State Protocol. However, I haven't found any documentation about it and it appears to have been removed from Smartbody back in May.

Is there any information available about what it is (or was)?

I'm working on a multi-user application that (obviously) involves shared state, which is why "World State Protocol" caught my eye.

Thanks in advance for any information.

July 5, 2014
8:23 pm
Avatar
Admin
Forum Posts: 983
Member Since:
December 1, 2011
sp_UserOfflineSmall Offline

The WSP library was a set of functions that allowed you to access state information from SmartBody and publish it onto the ActiveMQ message bus. For example, you could say 'send me the position of a character' and WSP library would send out such information as needed, or every second or so.   This functionality was built into SmartBody with the intention of using it for loosely coupled applications; you could write a separate application that knew nothing of SmartBody, but understood the WSP protocol, and could therefore gather basic state information.

We recently removed it because of lack of use. I've attached the documentation for it below:

 

Documents:World State Protocol

Jump to: navigation, search

Overview - The World State Protocol (WSP) is a library in C++/Java/Tcl that enables SASO modules to send and receive data to and from other modules within the system.

TAB Goal - ?

Developer - Tom Amundsen

Version - 1.0

SVN location - C++ implementation: \saso\core\smartbody\wsp; Java implementation: \saso\core\smartbody\wspj; Tcl implementation: \saso\core\smartbody\wspTcl

Technical maturity - prototype version, engineering module, internal ICT use

Projects that use this module

  • SASO
  • Smartbody

Contents

 [hide

[edit] Usage

C++ Implementation
You should include \wsp\include and link with wsp.lib. Also do a #include "wsp.h" to be able to call functions in the API. You will need to establish your own Elvish connection.

Wherever you want to make calls to the WSP library, you should have a line like this:
Manager* theWSP = create_manager();
Then make calls to the API like this:
theWSP->init();

Java Implementation
You should include the wsp.lib in your build path.

If you're providing data, you want to:
import manager.Manager;
import manager.WSPVector;
import manager.WSPVector3D;
import manager.WSPVector4D;
import callbacks.DoubleCallback;
import callbacks.ErrorCallback;
import callbacks.IntCallback;
import callbacks.RaycastCallback;
import callbacks.StringCallback;
import callbacks.Vector3DCallback;
import callbacks.Vector4DCallback;
import dataSources.DataType;
import edu.isi.mre.elvin.MessageEvent;
import edu.isi.mre.elvin.MessageListener;
import exceptions.ErrorCode;
import exceptions.WSPException;

If you're accessing data, you want to:
import manager.Manager;
import manager.WSPVector;
import manager.WSPVector3D;
import manager.WSPVector4D;
import accessors.DoubleAccessor;
import accessors.IntAccessor;
import accessors.RaycastProvider;
import accessors.StringAccessor;
import accessors.Vector3DAccessor;
import accessors.Vector4DAccessor;
import edu.isi.mre.elvin.MessageEvent;
import edu.isi.mre.elvin.MessageListener;
import exceptions.WSPDataNotFoundException;
import exceptions.WSPException;

Then, somewhere you should have a line like:
Manager theWSP = new Manager();

and just make calls to it like:
theWSP.init();

Tcl Implementation
Just run the elvish executable and call any wsp commands that you wish

 Functionality

  • init
  • shutdown
  • broadcast_update
  • process_command
  • register_int_source
  • register_double_source
  • register_string_source
  • register_vector_3d_source
  • register_vector_4d_source
  • register_raycast_provider
  • unregister_data_source
  • query_int_data
  • query_double_data
  • query_string_data
  • query_vector_3d_data
  • query_vector_4d_data
  • query_raycast
  • subscribe_int_interval
  • subscribe_double_interval
  • subscribe_string_interval
  • subscribe_vector_3d_interval
  • subscribe_vector_4d_interval
  • unsubscribe

 How To

init

This function is currently a NO-OP.

C++

theWSP->init();

Java

theWSP.init();

Tcl

wsp_init

shutdown

This function does some memory cleanup in the C++ and (naturally) in the Tcl implementations, but is just a NO-OP in the Java implementation.

C++

theWSP->shutdown();

Java

theWSP.shutdown();

Tcl

wsp_shutdown

broadcast_update

This is the workhorse method. It does everything on the server side to send out updates that need to be sent and everything on the client side to handle updates received and handles any errors that occur.

time: This should be your process' current time. It will be used to determine when to send updates.

 


NOTE: You are required to make the library function in seconds. So, you can call broadcast_update( time + 1 ) every second, broadcast_update( time + 1/1000 ) every millisecond, etc.

C++

theWSP->broadcast_update( double time );

Java

theWSP.broadcastUpdate( double time );

Tcl

wsp_broadcast_update $timer

process_command

This message is called when a WSP client's callback function receives a message with an op matching a message type it has subscribed to. It takes the message and handles it appropriately depending on the first token that identifies what type of message it receives.

message: the Elvin message received in the callback

C++

theWSP->process_command( char* message );

Java

theWSP.processCommand( string message );

In Tcl, you actually do not need to use this. It is hidden within the elvish.exe.

 REGISTRATION FUNCTIONS

All registration functions require you to define an accessor function in some way that will return the requested data.

In C++, every time you call one of the register_x_source functions, you must pass in a function pointer following the format:

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
long& value: reference to a long, you update its value to the current value when this accessor is called, and the function that called it will have the new value
void* data: the (C++) class data object that can be passed in to manipulate data

WSP_ERROR ( *int_accessor_function )( const std::string id, const std::string attribute_name, long& value, void* data );

 

Obviously you may need to change the datatype of the value to either: double, std::string, or wsp_vector. You are only required to modify the value to its current value and return a WSP_ERROR object indicating the error type.

In Java, you should make your class implement, for example, accessors.IntAccessor. Then you will be required to create a method:

public int getIntData( String id, String attributeName, Object data ) throws WSPException;

 

This function should return the current value of the data. Once again, you can apply this to; double, string, WSPVector3D, WSPVector4D.

In Tcl, you should create a command such as:

proc intAccessor{} {
     return $intValue
}

 register_int_source

This method allows a WSP implementer (providing data) to register an integer data source.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
int_accessor_function_pointer: the (C++) accessor function that the client claims will be able to retrieve the data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( IntAccessor )this: the (Java) accessor interface (containing the accessor function) that the client claims will be able to retrieve the data (we pass 'this', because you should be calling it from a class that implements IntAccessor; the getIntData method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

intAccessor: the Tcl command that the client claims will be able to retrieve the data

C++

theWSP->register_int_source( std::string id, std::string attribute_name, int_accessor_function_pointer, void* data );

Java

theWSP.registerIntSource( String id, String attributeName, ( IntAccessor )this, Object data );

Tcl

wsp_register_int_source id attributeName intAccessor

register_double_source

This method allows a WSP implementer (providing data) to register a double data source.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
double_accessor_function_pointer: the (C++) accessor function that the client claims will be able to retrieve the data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( DoubleAccessor )this: the (Java) accessor interface (containing the accessor function) that the client claims will be able to retrieve the data (we pass 'this', because you should be calling it from a class that implements DoubleAccessor; the getDoubleData method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

doubleAccessor: the Tcl command that the client claims will be able to retrieve the data

C++

theWSP->register_double_source( std::string id, std::string attribute_name, double_accessor_function_pointer, void* data );

Java

theWSP.registerDoubleSource( String id, String attributeName, ( DoubleAccessor )this, Object data );

Tcl

wsp_register_double_source id attributeName doubleAccessor

register_string_source

This method allows a WSP implementer (providing data) to register a string data source.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
string_accessor_function_pointer: the (C++) accessor function that the client claims will be able to retrieve the data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( StringAccessor )this: the (Java) accessor interface (containing the accessor function) that the client claims will be able to retrieve the data (we pass 'this', because you should be calling it from a class that implements StringAccessor; the getStringData method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

stringAccessor: the Tcl command that the client claims will be able to retrieve the data

 

C++

theWSP->register_string_source( std::string id, std::string attribute_name, string_accessor_function_pointer, void* data );

Java

theWSP.registerStringSource( String id, String attributeName, ( StringAccessor )this, Object data );

Tcl

wsp_register_string_source id attributeName stringAccessor

register_vector_3d_source

This method allows a WSP implementer (providing data) to register a Vector3D data source.

 

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
vector_3d_accessor_function_pointer: the (C++) accessor function that the client claims will be able to retrieve the data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( Vector3DAccessor )this: the (Java) accessor interface (containing the accessor function) that the client claims will be able to retrieve the data (we pass 'this', because you should be calling it from a class that implements Vector3DAccessor; the getVector3DData method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

vector3DAccessor: the Tcl command that the client claims will be able to retrieve the data

 

C++

theWSP->register_vector_3d_source( std::string id, std::string attribute_name, vector_3d_accessor_function_pointer, void* data );

Java

theWSP.registerVector3DSource( String id, String attributeName, ( Vector3DAccessor )this, Object data );

Tcl

wsp_register_vector_3d_source id attributeName vector3DAccessor

 register_vector_4d_source

This method allows a WSP implementer (providing data) to register a Vector4D data source.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
vector_4d_accessor_function_pointer: the (C++) accessor function that the client claims will be able to retrieve the data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( Vector4DAccessor )this: the (Java) accessor interface (containing the accessor function) that the client claims will be able to retrieve the data (we pass 'this', because you should be calling it from a class that implements Vector4DAccessor; the getVector4DData method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

vector4DAccessor: the Tcl command that the client claims will be able to retrieve the data

C++

theWSP->register_vector_4d_source( std::string id, std::string attribute_name, vector_4d_accessor_function_pointer, void* data );

Java

theWSP.registerVector4DSource( String id, String attributeName, ( Vector4DAccessor )this, Object data );

Tcl

wsp_register_vector_4d_source id attributeName vector3DAccessor

 register_raycast_provider

This method allows a WSP implementer (providing data) to register a raycast data source.

 

raycast_provider_function_pointer: the (C++) raycast provider function that the client claims will be able to perform raycasts. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( RaycastProvider )this: the (Java) accessor interface (containing the accessor function) that the client claims will be able to perform the raycast (we pass 'this', because you should be calling it from a class that implements RaycastProvider; the performRaycast method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

raycastProvider: the Tcl command that the client claims will be able to perform the raycast

C++

theWSP->register_raycast_source( raycast_provider_function, void* data );

Java

theWSP.registerRaycastSource( ( RaycastProvider )this, data );

Tcl

wsp_register_raycast_provider raycastProvider

 unregister_data_source

This method removes a registered data source

id: the id of the object we are unregistering an accessor function from
attribute_name: the attribute name of the object we are unregistering an accessor function from

C++

theWSP->unregister_data_source( std::string id, std::string attribute_name );

Java

theWSP.unregisterDataSource( String id, String attributeName );

Tcl

wsp_unregister_data_source id attributeName

 QUERYING FUNCTIONS

All query functions require you to define a callback and error callback functions in some way that will respectively use the data and handle any errors that occur while trying to perform the callback.

In C++, every time you call one of the query_x_data functions, you must pass in function pointers following the formats:

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
long& value: reference to a long, you update its value to the current value when this accessor is called, and the function that called it will have the new value
void* data: the (C++) class data object that can be passed in to manipulate data

error: the error code that represents what happened
reason: the human-readable error message

WSP_ERROR ( *int_callback )( const std::string id, const std::string attribute_name, long& value, void* data );
void ( *error_callback )( const std::string id, const std::string attribute_name, int error, std::string reason, void* data );

 

Obviously you may need to change the datatype of the value to either: double, std::string, or wsp_vector. You can do anything you want with 'value', that is the entire reason why you are using the WSP library! The error_callback will provide you an error code and the reason why this error occurred.

In Java, you should make your class implement, for example, callbacks.IntCallback and callbacks.ErrorCallback. Then you will be required to create the methods:

public void callback( String id, String attributeName, long value, Object data ) throws WSPException;
public void callback( String id, String attributeName, ErrorCode error, String reason, Object data ) throws WSPException;

 

Once again, you can do anything you want with 'value'.

In Tcl, you should create a command such as:

proc intCallback { value } { <br/> 
     puts "value is: $value"<br/> 
}

query_int_data

This function allows a WSP implementers to query a piece of integer data.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
int_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( IntCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements IntCallback; the intCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

intCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->query_int_data( std::string id, std::string attribute_name, error_callback_function_pointer, int_callback_function_pointer, void* data );

Java

theWSP.queryIntData( String id, String attributeName, ( ErrorCallback )this, ( IntCallback )this, Object data );

Tcl

wsp_query_int_data id attributeName errorCallback intCallback

 query_double_data

This function allows a WSP implementers to query a piece of double data.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
double_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( DoubleCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements DoubleCallback; the doubleCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

doubleCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->query_double_data( std::string id, std::string attribute_name, error_callback_function_pointer, double_callback_function_pointer, void* data );

Java

theWSP.queryDoubleData( String id, String attributeName, ( ErrorCallback )this, ( DoubleCallback )this, Object data );

Tcl

wsp_query_double_data id attributeName errorCallback doubleCallback

 query_string_data

This function allows a WSP implementers to query a piece of string data.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
string_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( StringCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements StringCallback; the stringCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

stringCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->query_string_data( std::string id, std::string attribute_name, error_callback_function_pointer, string_callback_function_pointer, void* data );

Java

theWSP.queryStringData( String id, String attributeName, ( ErrorCallback )this, ( StringCallback )this, Object data );

Tcl

wsp_query_string_data id attributeName errorCallback stringCallback

 query_vector_3d_data

This function allows a WSP implementers to query a piece of Vector3D data.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
vector_3d_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( Vector3DCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements Vector3DCallback; the vector3DCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

vector3DCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->query_vector_3d_data( std::string id, std::string attribute_name, error_callback_function_pointer, vector_3d_callback_function_pointer, void* data );

Java

theWSP.queryVector3DData( String id, String attributeName, ( ErrorCallback )this, ( Vector3DCallback )this, Object data );

Tcl

wsp_query_vector_3d_data id attributeName errorCallback vector3DCallback

query_vector_4d_data

This function allows a WSP implementers to query a piece of Vector3D data.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
vector_4d_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( Vector4DCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements Vector4DCallback; the vector4DCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

vector4DCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->query_vector_4d_data( std::string id, std::string attribute_name, error_callback_function_pointer, vector_4d_callback_function_pointer, void* data );

Java

theWSP.queryVector4DData( String id, String attributeName, ( ErrorCallback )this, ( Vector4DCallback )this, Object data );

Tcl

wsp_query_vector_4d_data id attributeName errorCallback vector4DCallback

 query_raycast

This function allows a WSP implementers to query a raycast provider.

position: the start position of the raycast, where this raycast is originating from
direction: the direction in which the raycast should be performed. raycast is performed from the starting position in the direction of this vector (the way that this is currently implemented in the CommAPI is that the direction is simply the end-point of the trace)
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
raycast_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( RaycastCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements RaycastCallback; the raycastCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

raycastCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->query_raycast( const wsp_vector& position, const wsp_vector& direction, error_callback_function_pointer, raycast_callback_function_pointer, void* data );

Java

theWSP.queryRaycast( position, direction, ( ErrorCallback )this, ( RaycastCallback )this, data );

Tcl

wsp_query_raycast 999.999,888.888,777.777 666.666,555.555,444.444 errorCallback raycastCallback

SUBSCRIBING FUNCTIONS

All subscribe functions require you to define a callback and error callback functions in some way that will respectively use the data and handle any errors that occur while trying to perform the callback.

In C++, every time you call one of the subscribe_x_interval functions, you must pass in function pointers following the formats:

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
long& value: reference to a long, you update its value to the current value when this accessor is called, and the function that called it will have the new value
void* data: the (C++) class data object that can be passed in to manipulate data

error: the error code that represents what happened
reason: the human-readable error message

WSP_ERROR ( *int_callback )( const std::string id, const std::string attribute_name, long& value, void* data );
void ( *error_callback )( const std::string id, const std::string attribute_name, int error, std::string reason, void* data );

 

Obviously you may need to change the datatype of the value to either: double, std::string, or wsp_vector. You can do anything you want with 'value', that is the entire reason why you are using the WSP library! The error_callback will provide you an error code and the reason why this error occurred.

In Java, you should make your class implement, for example, callbacks.IntCallback and callbacks.ErrorCallback. Then you will be required to create a method:

public void callback( String id, String attributeName, long value, Object data ) throws WSPException;
public void callback( String id, String attributeName, ErrorCode error, String reason, Object data ) throws WSPException;

 

Once again, you can do anything you want with 'value'.

In Tcl, you should create a command such as:

proc intCallback { value } {
     puts "value is: $value"
}

 subscribe_int_interval

This method allows a WSP implementer to subscribe to some integer data at a specified interval.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
interval: the rate at which you wish to receive updates for this subscription (the units are measured in seconds)
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
int_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
my_time: your process' current time. this will be used so that we know when the subscription was requested
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( IntCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements IntCallback; the intCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

errorCallback: the Tcl command that the client wants to be called upon receiving an error message
intCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->subscribe_int_interval( std::string id, std::string attribute_name, int interval, error_callback_function_pointer, int_callback_function_pointer, double my_time, void* data );

Java

theWSP.subscribeIntInterval( String id, String attributeName, int interval, ( ErrorCallback )this, ( IntCallback )this, double myTime, Object data );

Tcl

wsp_subscribe_int_interval id attributeName $intervalValue errorCallback intCallback $timer

subscribe_double_interval

This method allows a WSP implementer to subscribe to some double data at a specified interval.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
interval: the rate at which you wish to receive updates for this subscription (the units are measured in seconds)
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
double_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
my_time: your process' current time. this will be used so that we know when the subscription was requested
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( DoubleCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements DoubleCallback; the doubleCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

errorCallback: the Tcl command that the client wants to be called upon receiving an error message
doubleCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->subscribe_double_interval( std::string id, std::string attribute_name, int interval, error_callback_function_pointer, double_callback_function_pointer, double my_time, void* data );

Java

theWSP.subscribeDoubleInterval( String id, String attributeName, int interval, ( ErrorCallback )this, ( DoubleCallback )this, double myTime, Object data );

Tcl

wsp_subscribe_double_interval id attributeName $intervalValue errorCallback doubleCallback $timer

subscribe_string_interval

This method allows a WSP implementer to subscribe to some string data at a specified interval.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
interval: the rate at which you wish to receive updates for this subscription (the units are measured in seconds)
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
string_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
my_time: your process' current time. this will be used so that we know when the subscription was requested
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( StringCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements StringCallback; the stringCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

errorCallback: the Tcl command that the client wants to be called upon receiving an error message
stringCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->subscribe_string_interval( std::string id, std::string attribute_name, int interval, error_callback_function_pointer, string_callback_function_pointer, double my_time, void* data );

Java

theWSP.subscribeStringInterval( String id, String attributeName, int interval, ( ErrorCallback )this, ( StringCallback )this, double myTime, Object data );

Tcl

wsp_subscribe_string_interval id attributeName $intervalValue errorCallback stringCallback $timer

 subscribe_vector_3d_interval

This method allows a WSP implementer to subscribe to some string data at a specified interval.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
interval: the rate at which you wish to receive updates for this subscription (the units are measured in seconds)
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
vector_3d_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
my_time: your process' current time. this will be used so that we know when the subscription was requested
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( Vector3DCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements Vector3DCallback; the vector3DCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

errorCallback: the Tcl command that the client wants to be called upon receiving an error message
vector3DCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->subscribe_vector_3d_interval( std::string id, std::string attribute_name, int interval, error_callback_function_pointer, vector_3d_callback_function_pointer, double my_time, void* data );

Java

theWSP.subscribeVector3DInterval( String id, String attributeName, int interval, ( ErrorCallback )this, ( Vector3DCallback )this, double myTime, Object data );

Tcl

wsp_subscribe_vector_3d_interval id attributeName $intervalValue errorCallback vector3DCallback $timer

 subscribe_vector_4d_interval

This method allows a WSP implementer to subscribe to some string data at a specified interval.

id: the id of the object we are registering data for
attribute_name: the attribute name of the object we are registering data for
interval: the rate at which you wish to receive updates for this subscription (the units are measured in seconds)
error_callback_function_pointer: the (C++) error callback function that the client wants to have called if an error occurrs
vector_4d_callback_function_pointer: the (C++) callback function that the client wants to be called upon receiving an update for this data. this should be defined somewhere within the file you are making this call from
my_time: your process' current time. this will be used so that we know when the subscription was requested
void* data: the (C++) class data object that can be passed in to manipulate data

( ErrorCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called when an error occurs. (we pass 'this', because you should be calling it from a class that implements ErrorCallback; the errorCallback method that you must implement will be used)
( Vector4DCallback )this: the (Java) callback interface (containing the callback function) that the client wants to be called upon receiving an update for this data (we pass 'this', because you should be calling it from a class that implements Vector4DCallback; the vector4DCallback method that you must implement will be used)
Object data: the (Java) class data object that can be passed in to manipulate data

errorCallback: the Tcl command that the client wants to be called upon receiving an error message
vector4DCallback: the Tcl command that the client wants to be called upon receiving an update for this data

C++

theWSP->subscribe_vector_4d_interval( std::string id, std::string attribute_name, int interval, error_callback_function_pointer, vector_4d_callback_function_pointer, double my_time, void* data );

Java

theWSP.subscribeVector4DInterval( String id, String attributeName, int interval, ( ErrorCallback )this, ( Vector4DCallback )this, double myTime, Object data );

Tcl

wsp_subscribe_vector_4d_interval id attributeName $intervalValue errorCallback vector4DCallback $timer

 unsubscribe

This method allows a WSP implementer to cancel one of their subscriptions.

id: the id of the object we are unsubscribing from
attribute_name: the attribute name of the object we are unsubscribing from

C++

theWSP->unsubscribe( std::string id, std::string attribute_name );

Java

theWSP.unsubscribe( String id, String attributeName );

Tcl

wsp_unsubscribe id attributeName

Known Issues

For Raycast data sources (and any other data sources implemented similarly to a Raycast), there is a 'gotcha.' If there are two (or more) Raycast providers, when you perform a raycast-query, you will receive two (or more) raycast responses. You can distinguish between the responses by looking at the process-id token of the response message.

 Implementation

 Architecture

Architecture.jpgImage Enlarger

 Data Structures

All 3 implementations use the same architecture. The C++ and Tcl implentations both rely on the same library, so they are identical. The Java implementation is obviously different than these two, but the architecture is nearly identical.

There are two data structures that are used to contain the data required to send and receive data updates: DataSource and Subscription. Both DataSource and Subscription have wrapper classes for lists containing elements of their datatype, namely: DataSources and Subscriptions.

 Manager

The manager is the class that you actually instantiate in order to make calls to the WSP API. It provides you with a way to make the calls, and it does all the work required to send and receive updates accordingly.

Language and Files

 C++ - \saso\lib\wsp\wsp

  • wsp.h

define enums, vector struct, typedefs for callbacks, provide a factory function, provide pure virtual functions for the WSP API

  • wsp.cpp

implement the factory function and functions that handle errors

  • wsp_data_sources.h

define the member fields for a DataSource and the list: DataSources

  • wsp_data_sources.cpp

provide functions to create a DataSource, and allow you to interact with the list of DataSources

  • wsp_error.h

provide the error code and reason, provide functions to convert error codes from their enum to their string representation and vice-versa

  • wsp_error.cpp

implement the functions to convert error codes

  • wsp_impl.h

hold the necessary lists, the time, inherit the pure virtual functions from 'wsp', allow for necessary protected functions

  • wsp_impl.cpp

this is the file that does all of the work. it contains broadcast_update, process_command, message handling, and the implementation of all of functions in the API

  • wsp_subscriptions.h

define member fields for a Subscription and a list of Subscriptions

  • wsp_subscriptions.cpp

provide functions to create a Subscription, and allow you to interact with the list of Subscriptions

  • wsp_util.cpp

provide a tokenize function that we can use throughout the WSP library

  • wsp_util.h

define the tokenize member function

  • wsp_vector.cpp

a wsp_vector allows us to have a structure for both 3-D and 4-D vectors, functions for creating vectors from strings, and converting strings to vectors

  • wsp_vector.h

define member fields and functions for a wsp_vector

Tcl - \saso\lib\wsp\wspTcl

All of the files under the C++ implementation are used in addition to:

  • elvish.h

function prototypes for Elvish functionality

  • elvish.cpp

function implementations for Elvish functionality; Init function which creates Tcl commands to for the WSP API

  • wsp_tcl.h

function prototypes for WSP API

  • wsp_tcl.cpp

WSP API function implementations. They all parse the input from Tcl and call functions in the C++ API

  • test_server.tcl

a Tcl file that demonstrates all uses of the server-side WSP API

  • test_client.tcl

a Tcl file that demonstrates all uses of the client-side WSP API

Java - \saso\lib\wsp\wspj

  • accessors\Accessor.java

This interface is the super class for all of the data accessors. This is needed so that we can have general functions for subscription, registration, querying, etc that we can pass any type of accessor into, and be able to use the specific functions just the same.

  • accessors\DoubleAccessor.java

This interface provides a function to access double-type data. WSP clients acting as a server should implement this interface.

  • accessors\IntAccessor.java

This interface provides a function to access int-type data. WSP clients acting as a server should implement this interface.

  • accessors\StringAccessor.java

This interface provides a function to access string-type data. WSP clients acting as a server should implement this interface.

  • accessors\Vector3DAccessor.java

This interface provides a function to access Vector3D-type data. WSP clients acting as a server should implement this interface.

  • accessors\Vector4DAccessor.java

This interface provides a function to access Vector4D-type data. WSP clients acting as a server should implement this interface.

  • accessors\RaycastProvider.java

This interface provides a function to perform raycasts. WSP clients acting as a server should implement this interface.

  • callbacks\Callback.java

This interface is the super class for all of the callback functions. This is needed so that we can have general functions for subscription, registration, querying, etc that we can pass any type of callback into, and be able to use the specific functions just the same.

  • callbacks\CallbackHandler.java

This class handles callbacks for all types of data. It basically just keeps the WSP class cleaner by allowing us to replace many lines of code with one function call without using too much memory overhead.

  • callbacks\DoubleCallback.java

This interface provides a function to perform a callback on double-type data. WSP clients acting as a client should implement this interface.

  • callbacks\ErrorCallback.java

This interface provides a function to perform a callback when an error occurs. WSP clients acting as a client should implement this interface.

  • callbacks\IntCallback.java

This interface provides a function to perform a callback on int-type data. WSP clients acting as a client should implement this interface.

  • callbacks\StringCallback.java

This interface provides a function to perform a callback on String-type data. WSP clients acting as a client should implement this interface.

  • callbacks\Vector3DCallback.java

This interface provides a function to perform a callback on Vector3D-type data. WSP clients acting as a client should implement this interface.

  • callbacks\Vector4DCallback.java

This interface provides a function to perform a callback on Vector4D-type data. WSP clients acting as a client should implement this interface.

  • callbacks\RaycastCallback.java

This interface provides a function to perform a callback on raycast data. WSP clients acting as a client should implement this interface.

  • dataSources\DataSource.java

This class is used to create objects that allow a WSP server to provide data.

  • dataSources\AttributeDataSource.java

This class is used to keep track of data sources for information that is retrieved by id/attribute lookup.

  • dataSources\RaycastDataSource.java

This class is used to keep track of data sources for raycast information

  • dataSources\DataSourceList.java

This class is a wrapper for an ArrayList<DataSource>. The main motivation for this to be a wrapper is so that we can change it from an ArrayList<> to a HashMap, or something else without having to chance any code anywhere besides this class. This class provides almost all of the functionality that an ArrayList would, so it's not like this actually protects the data in any particular way.

  • dataSources\DataType.java

This is just an enum that allows us to identify what type of data a DataSource or Subscription is associated with.

 

  • exceptions\ErrorCode.java

This is an enum that allows us to identify all of the different error types. It also provides to functions that allow us to convert an ErrorCode to its String representation, and vice versa.

  • exceptions\WSPDataNotFoundException.java

This exception indicates that data could not be found. This should happen is a DataSource is registered for a specific piece of data, but when it calls its accessor function, it cannot retrieve the data for some unknown reason (i.e. - not a mismatch ID or attributeName)

  • exceptions\WSPException.java

This is the base class for all of the exceptions in this project. It basically just holds an ErrorCode and a reason String. That's all is really needed.

  • exceptions\WSPMismatchAttributeException

This exception indicates that there was a mismatach attributeName. This should happen is a DataSource is registered for a specific ID with a specific accessor function, but when it goes to call that accessor function, the attributeName of the data it is accessing does not match the attributeName that the DataSource claims to provide.

  • exceptions\WSPMismatchIDException.java

This exception indicates that there was a mismatach ID. This should happen is a DataSource is registered for a specific ID with a specific accessor function, but when it goes to call that accessor function, the ID of the data it is accessing does not match the ID that the DataSource claims to provide.

  • exceptions\WSPParseException.java

This is the exception that indicates that there was a parse error. This occurs when a WSP client receives an update response, but the value it receives cannot be parsed to match an acceptable DataType for whatever reason. We will assume that doubles and ints can be interchanged, anything can be accepted as a String. The only real time we should have a parse error is when some kind of Vector is either expected and not received, or received when not expected.

  • exceptions\WSPTimeoutException.java

This is an exception that indicates that there has been a Timeout. This means that a WPS client was expecting an update, but did not receive one (within some period of lag time).

  • manager\Manager.java

This is the class that WSP clients will instantiate. It provides all the functions in the WSP API that allow client processes to register, query, and subscribe to data sources.

  • manager\WSP.java

This is the super class of the Manager. It provides methods that do all of the work that the Manager needs to get done that shouldn't be a part of the WSP API.

  • manager\WSPVector3D.java

This class acts as a data structure for 3D-Vectors. Inherits from WSPVector

  • manager\WSPVector4D.java

This class acts as a data structure for 4D-Vectors. Inherits from WSPVector

  • manager\WSPVector.java

This class acts as a data structure for Vectors

  • manager\VectorString.java

This class provides a way to convert a string to a vector

  • messaging\ElvinConnection.java

This class provides us with a way to send Elvin messages. Its main purpose is to keep this project organized and to allow us to use different types of messaging systems very easily. You would only need to create a new class if you wanted to use a completely different messaging system. None of the code anywhere in the library would have to change.

 

  • dataRequests\DataRequest.java

This is a generic DataRequest. It has functionality for all queries and subscriptions

  • dataRequests\DataRequestList.java

This class is just a wrapper for an ArrayList<Subscrition>. The main motivation for this to be a wrapper is so that we can change it from an ArrayList<> to a HashMap, or something else without having to chance any code anywhere besides this class. This class provides almost all of the functionality that an ArrayList would, so it's not like this actually protects the data in any particular way.

  • dataRequests\AttributeRequest.java

This class is used to create objects that allow a WSP server to keep track of data that store information by id/attribute lookup

  • dataRequests\AttributeSubscription.java

This class is used to create objects that allow a WSP server to perform callbacks and know when to send updates. It keeps track of the id, attributeName, dataType, and data object used for a specific piece of data, as well as a callback function that the library can call whenever it receives an update from a client WSP server process.

  • dataRequests\AttributeQuery.java

This class is used to create objects that allow a WSP server to keep track of data queried that are storing information by id/attribute lookup

  • dataRequests\RaycastRequest.java

This class is used to create objects that allow a WSP server to keep track of data that store information for raycasts

  • dataRequests\RaycastQuery.java

This class is used to create objects that allow a WSP server to keep track of data queried for raycasts

  • dataRequests\RaycastSubscription.java

This class is used to create objects that allow a WSP server to keep track of data subscribed for raycasts

 Interface Modules

As the WSP is a library, it can (and probably should) be used by any module in the SASO system.

Authors of any module should simply follow the steps mentioned above in order to include the library with their module and simply make the appropriate API calls to send or receive the data that they need.

Messages

All of the Elvin messages are completely self-contained, and an modules using the WSP library should never have to read or send any messages. Having said that, here is the list of messages that the WSP uses:

wsp query-attribute-value id attribute-name

This is the message that is sent after you make a call to one of the query_x_data() functions. It indicates that you want to receive one update for the data corresponding to the specified id and attribute-name.

wsp answer-attribute-value process-id id attribute-name UPDATE/ERROR value/message

This is the message that is sent when a WSP acting as a server is sending an update. It simply sends out the id, attribute-name, and value and indicates UPDATE. If there was an error while accessing the data, it will say ERROR instead of UPDATE, and the next token will contain the error message.

wsp subscribe-attribute-value id attribute-name interval

This is the message that is sent when you make a call to one of the subscribe_x_interval() functions. It indicates that you want to subscribe to receive updates for the specified id and attribute-name at the specified rate.

wsp unsubscribe-attribute-value id attribute-name interval

This is the message that is sent when you call the unsubscribe() function. It indicates that you want to remove your subscription to the specified id and attribute-name at the specified rate.

 Future Features

  • Updates sent only upon change. Consumers just subscribe to a piece of data. Producers send updates every time the data has "changed". With many types of data, there will be some sort of change-determining function. If we are tracking position, the double values of all the vector components will change constantly by infinitesimal amounts, and this probably doesn't need to be communicated.
  • Configuration file to auto-subscribe to data that is assumed to be presently provided. This is already somewhat implemented if you look at the doAutoSubscribe() method in the wspj\src\testing\WSPTestClient.java and wspj\wspTestClient.props configuration file.
  • Sensors/WMEs. Make a template sensor which contains a WME. The sensor detects when data has changed and sends out an update. The API would have to support new functionality to actually create these sensors. It would probably just involve passing a few more function pointers.
  • Handling other types of data: line of sight calculations, ontology information, etc.
  • Different methods of requesting data: "I want the position of all people within a 50 m radius of me;" "I want the rotation of all captains in the current game;" "I want the hair color of all children under than age of 9;" etc.
July 7, 2014
1:21 pm
Avatar
Member
Members
Forum Posts: 4
Member Since:
February 12, 2014
sp_UserOfflineSmall Offline

 Thanks, Ari. It looks somewhat similar to what I have in mind, but if I'm the only person who would be using it I can see why you removed it.  🙂

I'm well along in my own work anyway, I just didn't want to re-invent the wheel.

A (sort-of) related question... the physics implementation appears to apply only to objects colliding with a character. Are pawns influenced by things like gravity, and are they able to collide with each other? I'm looking over the Python API and I don't see any way to set the physical properties of a pawn, just a joint.

Also, is there any notion of pawns being attached in a  transform hierarchy? For example, if I have a table with a chess board and some pieces on it, and I move the table, the board and pieces would move as well rather than remaining in place. If not, I can certainly move all the pawns (and knights and rooks, too!) but if I don't need to then I won't.  🙂

(Just to give some context... I'm working on a simple multi-user environment in which some avatars are controlled by users and some are controlled by SmartBody, in an environment containing objects that they can all interact with).

July 7, 2014
5:32 pm
Avatar
Admin
Forum Posts: 983
Member Since:
December 1, 2011
sp_UserOfflineSmall Offline

You can still use the wsp library, if you like.

I don't have any parenting feature in SmartBody that would let you parent the 'pawns' to the chessboard - you'll have to move them directly. I'll add the parenting feature when I have some time to do so.

The pawns have joints (usually just one joint). The physics properties are applied to the joints, which are proxies for rigid bodies. So when you set the physical properties for a joint, you are in effect setting the properties for a joint.

We are currently using the collision library from the ODE physics package. You can set two attributes on the pawns:

collisionShape  =  sphere, box, capsule

collisionShapeScale = (1,1,1)

 

like this:

 

scene.getPawn("mypawn").setStringAttribute("collisionShape", "sphere")

scene.getPawn("mypawn").setVec3Attribute("collisionShapeScale, 1, 1, 1)

 

where the scale represent three parameters that are interpreted differently depending on the shape:

sphere - radius is the first parameter,

capsule - radius is the first parameter, length is the second,

box - x,y,z are first, second and third parameters

 

We haven't included mesh-based collisions, but that would be easy to add.

Any object that is physics-based can collide with other physics-based objects, see an example here:

https://www.youtube.com/watch?feature=player_embedded&v=ePqTYhcohcU

 

Ari

July 7, 2014
8:21 pm
Avatar
Member
Members
Forum Posts: 4
Member Since:
February 12, 2014
sp_UserOfflineSmall Offline

Great, thanks Ari. That should work fine for what I'm doing.

Forum Timezone: America/Los_Angeles

Most Users Ever Online: 733

Currently Online: jiangringgaard7, groth23rowland, mcclain06kearney, bugge59mackinnon, williamson15mogensen, raskrask1, JosephRoper17, heavenlyliar6390
93 Guest(s)

Currently Browsing this Page:
1 Guest(s)

Top Posters:

jwwalker: 80

jyambao: 52

rbaral: 47

adiaz: 30

WargnierP: 29

lucky7456969: 28

mbarros: 28

avida.matt: 26

JonathanW: 24

laguerre: 23

Member Stats:

Guest Posters: 69

Members: 122211

Moderators: 3

Admins: 4

Forum Stats:

Groups: 1

Forums: 5

Topics: 531

Posts: 2495