mirror of
https://github.com/nasa/trick.git
synced 2024-12-24 07:16:41 +00:00
Variable Server - var_send_once and integration test (#1330)
* Adds the send_once command and message type, which allows a user to request a variable to be sent immediately and only once (intended to replace the var_add, var_send, var_clear idiom that is commonly used for this purpose) * Minor refactoring of variable server internals to reduce repeated code * Adds SIM_test_varserv to integration test to test basic variable server functionality * Changes graphics client for SIM_billiards to use var_send_once as an example of intended use * Add documentation for var_send_once in docs and tutorial * Set exit_code_enabled in trick unit tests to be true by default * Patch for failing bookworm build
This commit is contained in:
parent
6d56c281e0
commit
9c8799610f
@ -189,6 +189,22 @@ trick.var_send()
|
|||||||
The var_send command forces the variable server to return the list of values to the
|
The var_send command forces the variable server to return the list of values to the
|
||||||
client immediately.
|
client immediately.
|
||||||
|
|
||||||
|
#### Sending variables only once and immediately
|
||||||
|
|
||||||
|
```python
|
||||||
|
trick.var_send_once( string var_name)
|
||||||
|
```
|
||||||
|
|
||||||
|
The var_send_once command forces the variable server to return the value of the given
|
||||||
|
variable to the client immediately.
|
||||||
|
|
||||||
|
```python
|
||||||
|
trick.var_send_once( string var_list, int num_vars)
|
||||||
|
```
|
||||||
|
|
||||||
|
var_send_once can also accept a comma separated list of variables. The number of variables
|
||||||
|
in this list must match num_vars, or it will not be processed.
|
||||||
|
|
||||||
#### Changing the Units
|
#### Changing the Units
|
||||||
|
|
||||||
```python
|
```python
|
||||||
@ -386,12 +402,17 @@ unprintable character) that occurs within the character string value will appear
|
|||||||
escaped character, i.e. preceded by a backslash.
|
escaped character, i.e. preceded by a backslash.
|
||||||
|
|
||||||
The 1st value returned in the list will always be a message indicator. The possible
|
The 1st value returned in the list will always be a message indicator. The possible
|
||||||
values of the message indicator are:
|
values of the message indicator listen in the table below.
|
||||||
- 0 returned variable value(s) from var_add or var_send
|
|
||||||
- 1 returned value from var_exists
|
| Name | Value | Meaning |
|
||||||
- 2 returned value from send_sie_resource (special command used by Trick View)
|
|-------------------|-------|---------|
|
||||||
- 3 returned value from send_event_data (special command used by Events/Malfunctions Trick View) or var_send_list_size
|
| VS\_IP\_ERROR | -1 | Protocol Error|
|
||||||
- 4 values redirected from stdio if var_set_send_stdio is enabled
|
| VS\_VAR\_LIST | 0 | A list of variable values. |
|
||||||
|
| VS\_VAR\_EXISTS | 1 | Response to var\_exists( variable_name )|
|
||||||
|
| VS\_SIE\_RESOURCE | 2 | Response to send_sie_resource|
|
||||||
|
| VS\_LIST\_SIZE | 3 | Response to var_send_list_size or send_event_data|
|
||||||
|
| VS\_STDIO | 4 | Values Redirected from stdio if var_set_send_stdio is enabled|
|
||||||
|
| VS\_SEND\_ONCE | 5 | Response to var\_send\_once|
|
||||||
|
|
||||||
If the variable units are also specified along with the variable name in a var_add or
|
If the variable units are also specified along with the variable name in a var_add or
|
||||||
var_units command, then that variable will also have its units specification returned following
|
var_units command, then that variable will also have its units specification returned following
|
||||||
|
@ -133,8 +133,7 @@ Control Panel, as shown below.
|
|||||||
The output of the script will display three columns of numbers. The left most
|
The output of the script will display three columns of numbers. The left most
|
||||||
number is the [variable server message type](#variable-server-message-types).
|
number is the [variable server message type](#variable-server-message-types).
|
||||||
Here, a message type of 0 indicates that the message is the (tab delimited) list
|
Here, a message type of 0 indicates that the message is the (tab delimited) list
|
||||||
of the values we requested. This is the only message type we'll be concerned
|
of the values we requested. The two columns to the right of the message number are
|
||||||
with in this tutorial. The two columns to the right of the message number are
|
|
||||||
the values of ```dyn.cannon.pos[0]``` and ```dyn.cannon.pos[1]```, in the order
|
the values of ```dyn.cannon.pos[0]``` and ```dyn.cannon.pos[1]```, in the order
|
||||||
that they were specified in the script.
|
that they were specified in the script.
|
||||||
|
|
||||||
@ -208,14 +207,68 @@ Suppose we wanted to get the value of the initial angle of our cannon. We don't
|
|||||||
need to get it repeatedly, because it doesn't change. We just want to get it
|
need to get it repeatedly, because it doesn't change. We just want to get it
|
||||||
once, and then to repeatedly get the position data, which changes over time.
|
once, and then to repeatedly get the position data, which changes over time.
|
||||||
|
|
||||||
For this situation we can use the [**var_send**](#api-var-send) command, which
|
For this situation, we can take one of several approaches. The most straightforward
|
||||||
tells the variable server to send the values specified in the session variable
|
is the [**var_send_once**](#api-var-send-once) command, which tells the variable
|
||||||
list immediately, regardless of whether [**var_pause**](#api-var-pause) was
|
server to send the values sent as arguments immediately, regardless of whether
|
||||||
previously commanded.
|
[**var_pause**](#api-var-pause) was previously commanded.
|
||||||
|
|
||||||
To demonstrate how this works, let's add the following code to our script, right
|
To demonstrate how this works, let's add the following code to our script, right
|
||||||
after the line where we sent the **var_ascii** command.
|
after the line where we sent the **var_ascii** command.
|
||||||
|
|
||||||
|
```python
|
||||||
|
client_socket.send( "trick.var_send_once(\"dyn.cannon.init_angle\")\n")
|
||||||
|
line = insock.readline()
|
||||||
|
print line
|
||||||
|
```
|
||||||
|
|
||||||
|
In this code, we simply ask the variable server to immediately send the value of ```dyn.cannon.init_angle```,
|
||||||
|
call ```insock.readline()``` to wait for a response, and print the response when it is received.
|
||||||
|
[**var_send_once**](#api-var-send-once) does not alter the session variable list in any way.
|
||||||
|
|
||||||
|
When we run the client, the first few lines of output should look something like:
|
||||||
|
|
||||||
|
```
|
||||||
|
5 0.5235987755982988
|
||||||
|
|
||||||
|
0 0 0
|
||||||
|
|
||||||
|
0 0 0
|
||||||
|
```
|
||||||
|
|
||||||
|
The [**var_send_once**](#api-var-send-once) command uses a [message type](#variable-server-message-types) of 5
|
||||||
|
to allow a programmer to differentiate between normal session variables and var_send_once variables. var_send_once
|
||||||
|
does not alter or interfere with the session variable list, which would allow both of these features to be
|
||||||
|
used simultaneously in a sim.
|
||||||
|
|
||||||
|
The [**var_send_once**](#api-var-send-once) also allows a user to request multiple variables in a single
|
||||||
|
command. [**var_send_once**](#api-var-send-once) can accept a comma-separated list of variables as the
|
||||||
|
first argument and the number of variables in the list as the second argument.
|
||||||
|
In our example, suppose we also wanted to retrieve the initial speed of the cannonball.
|
||||||
|
We could retrieve both variables with a single command:
|
||||||
|
|
||||||
|
```python
|
||||||
|
client_socket.send( "trick.var_send_once(\"dyn.cannon.init_angle, dyn.cannon.init_speed\", 2)\n")
|
||||||
|
```
|
||||||
|
|
||||||
|
Now, when we run the client, we get both the init_angle and the init_speed with the first message.
|
||||||
|
|
||||||
|
```
|
||||||
|
5 0.5235987755982988 50
|
||||||
|
|
||||||
|
0 0 0
|
||||||
|
|
||||||
|
0 0 0
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Another commonly used pattern to retrieve variables only once is to use the [**var_add**](#api-var-add),
|
||||||
|
[**var_send**](#api-var-send), and [**var_clear**](#api-var-clear) commands. [**var_send**](#api-var-send) tells
|
||||||
|
the variable server to send all **session** variables immediately regardless of whether [**var_pause**](#api-var-pause)
|
||||||
|
was previously commanded.
|
||||||
|
|
||||||
|
To demonstrate how this works, replace the code in the previous listing with the snippet below, right
|
||||||
|
after the line where we sent the **var_ascii** command.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
client_socket.send( "trick.var_add(\"dyn.cannon.init_angle\")\n")
|
client_socket.send( "trick.var_add(\"dyn.cannon.init_angle\")\n")
|
||||||
client_socket.send( "trick.var_send()\n" )
|
client_socket.send( "trick.var_send()\n" )
|
||||||
@ -224,6 +277,8 @@ print line
|
|||||||
client_socket.send( "trick.var_clear()\n" )
|
client_socket.send( "trick.var_clear()\n" )
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
In this snippet of code, we add ```dyn.cannon.init_angle``` to the session
|
In this snippet of code, we add ```dyn.cannon.init_angle``` to the session
|
||||||
variable list. Then we call [**var_send**](#api-var-send) to tell the variable
|
variable list. Then we call [**var_send**](#api-var-send) to tell the variable
|
||||||
server to send us the value, and wait for the response by calling
|
server to send us the value, and wait for the response by calling
|
||||||
@ -501,6 +556,7 @@ Add this to the bottom of RUN_test/input.py to give it a try.
|
|||||||
| VS\_SIE\_RESOURCE | 2 | Response to send_sie_resource|
|
| VS\_SIE\_RESOURCE | 2 | Response to send_sie_resource|
|
||||||
| VS\_LIST\_SIZE | 3 | Response to var_send_list_size or send_event_data|
|
| VS\_LIST\_SIZE | 3 | Response to var_send_list_size or send_event_data|
|
||||||
| VS\_STDIO | 4 | Values Redirected from stdio if var_set_send_stdio is enabled|
|
| VS\_STDIO | 4 | Values Redirected from stdio if var_set_send_stdio is enabled|
|
||||||
|
| VS\_SEND\_ONCE | 5 | Response to var\_send\_once|
|
||||||
|
|
||||||
<a id=the-variable-server-api></a>
|
<a id=the-variable-server-api></a>
|
||||||
### The Variable Server API
|
### The Variable Server API
|
||||||
@ -545,6 +601,13 @@ Resume periodic responses.
|
|||||||
**var\_send()** -
|
**var\_send()** -
|
||||||
Send response immediately.
|
Send response immediately.
|
||||||
|
|
||||||
|
<a id=api-var-send-once></a>
|
||||||
|
**var\_send\_once( variable_name )** -
|
||||||
|
Immediately send the value of variable_name
|
||||||
|
|
||||||
|
**var\_send\_once( variable_list, num_variables )** -
|
||||||
|
Immediately send the value of all variables in the comma separated variable_list, or an error if the number of variables in the list does not match num_variables
|
||||||
|
|
||||||
<a id=api-var-clear></a>
|
<a id=api-var-clear></a>
|
||||||
**var\_clear()** -
|
**var\_clear()** -
|
||||||
Clear the session variable list.
|
Clear the session variable list.
|
||||||
|
@ -305,6 +305,8 @@ int var_add(std::string in_name, std::string units_name) ;
|
|||||||
int var_remove(std::string in_name) ;
|
int var_remove(std::string in_name) ;
|
||||||
int var_units(std::string var_name , std::string units_name) ;
|
int var_units(std::string var_name , std::string units_name) ;
|
||||||
int var_exists(std::string in_name) ;
|
int var_exists(std::string in_name) ;
|
||||||
|
int var_send_once(std::string in_name) ;
|
||||||
|
int var_send_once(std::string in_name, int numArgs) ;
|
||||||
int var_send() ;
|
int var_send() ;
|
||||||
int var_clear() ;
|
int var_clear() ;
|
||||||
int var_cycle(double in_rate) ;
|
int var_cycle(double in_rate) ;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
#include "trick/ThreadBase.hh"
|
#include "trick/ThreadBase.hh"
|
||||||
#include "trick/VariableServerReference.hh"
|
#include "trick/VariableServerReference.hh"
|
||||||
#include "trick/variable_server_sync_types.h"
|
#include "trick/variable_server_sync_types.h"
|
||||||
|
#include "trick/variable_server_message_types.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Trick {
|
namespace Trick {
|
||||||
|
|
||||||
@ -120,6 +122,16 @@ namespace Trick {
|
|||||||
*/
|
*/
|
||||||
int var_exists( std::string in_name ) ;
|
int var_exists( std::string in_name ) ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief @userdesc Command to immediately send the value of a comma separated list of variables
|
||||||
|
@par Python Usage:
|
||||||
|
@code trick.var_send_once("<in_name_list>", <number of variables in list>) @endcode
|
||||||
|
@param in_name_list - the variables name to retrieve, comma separated
|
||||||
|
@param num_vars - number of vars in in_name_list
|
||||||
|
@return always 0
|
||||||
|
*/
|
||||||
|
int var_send_once(std::string in_name_list, int num_vars);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief @userdesc Command to instruct the variable server to immediately send back the values of
|
@brief @userdesc Command to instruct the variable server to immediately send back the values of
|
||||||
variables that are registered with the var_add command
|
variables that are registered with the var_add command
|
||||||
@ -369,11 +381,22 @@ namespace Trick {
|
|||||||
*/
|
*/
|
||||||
int copy_sim_data();
|
int copy_sim_data();
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Copy given variable values from Trick memory to each variable's output buffer.
|
||||||
|
cyclical indicated whether it is a normal cyclical copy or a send_once copy
|
||||||
|
*/
|
||||||
|
int copy_sim_data(std::vector<VariableReference *> given_vars, bool cyclical);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Write data in the appropriate format (var_ascii or var_binary) from variable output buffers to socket.
|
@brief Write data in the appropriate format (var_ascii or var_binary) from variable output buffers to socket.
|
||||||
*/
|
*/
|
||||||
int write_data();
|
int write_data();
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Write data from the given var only to the appropriate format (var_ascii or var_binary) from variable output buffers to socket.
|
||||||
|
*/
|
||||||
|
int write_data(std::vector<VariableReference *> var) ;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief gets the send_stdio flag.
|
@brief gets the send_stdio flag.
|
||||||
*/
|
*/
|
||||||
@ -426,9 +449,19 @@ namespace Trick {
|
|||||||
int transmit_file(std::string file_name);
|
int transmit_file(std::string file_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Called by write_data to write data to socket in var_binary format.
|
@brief Called by write_data to write given variables to socket in var_binary format.
|
||||||
*/
|
*/
|
||||||
int write_binary_data( int Start, char *buf1, int PacketNum );
|
int write_binary_data( int Start, char *buf1, const std::vector<VariableReference *>& given_vars, VS_MESSAGE_TYPE message_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Called by write_data to write given variables to socket in var_ascii format.
|
||||||
|
*/
|
||||||
|
int write_ascii_data(char * dest_buf, const std::vector<VariableReference *>& given_vars, VS_MESSAGE_TYPE message_type );
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Construct a variable reference from the string in_name and handle error checking
|
||||||
|
*/
|
||||||
|
VariableReference* create_var_reference(std::string in_name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@brief Make a time reference.
|
@brief Make a time reference.
|
||||||
|
@ -12,7 +12,8 @@ typedef enum {
|
|||||||
VS_VAR_EXISTS = 1,
|
VS_VAR_EXISTS = 1,
|
||||||
VS_SIE_RESOURCE = 2,
|
VS_SIE_RESOURCE = 2,
|
||||||
VS_LIST_SIZE = 3 ,
|
VS_LIST_SIZE = 3 ,
|
||||||
VS_STDIO = 4
|
VS_STDIO = 4,
|
||||||
|
VS_SEND_ONCE = 5
|
||||||
} VS_MESSAGE_TYPE ;
|
} VS_MESSAGE_TYPE ;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -23,11 +23,10 @@ class testSimObject : public Trick::SimObject {
|
|||||||
("default_data") vst.default_vars();
|
("default_data") vst.default_vars();
|
||||||
("initialization") vst.init();
|
("initialization") vst.init();
|
||||||
("initialization") vst.testAddRemove();
|
("initialization") vst.testAddRemove();
|
||||||
|
("initialization") vst.testUnits();
|
||||||
("initialization") vst.testExists();
|
("initialization") vst.testExists();
|
||||||
("initialization") vst.testPause();
|
("initialization") vst.testPause();
|
||||||
("initialization") vst.testOther();
|
("initialization") vst.testSendOnce();
|
||||||
//(1.0, "scheduled") trick_ret = vst.testing();
|
|
||||||
|
|
||||||
("shutdown") vst.shutdown();
|
("shutdown") vst.shutdown();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -11,6 +11,7 @@ PROGRAMMERS: ( (Lindsay Landry) (L3) (9-12-2013) )
|
|||||||
|
|
||||||
#ifndef VS_HH
|
#ifndef VS_HH
|
||||||
#define VS_HH
|
#define VS_HH
|
||||||
|
|
||||||
class VSTest {
|
class VSTest {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -19,13 +20,13 @@ class VSTest {
|
|||||||
char got_read[80];
|
char got_read[80];
|
||||||
double cycle_rate;
|
double cycle_rate;
|
||||||
|
|
||||||
TCDevice bob;
|
TCDevice comm_device;
|
||||||
|
|
||||||
char a;
|
char a;
|
||||||
unsigned char b;
|
unsigned char b;
|
||||||
short c;
|
short c;
|
||||||
unsigned short d;
|
unsigned short d;
|
||||||
int e; /* M xy-position */
|
int e; /* m xy-position */
|
||||||
unsigned int f;
|
unsigned int f;
|
||||||
long g;
|
long g;
|
||||||
unsigned long h;
|
unsigned long h;
|
||||||
@ -34,7 +35,7 @@ class VSTest {
|
|||||||
long long k;
|
long long k;
|
||||||
unsigned long long l;
|
unsigned long long l;
|
||||||
bool m;
|
bool m;
|
||||||
|
int n[5];
|
||||||
|
|
||||||
VSTest();
|
VSTest();
|
||||||
~VSTest();
|
~VSTest();
|
||||||
@ -51,8 +52,8 @@ class VSTest {
|
|||||||
int testAddRemove();
|
int testAddRemove();
|
||||||
int testExists();
|
int testExists();
|
||||||
int testPause();
|
int testPause();
|
||||||
int testOther();
|
int testSendOnce();
|
||||||
int testCycle();
|
int testUnits();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int get_line(char* thing);
|
int get_line(char* thing);
|
||||||
|
@ -41,7 +41,7 @@ int VSTest::vs_write(char* cmd_buffer) {
|
|||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
nbytes = strlen(cmd_buffer);
|
nbytes = strlen(cmd_buffer);
|
||||||
tc_write(&bob, cmd_buffer, nbytes);
|
tc_write(&comm_device, cmd_buffer, nbytes);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
@ -65,16 +65,13 @@ int VSTest::vs_read() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
num = tc_pending(&bob);
|
num = tc_pending(&comm_device);
|
||||||
if (num) {
|
if (num) {
|
||||||
tc_read(&bob, read_buffer, num);
|
tc_read(&comm_device, read_buffer, num);
|
||||||
get_line(read_buffer);
|
get_line(read_buffer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//std::cout << (cpu_t - cpu_st) << std::endl;
|
|
||||||
//std::cout << read_buffer << std::endl;
|
|
||||||
//printLine();
|
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -25,4 +25,7 @@ int VSTest::default_vars() {
|
|||||||
k = -12345678912345;//long long
|
k = -12345678912345;//long long
|
||||||
l = 12345678912345; //unsigned long
|
l = 12345678912345; //unsigned long
|
||||||
m = false; //boolean
|
m = false; //boolean
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
n[i] = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,21 +15,21 @@ int VSTest::init() {
|
|||||||
char msg[256];
|
char msg[256];
|
||||||
|
|
||||||
port_num = var_server_get_port();
|
port_num = var_server_get_port();
|
||||||
hostest = var_server_get_hostname();
|
hostest = "localhost";
|
||||||
|
|
||||||
memset(&bob, '\0', sizeof(TCDevice));
|
memset(&comm_device, '\0', sizeof(TCDevice));
|
||||||
|
|
||||||
bob.hostname = const_cast<char*>(hostest);
|
comm_device.hostname = const_cast<char*>(hostest);
|
||||||
bob.port = port_num;
|
comm_device.port = port_num;
|
||||||
|
|
||||||
//std::cout << bob.hostname << bob.port << std::endl;
|
//std::cout << bob.hostname << bob.port << std::endl;
|
||||||
|
|
||||||
bob.disable_handshaking = TC_COMM_TRUE;
|
comm_device.disable_handshaking = TC_COMM_TRUE;
|
||||||
bob.disabled = TC_COMM_FALSE;
|
comm_device.disabled = TC_COMM_FALSE;
|
||||||
|
|
||||||
tc_connect(&bob);
|
tc_connect(&comm_device);
|
||||||
|
|
||||||
if ( tc_isValid (&bob) ) {
|
if ( tc_isValid (&comm_device) ) {
|
||||||
printf ("connection is valid\n");
|
printf ("connection is valid\n");
|
||||||
} else {
|
} else {
|
||||||
printf ("connection is NOT valid\n");
|
printf ("connection is NOT valid\n");
|
||||||
|
@ -11,7 +11,7 @@ PROGRAMMERS: ( (Lindsay Landry) (L3) (9-12-2013) )
|
|||||||
|
|
||||||
int VSTest::shutdown() {
|
int VSTest::shutdown() {
|
||||||
|
|
||||||
tc_disconnect(&bob);
|
tc_disconnect(&comm_device);
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
@ -33,50 +33,38 @@ int VSTest::strcmp_IgnoringWhiteSpace(const char* s1, const char* s2) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VSTest::testUnits() {
|
||||||
// Expect cycle time of 0.01 s
|
|
||||||
int VSTest::testCycle() {
|
|
||||||
char msg[256];
|
char msg[256];
|
||||||
char suite[] = "VariableServerTest";
|
char suite[] = "VariableServerTest";
|
||||||
/*
|
int result;
|
||||||
int num, num2;
|
|
||||||
double cpu_t, cpu_st;
|
|
||||||
struct rusage cpu_usg;
|
|
||||||
|
|
||||||
sprintf(msg,"trick.var_add(\"vsx.vst.l\")\n");
|
// INVALID UNIT CHANGE
|
||||||
|
sprintf(msg,"trick.var_add(\"vsx.vst.c\")\ntrick.var_units(\"vsx.vst.c\",\"g\")\n");
|
||||||
vs_write(msg);
|
vs_write(msg);
|
||||||
|
std::cerr << "The purpose of this test is to cause an error. Error messages are expected." << std::endl;
|
||||||
|
vs_read();
|
||||||
|
result = strcmp_IgnoringWhiteSpace("0 -1234", got_read);
|
||||||
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableInvalidUnits")
|
||||||
|
|
||||||
// currently bad programming, could get stuck in this loop
|
// ADD UNITS
|
||||||
while (true) {
|
sprintf(msg,"trick.var_add(\"vsx.vst.e\",\"m\")\n");
|
||||||
getrusage(RUSAGE_SELF, &cpu_usg);
|
vs_write(msg);
|
||||||
cpu_st = ((double) cpu_usg.ru_utime.tv_sec) + ((double) cpu_usg.ru_utime.tv_usec/1000000.0);
|
vs_read();
|
||||||
|
result = strcmp_IgnoringWhiteSpace("0 -1234 -123456 {m}", got_read);
|
||||||
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableAddUnits")
|
||||||
|
|
||||||
num = tc_pending(&bob);
|
// CHANGE UNITS
|
||||||
//first read.
|
sprintf(msg,"trick.var_units(\"vsx.vst.e\",\"ft\")\n");
|
||||||
if (num) {
|
vs_write(msg);
|
||||||
break;
|
vs_read();
|
||||||
}
|
result = strcmp_IgnoringWhiteSpace("0 -1234 -405039 {ft}", got_read);
|
||||||
}
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableChangeUnits")
|
||||||
|
|
||||||
while (true) {
|
|
||||||
getrusage(RUSAGE_SELF, &cpu_usg);
|
|
||||||
cpu_t = ((double) cpu_usg.ru_utime.tv_sec) + ((double) cpu_usg.ru_utime.tv_usec/1000000.0);
|
|
||||||
|
|
||||||
num2 = tc_pending(&bob);
|
|
||||||
|
|
||||||
if (num2 == 2*num) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//std::cout << cpu_t - cpu_st << std::endl;
|
|
||||||
|
|
||||||
|
// CLEAR VARIABLE SERVER
|
||||||
sprintf(msg,"trick.var_clear()\n");
|
sprintf(msg,"trick.var_clear()\n");
|
||||||
vs_write(msg);
|
vs_write(msg);
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int VSTest::testAddRemove() {
|
int VSTest::testAddRemove() {
|
||||||
char msg[256];
|
char msg[256];
|
||||||
char suite[] = "VariableServerTest";
|
char suite[] = "VariableServerTest";
|
||||||
@ -89,37 +77,10 @@ int VSTest::testAddRemove() {
|
|||||||
std::cout << got_read << std::endl;
|
std::cout << got_read << std::endl;
|
||||||
result = strcmp_IgnoringWhiteSpace("0 -1234", got_read);
|
result = strcmp_IgnoringWhiteSpace("0 -1234", got_read);
|
||||||
TRICK_EXPECT_EQ(result, 0, suite, "VariableAddNoUnits")
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableAddNoUnits")
|
||||||
trick_test_add_parent( suite , "VariableAddNoUnits" , "3700107028");
|
|
||||||
|
|
||||||
vs_read();
|
vs_read();
|
||||||
result = strcmp_IgnoringWhiteSpace("0 -1234", got_read);
|
result = strcmp_IgnoringWhiteSpace("0 -1234", got_read);
|
||||||
TRICK_EXPECT_EQ(result, 0, suite, "VariableAddCyclic")
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableAddCyclic")
|
||||||
trick_test_add_parent( suite , "VariableAddCyclic" , "3700107028");
|
|
||||||
|
|
||||||
// INVALID UNIT CHANGE
|
|
||||||
sprintf(msg,"trick.var_units(\"vsx.vst.c\",\"g\")\n");
|
|
||||||
vs_write(msg);
|
|
||||||
std::cerr << "The purpose of this test is to cause an error. Error messages are expected." << std::endl;
|
|
||||||
vs_read();
|
|
||||||
result = strcmp_IgnoringWhiteSpace("0 -1234", got_read);
|
|
||||||
TRICK_EXPECT_EQ(result, 0, suite, "VariableInvalidUnits")
|
|
||||||
trick_test_add_parent( suite , "VariableInvalidUnits" , "");
|
|
||||||
|
|
||||||
// ADD UNITS
|
|
||||||
sprintf(msg,"trick.var_add(\"vsx.vst.e\",\"M\")\n");
|
|
||||||
vs_write(msg);
|
|
||||||
vs_read();
|
|
||||||
result = strcmp_IgnoringWhiteSpace("0 -1234 -123456 {M}", got_read);
|
|
||||||
TRICK_EXPECT_EQ(result, 0, suite, "VariableAddUnits")
|
|
||||||
trick_test_add_parent( suite , "VariableAddUnits" , "3700107028");
|
|
||||||
|
|
||||||
// CHANGE UNITS
|
|
||||||
sprintf(msg,"trick.var_units(\"vsx.vst.e\",\"ft\")\n");
|
|
||||||
vs_write(msg);
|
|
||||||
vs_read();
|
|
||||||
result = strcmp_IgnoringWhiteSpace("0 -1234 -405039 {ft}", got_read);
|
|
||||||
TRICK_EXPECT_EQ(result, 0, suite, "VariableChangeUnits")
|
|
||||||
trick_test_add_parent( suite , "VariableChangeUnits" , "2710769246");
|
|
||||||
|
|
||||||
// REMOVE SINGLE VARIABLE
|
// REMOVE SINGLE VARIABLE
|
||||||
sprintf(msg,"trick.var_remove(\"vsx.vst.e\")\n");
|
sprintf(msg,"trick.var_remove(\"vsx.vst.e\")\n");
|
||||||
@ -127,18 +88,45 @@ int VSTest::testAddRemove() {
|
|||||||
vs_read();
|
vs_read();
|
||||||
result = strcmp_IgnoringWhiteSpace("0 -1234", got_read);
|
result = strcmp_IgnoringWhiteSpace("0 -1234", got_read);
|
||||||
TRICK_EXPECT_EQ(result, 0, suite, "VariableRemove")
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableRemove")
|
||||||
trick_test_add_parent( suite , "VariableRemove" , "806750761");
|
|
||||||
|
|
||||||
// CLEAR VARIABLE SERVER
|
// CLEAR VARIABLE SERVER
|
||||||
sprintf(msg,"trick.var_clear()\n");
|
sprintf(msg,"trick.var_clear()\n");
|
||||||
vs_write(msg);
|
vs_write(msg);
|
||||||
vs_read();
|
vs_read();
|
||||||
TRICK_EXPECT_EQ(strcmp(got_read, ""), 0, suite, "VariableClear")
|
TRICK_EXPECT_EQ(strcmp(got_read, ""), 0, suite, "VariableClear")
|
||||||
trick_test_add_parent( suite , "VariableClear" , "835578702");
|
|
||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VSTest::testSendOnce() {
|
||||||
|
char msg[256];
|
||||||
|
char suite[] = "VariableServerTest";
|
||||||
|
int result;
|
||||||
|
|
||||||
|
// SEND ONCE
|
||||||
|
sprintf(msg,"trick.var_send_once(\"vsx.vst.e\")\n");
|
||||||
|
vs_write(msg);
|
||||||
|
vs_read();
|
||||||
|
result = strcmp_IgnoringWhiteSpace("5 -123456", got_read);
|
||||||
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableSendOnce")
|
||||||
|
trick_test_add_parent( suite , "VariableSendOnce" , "");
|
||||||
|
|
||||||
|
// SEND ONCE LIST
|
||||||
|
sprintf(msg,"trick.var_send_once(\"vsx.vst.n[0], vsx.vst.n[1], vsx.vst.n[2],\", 3)\n");
|
||||||
|
vs_write(msg);
|
||||||
|
vs_read();
|
||||||
|
result = strcmp_IgnoringWhiteSpace("5 0 1 2", got_read);
|
||||||
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableSendOnceList")
|
||||||
|
|
||||||
|
// SEND ONCE LIST - WRONG INDICES
|
||||||
|
sprintf(msg,"trick.var_send_once(\"vsx.vst.n[0], vsx.vst.n[1], vsx.vst.n[2],\", 4)\n");
|
||||||
|
vs_write(msg);
|
||||||
|
std::cerr << "The purpose of this test is to cause an error. Error messages are expected." << std::endl;
|
||||||
|
vs_read();
|
||||||
|
result = strcmp_IgnoringWhiteSpace("", got_read);
|
||||||
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableSendOnceListError")
|
||||||
|
}
|
||||||
|
|
||||||
int VSTest::testExists() {
|
int VSTest::testExists() {
|
||||||
char msg[256];
|
char msg[256];
|
||||||
char suite[] = "VariableServerTest";
|
char suite[] = "VariableServerTest";
|
||||||
@ -156,9 +144,9 @@ int VSTest::testExists() {
|
|||||||
sprintf(msg,"trick.var_exists(\"vsx.vst.z\")\n");
|
sprintf(msg,"trick.var_exists(\"vsx.vst.z\")\n");
|
||||||
vs_write(msg);
|
vs_write(msg);
|
||||||
vs_read();
|
vs_read();
|
||||||
|
std::cout << "Check variable doesn't exist: " << got_read << std::endl;
|
||||||
result = strcmp_IgnoringWhiteSpace("1 0",got_read);
|
result = strcmp_IgnoringWhiteSpace("1 0",got_read);
|
||||||
TRICK_EXPECT_EQ(result, 0, suite, "VariableNotExists")
|
TRICK_EXPECT_EQ(result, 0, suite, "VariableNotExists")
|
||||||
trick_test_add_parent( suite , "VariableNotExists" , "3587464751");
|
|
||||||
|
|
||||||
sprintf(msg,"trick.var_clear()\n");
|
sprintf(msg,"trick.var_clear()\n");
|
||||||
vs_write(msg);
|
vs_write(msg);
|
||||||
@ -214,16 +202,3 @@ int VSTest::testPause() {
|
|||||||
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VSTest::testOther() {
|
|
||||||
char msg[256];
|
|
||||||
char suite[] = "VariableServerTest";
|
|
||||||
|
|
||||||
sprintf(msg,"trick.var_binary()\n");
|
|
||||||
vs_write(msg);
|
|
||||||
sprintf(msg,"trick.var_add(\"vsx.vst.l\")\n");
|
|
||||||
vs_write(msg);
|
|
||||||
vs_read();
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
/******************************TRICK HEADER*************************************
|
|
||||||
PURPOSE: ( Test variable server )
|
|
||||||
REFERENCE: ( None )
|
|
||||||
ASSUMPTIONS AND LIMITATIONS: ( None )
|
|
||||||
CLASS: ( scheduled )
|
|
||||||
LIBRARY DEPENDENCY: ( VS.o )
|
|
||||||
PROGRAMMERS: ( (Lindsay Landry) (L3) (9-12-2013) )
|
|
||||||
*******************************************************************************/
|
|
||||||
#include "../include/VS.hh"
|
|
||||||
#include "sim_services/VariableServer/include/VariableServer.hh"
|
|
||||||
#include "sim_services/UnitTest/include/trick_tests.h"
|
|
||||||
|
|
||||||
int VSTest::test() {
|
|
||||||
|
|
||||||
var_ascii();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
@ -36,7 +36,8 @@ SIMS_TO_COMPILE_AND_RUN = \
|
|||||||
SIM_test_sched \
|
SIM_test_sched \
|
||||||
SIM_test_templates \
|
SIM_test_templates \
|
||||||
SIM_threads \
|
SIM_threads \
|
||||||
SIM_trickified
|
SIM_trickified \
|
||||||
|
SIM_test_varserv
|
||||||
|
|
||||||
# Sims with problems, no purpose, or maybe shouldn't be a test
|
# Sims with problems, no purpose, or maybe shouldn't be a test
|
||||||
# SIM_leaks ( should be deleted )
|
# SIM_leaks ( should be deleted )
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include <igl/opengl/glfw/Viewer.h>
|
#include <igl/opengl/glfw/Viewer.h>
|
||||||
// #include <igl/readOFF.h>
|
|
||||||
#include <igl/opengl/glfw/imgui/ImGuiPlugin.h>
|
#include <igl/opengl/glfw/imgui/ImGuiPlugin.h>
|
||||||
#include <igl/opengl/glfw/imgui/ImGuiMenu.h>
|
#include <igl/opengl/glfw/imgui/ImGuiMenu.h>
|
||||||
#include <igl/opengl/glfw/imgui/ImGuiHelpers.h>
|
#include <igl/opengl/glfw/imgui/ImGuiHelpers.h>
|
||||||
@ -13,6 +12,7 @@
|
|||||||
|
|
||||||
#include "Socket.hh"
|
#include "Socket.hh"
|
||||||
|
|
||||||
|
#define STR_MAX 1024
|
||||||
|
|
||||||
std::vector<Eigen::Vector3d> ball_colors = {Eigen::Vector3d(0.0,0.4,0.0), //green
|
std::vector<Eigen::Vector3d> ball_colors = {Eigen::Vector3d(0.0,0.4,0.0), //green
|
||||||
Eigen::Vector3d(1.0,1.0,0.0), //yellow
|
Eigen::Vector3d(1.0,1.0,0.0), //yellow
|
||||||
@ -153,7 +153,7 @@ class Circle : public Polygon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isValid() const {
|
bool isValid() const {
|
||||||
return points.size() == vertexMax;
|
return points.size() == 1 && radius >= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderedShape *render() const {
|
RenderedShape *render() const {
|
||||||
@ -298,14 +298,11 @@ class Table {
|
|||||||
|
|
||||||
// Need to have an agreed upon way to send over variables
|
// Need to have an agreed upon way to send over variables
|
||||||
int addShape(std::vector<double> shapeData, Eigen::Vector3d color, bool isStatic, PolygonType type, double layer) {
|
int addShape(std::vector<double> shapeData, Eigen::Vector3d color, bool isStatic, PolygonType type, double layer) {
|
||||||
// std::cout << "In AddShape" << std::endl;
|
|
||||||
Polygon *shape;
|
Polygon *shape;
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
||||||
case GENERIC: {
|
case GENERIC: {
|
||||||
// Number of points is just data / 2 i guess
|
// Number of points is just data / 2 i guess
|
||||||
// std::cout << "Creating generic polygon with " << shapeData.size()/2 << " points" << std::endl;
|
|
||||||
Polygon *newPolygon = new Polygon(shapeData.size()/2, layer);
|
Polygon *newPolygon = new Polygon(shapeData.size()/2, layer);
|
||||||
for (int i = 0; i < shapeData.size(); i+=2) {
|
for (int i = 0; i < shapeData.size(); i+=2) {
|
||||||
double x = shapeData[i];
|
double x = shapeData[i];
|
||||||
@ -316,7 +313,6 @@ class Table {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CIRCLE: {
|
case CIRCLE: {
|
||||||
// std::cout << "Adding circle" << std::endl;
|
|
||||||
if (shapeData.size() != 3) {
|
if (shapeData.size() != 3) {
|
||||||
std::cout << "Bad shapedata size for circle" << std::endl;
|
std::cout << "Bad shapedata size for circle" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
@ -345,7 +341,6 @@ class Table {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case RECTANGLE: {
|
case RECTANGLE: {
|
||||||
// std::cout << "In rectangle" << std::endl;
|
|
||||||
Rectangle *newRectangle = new Rectangle(layer);
|
Rectangle *newRectangle = new Rectangle(layer);
|
||||||
if (shapeData.size() != 4) {
|
if (shapeData.size() != 4) {
|
||||||
std::cout << "Bad shapedata size for rectangle" << std::endl;
|
std::cout << "Bad shapedata size for rectangle" << std::endl;
|
||||||
@ -481,14 +476,12 @@ class Table {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Polygon *> staticShapes;
|
std::vector<Polygon *> staticShapes;
|
||||||
|
std::vector<Polygon *> movingShapes;
|
||||||
std::vector<RenderedShape *> staticRenderedShapes;
|
std::vector<RenderedShape *> staticRenderedShapes;
|
||||||
std::vector<RenderedShape *> movingRenderedShapes;
|
std::vector<RenderedShape *> movingRenderedShapes;
|
||||||
int numStaticVertices;
|
int numStaticVertices;
|
||||||
int numStaticFaces;
|
int numStaticFaces;
|
||||||
bool staticRendered = false;
|
bool staticRendered = false;
|
||||||
|
|
||||||
std::vector<Polygon *> movingShapes;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void printUsage() {
|
void printUsage() {
|
||||||
@ -505,20 +498,76 @@ std::vector<std::string> split (std::string& str, const char delim) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<double> parseTrickResponse(std::vector<std::string> list) {
|
double totalTime = 0;
|
||||||
std::vector<double> ret;
|
std::vector<double> requestTime;
|
||||||
for (int i = 1; i < list.size(); i++) {
|
|
||||||
ret.push_back(stod(list[i]));
|
template <typename T>
|
||||||
}
|
T stringConvert (const std::string& str)
|
||||||
return ret;
|
{
|
||||||
|
std::istringstream ss(str);
|
||||||
|
T num;
|
||||||
|
ss >> num;
|
||||||
|
return num;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> parseTrickResponseInt(std::vector<std::string> list) {
|
template <typename T>
|
||||||
std::vector<int> ret;
|
std::vector<T> trickResponseConvert (std::string& response)
|
||||||
for (int i = 1; i < list.size(); i++) {
|
{
|
||||||
ret.push_back(stoi(list[i]));
|
auto responseSplit = split(response, '\t');
|
||||||
|
std::vector<T> result;
|
||||||
|
// ignore index 0
|
||||||
|
for (int i = 1; i < responseSplit.size(); i++) {
|
||||||
|
result.push_back(stringConvert<T>(responseSplit[i]));
|
||||||
}
|
}
|
||||||
return ret;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T getVar(Socket& socket, std::string varName) {
|
||||||
|
std::string requestString = "trick.var_send_once(\"" + varName + "\")\n";
|
||||||
|
std::string reply;
|
||||||
|
|
||||||
|
socket << requestString;
|
||||||
|
socket >> reply;
|
||||||
|
|
||||||
|
return stringConvert<T>(split(reply, '\t')[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wrapper for sprintf use case bc im tired of dealing with std::string vs char* stuff
|
||||||
|
std::string format(const std::string& formatString, int num) {
|
||||||
|
char *buf = (char *)malloc(formatString.size() + 10);
|
||||||
|
sprintf(buf, formatString.c_str(), num);
|
||||||
|
|
||||||
|
return std::string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assumes the varName string has a %d in it
|
||||||
|
template <typename T>
|
||||||
|
std::vector<T> getVarList(Socket& socket, std::string varName, int num) {
|
||||||
|
std::string totalRequest = "";
|
||||||
|
std::vector<T> result;
|
||||||
|
totalRequest += format(varName, 0);
|
||||||
|
for (int i = 1; i < num; i++) {
|
||||||
|
totalRequest += ", ";
|
||||||
|
totalRequest += format(varName, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string requestString = "trick.var_send_once(\"" + totalRequest + "\", " + std::to_string(num) + ")\n";
|
||||||
|
|
||||||
|
std::string reply;
|
||||||
|
socket << requestString;
|
||||||
|
socket >> reply;
|
||||||
|
return trickResponseConvert<T>(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::vector<T> fold (const std::vector<T> a, const std::vector<T> b) {
|
||||||
|
std::vector<T> result;
|
||||||
|
for (int i = 0; i < a.size() && i < b.size(); i++) {
|
||||||
|
result.emplace_back (a[i]);
|
||||||
|
result.emplace_back (b[i]);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@ -543,52 +592,19 @@ int main(int argc, char *argv[])
|
|||||||
std::string reply;
|
std::string reply;
|
||||||
|
|
||||||
socket << "trick.var_set_client_tag(\"PoolTableDisplay\") \n";
|
socket << "trick.var_set_client_tag(\"PoolTableDisplay\") \n";
|
||||||
socket << "trick.var_add(\"dyn.table.numBalls\")\ntrick.var_send() \ntrick.var_clear() \n";
|
|
||||||
socket >> reply;
|
|
||||||
|
|
||||||
auto parsed = split(reply, '\t');
|
int numBalls = getVar<int>(socket, "dyn.table.numBalls");
|
||||||
int numBalls = stoi(parsed[1]);
|
// int numBalls = 16;
|
||||||
std::cout << "Number of balls received: " << numBalls << std::endl;
|
std::vector<double> radii = getVarList<double>(socket, "dyn.table.balls[%d][0].radius", numBalls);
|
||||||
|
int numTablePoints = getVar<int>(socket, "dyn.table.numTablePoints");
|
||||||
std::string radiusRequest = "";
|
enum PolygonType tableShape = PolygonType(getVar<int>(socket, "dyn.table.tableShapeType"));
|
||||||
char* templateString = "trick.var_add(\"dyn.table.balls[%d][0].radius\")\n";
|
std::vector<double> table_x = getVarList<double>(socket, "dyn.table.tableShape[%d][0]._x", numTablePoints);
|
||||||
for (int i = 0; i < numBalls; i++) {
|
std::vector<double> table_y = getVarList<double>(socket, "dyn.table.tableShape[%d][0]._y", numTablePoints);
|
||||||
char buf[64];
|
std::vector<double> tablePoints = fold(table_x, table_y);
|
||||||
sprintf(buf, templateString, i);
|
|
||||||
radiusRequest += std::string(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
socket << radiusRequest;
|
|
||||||
socket << "trick.var_send() \ntrick.var_clear() \n";
|
|
||||||
socket >> reply;
|
|
||||||
|
|
||||||
auto radii = parseTrickResponse(split(reply, '\t'));
|
|
||||||
|
|
||||||
Table table;
|
Table table;
|
||||||
|
|
||||||
socket << "trick.var_add(\"dyn.table.numTablePoints\") \ntrick.var_add(\"dyn.table.tableShapeType\")\n \ntrick.var_send() \ntrick.var_clear() \n";
|
|
||||||
socket >> reply;
|
|
||||||
|
|
||||||
std::vector<double> tableData = parseTrickResponse(split(reply, '\t'));
|
|
||||||
int numTablePoints = tableData[0];
|
|
||||||
enum PolygonType tableShape = PolygonType((int)tableData[1]);
|
|
||||||
|
|
||||||
std::string pointRequest = "";
|
|
||||||
for (int i = 0; i < numTablePoints; i++) {
|
|
||||||
templateString = "trick.var_add(\"dyn.table.tableShape[%d][0]._x\")\ntrick.var_add(\"dyn.table.tableShape[%d][0]._y\")\n";
|
|
||||||
char buf[256];
|
|
||||||
sprintf(buf, templateString, i, i);
|
|
||||||
pointRequest += std::string(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
socket << pointRequest;
|
|
||||||
socket << "trick.var_send() \ntrick.var_clear() \n";
|
|
||||||
socket >> reply;
|
|
||||||
|
|
||||||
std::vector<double> tablePoints = parseTrickResponse(split(reply, '\t'));
|
|
||||||
table.addShape(tablePoints, Eigen::Vector3d(0.2, 0.6, 0.2), true, tableShape, layer_TABLE);
|
table.addShape(tablePoints, Eigen::Vector3d(0.2, 0.6, 0.2), true, tableShape, layer_TABLE);
|
||||||
|
|
||||||
|
|
||||||
// Make the rail - translate each point on the table out from center by railWidth
|
// Make the rail - translate each point on the table out from center by railWidth
|
||||||
std::vector<double> railData;
|
std::vector<double> railData;
|
||||||
|
|
||||||
@ -601,12 +617,13 @@ int main(int argc, char *argv[])
|
|||||||
railData.push_back(tablePoints[3] + railWidth);
|
railData.push_back(tablePoints[3] + railWidth);
|
||||||
} else {
|
} else {
|
||||||
// If it's just a shape then rail is bigger shape
|
// If it's just a shape then rail is bigger shape
|
||||||
// Works with simple convex polygons
|
// Works with simple convex polygons centered at 0,0
|
||||||
|
// Could probably calculate center and make it more general but i dont want to
|
||||||
double railWidth = 0.15;
|
double railWidth = 0.15;
|
||||||
for (int i = 0; i < tablePoints.size(); i+=2) {
|
for (int i = 0; i < tablePoints.size(); i+=2) {
|
||||||
Eigen::Vector2d point(tablePoints[i], tablePoints[i+1]);
|
Eigen::Vector2d point(tablePoints[i], tablePoints[i+1]);
|
||||||
Eigen::Vector2d railPoint(tablePoints[i], tablePoints[i+1]);
|
Eigen::Vector2d railPoint(tablePoints[i], tablePoints[i+1]);
|
||||||
point *= railWidth;
|
point = point.normalized() * railWidth;
|
||||||
railPoint = railPoint + point;
|
railPoint = railPoint + point;
|
||||||
railData.push_back(railPoint(0));
|
railData.push_back(railPoint(0));
|
||||||
railData.push_back(railPoint(1));
|
railData.push_back(railPoint(1));
|
||||||
@ -615,82 +632,41 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
table.addShape(railData, Eigen::Vector3d(.3, .2, .15), true, tableShape, layer_RAIL);
|
table.addShape(railData, Eigen::Vector3d(.3, .2, .15), true, tableShape, layer_RAIL);
|
||||||
|
|
||||||
socket << "trick.var_add(\"dyn.table.numPockets\")\n \ntrick.var_send() \ntrick.var_clear() \n";
|
// pockets
|
||||||
socket >> reply;
|
int numPockets = getVar<int>(socket, "dyn.table.numPockets");
|
||||||
|
|
||||||
int numPockets = stoi(split(reply, '\t')[1]);
|
std::vector<double> pocket_x = getVarList<double>(socket, "dyn.table.pockets[%d][0].pos._x", numPockets);
|
||||||
|
std::vector<double> pocket_y = getVarList<double>(socket, "dyn.table.pockets[%d][0].pos._y", numPockets);
|
||||||
|
std::vector<double> pocket_r = getVarList<double>(socket, "dyn.table.pockets[%d][0].radius", numPockets);
|
||||||
for (int i = 0; i < numPockets; i++) {
|
for (int i = 0; i < numPockets; i++) {
|
||||||
templateString = "trick.var_add(\"dyn.table.pockets[%d][0].pos._x\")\ntrick.var_add(\"dyn.table.pockets[%d][0].pos._y\")\n\ntrick.var_add(\"dyn.table.pockets[%d][0].radius\")\n";
|
table.addShape(std::vector<double>({pocket_x[i],pocket_y[i],pocket_r[i]}), Eigen::Vector3d(0.0, 0.0, 0.0), true, CIRCLE, layer_POCKET);
|
||||||
char buf[256];
|
|
||||||
sprintf(buf, templateString, i, i, i);
|
|
||||||
std::string pocketRequest = std::string(buf);
|
|
||||||
|
|
||||||
socket << pocketRequest;
|
|
||||||
socket << "trick.var_send() \ntrick.var_clear() \n";
|
|
||||||
socket >> reply;
|
|
||||||
std::vector<double> pocketData = parseTrickResponse(split(reply, '\t'));
|
|
||||||
table.addShape(pocketData, Eigen::Vector3d(0.0, 0.0, 0.0), true, CIRCLE, layer_POCKET);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bumpers
|
// bumpers
|
||||||
socket << "trick.var_add(\"dyn.table.numBumpers\")\n \ntrick.var_send() \ntrick.var_clear() \n";
|
int numBumpers = getVar<int>(socket, "dyn.table.numBumpers");
|
||||||
socket >> reply;
|
|
||||||
|
|
||||||
int numBumpers = stoi(split(reply, '\t')[1]);
|
|
||||||
|
|
||||||
std::cout << "Num bumpers: " << numBumpers << std::endl;
|
|
||||||
|
|
||||||
for (int i = 0; i < numBumpers; i++) {
|
for (int i = 0; i < numBumpers; i++) {
|
||||||
std::string bumperRequests = "";
|
int numPoints = getVar<int>(socket,format("dyn.table.bumpers[%d][0].numPoints", i));
|
||||||
|
PolygonType bumperShapeType = PolygonType(getVar<int>(socket,format("dyn.table.bumpers[%d][0].shapeType", i)));
|
||||||
|
|
||||||
templateString = "trick.var_add(\"dyn.table.bumpers[%d][0].numPoints\")\ntrick.var_add(\"dyn.table.bumpers[%d][0].shapeType\") \n";
|
std::string request_bumper = format("dyn.table.bumpers[%d][0]", i);
|
||||||
char buf[256];
|
|
||||||
sprintf(buf, templateString, i, i);
|
|
||||||
bumperRequests += std::string(buf);
|
|
||||||
socket << bumperRequests;
|
|
||||||
socket << "trick.var_send() \ntrick.var_clear() \n";
|
|
||||||
socket >> reply;
|
|
||||||
std::vector<int> bumperData = parseTrickResponseInt(split(reply, '\t'));
|
|
||||||
int bumperPoints = bumperData[0];
|
|
||||||
enum PolygonType bumperShape = PolygonType((int)bumperData[1]);
|
|
||||||
|
|
||||||
templateString = "trick.var_add(\"dyn.table.bumpers[%d][0].renderedShape[%d][0]._x\")\ntrick.var_add(\"dyn.table.bumpers[%d][0].renderedShape[%d][0]._y\")\n";
|
std::string request_x = request_bumper + ".renderedShape[%d][0]._x";
|
||||||
bumperRequests = "";
|
std::string request_y = request_bumper + ".renderedShape[%d][0]._y";
|
||||||
for (int j = 0; j < bumperPoints; j++) {
|
|
||||||
char buf[256];
|
std::vector<double> list_x = getVarList<double>(socket, request_x, numPoints);
|
||||||
sprintf(buf, templateString, i, j, i, j);
|
std::vector<double> list_y = getVarList<double>(socket, request_y, numPoints);
|
||||||
bumperRequests += std::string(buf);
|
std::vector<double> bumperBorder = fold(list_x, list_y);
|
||||||
}
|
table.addShape(bumperBorder, Eigen::Vector3d(0.2,0.4,0.2), true, bumperShapeType, layer_BUMPER);
|
||||||
socket << bumperRequests;
|
|
||||||
socket << "trick.var_send() \ntrick.var_clear() \n";
|
|
||||||
socket >> reply;
|
|
||||||
|
|
||||||
std::vector<double> bumperBorder = parseTrickResponse(split(reply, '\t'));
|
|
||||||
table.addShape(bumperBorder, Eigen::Vector3d(0.2,0.4,0.2), true, bumperShape, layer_BUMPER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// socket << "trick.var_pause()\n";
|
|
||||||
// Request all of the ball positions
|
// Request all of the ball positions
|
||||||
std::string positionRequest = "";
|
|
||||||
templateString = "trick.var_add(\"dyn.table.balls[%d][0].pos._x\")\ntrick.var_add(\"dyn.table.balls[%d][0].pos._y\")\n";
|
std::vector<double> ball_x = getVarList<double>(socket, "dyn.table.balls[%d][0].pos._x", numBalls);
|
||||||
|
std::vector<double> ball_y = getVarList<double>(socket, "dyn.table.balls[%d][0].pos._y", numBalls);
|
||||||
for (int i = 0; i < numBalls; i++) {
|
for (int i = 0; i < numBalls; i++) {
|
||||||
char buf[128];
|
|
||||||
sprintf(buf, templateString, i, i);
|
|
||||||
positionRequest += std::string(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
socket << positionRequest;
|
|
||||||
socket << "trick.var_send() \ntrick.var_clear() \n";
|
|
||||||
socket >> reply;
|
|
||||||
|
|
||||||
auto positions = parseTrickResponse(split(reply, '\t'));
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < numBalls; i++) {
|
|
||||||
std::vector<double> circleData = {positions[(i*2)], positions[(i*2 + 1)], radii[i]};
|
|
||||||
Eigen::Vector3d circleColor = ball_colors[i % ball_colors.size()];
|
Eigen::Vector3d circleColor = ball_colors[i % ball_colors.size()];
|
||||||
table.addShape(circleData, circleColor, false, CIRCLE, layer_BALL);
|
table.addShape(std::vector<double>({ball_x[i], ball_y[i], radii[i]}), circleColor, false, CIRCLE, layer_BALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool mousePressed = false;
|
bool mousePressed = false;
|
||||||
@ -740,7 +716,7 @@ int main(int argc, char *argv[])
|
|||||||
view->callback_pre_draw = [&](igl::opengl::glfw::Viewer& viewer) -> bool {
|
view->callback_pre_draw = [&](igl::opengl::glfw::Viewer& viewer) -> bool {
|
||||||
// Look for new data and redraw
|
// Look for new data and redraw
|
||||||
socket >> reply;
|
socket >> reply;
|
||||||
std::vector<double> replyData = parseTrickResponse(split(reply, '\t'));
|
std::vector<double> replyData = trickResponseConvert<double>(reply);
|
||||||
|
|
||||||
if (replyData.size() <= 1) {
|
if (replyData.size() <= 1) {
|
||||||
return false;
|
return false;
|
||||||
@ -824,8 +800,8 @@ int main(int argc, char *argv[])
|
|||||||
// Need to get nBalls and positions every time
|
// Need to get nBalls and positions every time
|
||||||
socket << "trick.var_pause() \n";
|
socket << "trick.var_pause() \n";
|
||||||
socket << "trick.var_add(\"dyn.table.numBalls\")\n";
|
socket << "trick.var_add(\"dyn.table.numBalls\")\n";
|
||||||
positionRequest = "";
|
std::string positionRequest = "";
|
||||||
templateString = "trick.var_add(\"dyn.table.balls[%d][0].pos._x\")\ntrick.var_add(\"dyn.table.balls[%d][0].pos._y\")\ntrick.var_add(\"dyn.table.balls[%d][0].inPlay\")\n";
|
char * templateString = "trick.var_add(\"dyn.table.balls[%d][0].pos._x\")\ntrick.var_add(\"dyn.table.balls[%d][0].pos._y\")\ntrick.var_add(\"dyn.table.balls[%d][0].inPlay\")\n";
|
||||||
for (int i = 0; i < numBalls; i++) {
|
for (int i = 0; i < numBalls; i++) {
|
||||||
char buf[128];
|
char buf[128];
|
||||||
sprintf(buf, templateString, i, i, i);
|
sprintf(buf, templateString, i, i, i);
|
||||||
|
@ -579,7 +579,6 @@ int Trick::DataRecordGroup::data_record(double in_time) {
|
|||||||
bool change_detected = false ;
|
bool change_detected = false ;
|
||||||
|
|
||||||
//TODO: does not handle bitfields correctly!
|
//TODO: does not handle bitfields correctly!
|
||||||
|
|
||||||
if ( record == true ) {
|
if ( record == true ) {
|
||||||
if ( freq != DR_Always ) {
|
if ( freq != DR_Always ) {
|
||||||
for (jj = 0; jj < change_buffer.size() ; jj++) {
|
for (jj = 0; jj < change_buffer.size() ; jj++) {
|
||||||
@ -691,6 +690,7 @@ int Trick::DataRecordGroup::write_data(bool must_write) {
|
|||||||
// buffer_mutex is used in this one place to prevent forced calls of write_data
|
// buffer_mutex is used in this one place to prevent forced calls of write_data
|
||||||
// to not overwrite data being written by the asynchronous thread.
|
// to not overwrite data being written by the asynchronous thread.
|
||||||
pthread_mutex_lock(&buffer_mutex) ;
|
pthread_mutex_lock(&buffer_mutex) ;
|
||||||
|
|
||||||
local_buffer_num = buffer_num ;
|
local_buffer_num = buffer_num ;
|
||||||
if ( (local_buffer_num - writer_num) > max_num ) {
|
if ( (local_buffer_num - writer_num) > max_num ) {
|
||||||
num_to_write = max_num ;
|
num_to_write = max_num ;
|
||||||
|
@ -56,7 +56,7 @@ void Trick::TestSuite::delete_test_results() {
|
|||||||
Trick::UnitTest::UnitTest() {
|
Trick::UnitTest::UnitTest() {
|
||||||
the_unit_test_output = this ;
|
the_unit_test_output = this ;
|
||||||
enabled = false ;
|
enabled = false ;
|
||||||
exit_code_enabled = false ;
|
exit_code_enabled = true ;
|
||||||
file_name = std::string("test_details.xml") ;
|
file_name = std::string("test_details.xml") ;
|
||||||
name = std::string("AllTests") ;
|
name = std::string("AllTests") ;
|
||||||
}
|
}
|
||||||
|
@ -46,17 +46,18 @@ REF2* Trick::VariableServerThread::make_error_ref(std::string in_name) {
|
|||||||
return new_ref;
|
return new_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Trick::VariableServerThread::var_add(std::string in_name) {
|
Trick::VariableReference* Trick::VariableServerThread::create_var_reference(std::string in_name) {
|
||||||
|
|
||||||
VariableReference * new_var ;
|
|
||||||
REF2 * new_ref ;
|
REF2 * new_ref ;
|
||||||
|
|
||||||
|
// Time var is treated specially
|
||||||
if ( in_name.compare("time") == 0 ) {
|
if ( in_name.compare("time") == 0 ) {
|
||||||
new_ref = make_time_ref() ;
|
new_ref = make_time_ref() ;
|
||||||
} else {
|
} else {
|
||||||
|
// otherwise ref_attributes takes care of the hard part
|
||||||
new_ref = ref_attributes(in_name.c_str()) ;
|
new_ref = ref_attributes(in_name.c_str()) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check error cases
|
||||||
if ( new_ref == NULL ) {
|
if ( new_ref == NULL ) {
|
||||||
message_publish(MSG_ERROR, "Variable Server could not find variable %s.\n", in_name.c_str());
|
message_publish(MSG_ERROR, "Variable Server could not find variable %s.\n", in_name.c_str());
|
||||||
new_ref = make_error_ref(in_name);
|
new_ref = make_error_ref(in_name);
|
||||||
@ -81,7 +82,12 @@ int Trick::VariableServerThread::var_add(std::string in_name) {
|
|||||||
new_ref = make_error_ref(in_name);
|
new_ref = make_error_ref(in_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
new_var = new VariableReference(new_ref) ;
|
// Actually constructs the variable reference in the success case
|
||||||
|
return new VariableReference(new_ref) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Trick::VariableServerThread::var_add(std::string in_name) {
|
||||||
|
VariableReference * new_var = create_var_reference(in_name);
|
||||||
vars.push_back(new_var) ;
|
vars.push_back(new_var) ;
|
||||||
|
|
||||||
return(0) ;
|
return(0) ;
|
||||||
@ -93,6 +99,36 @@ int Trick::VariableServerThread::var_add(std::string var_name, std::string units
|
|||||||
return(0) ;
|
return(0) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helper function for var_send_once
|
||||||
|
std::vector<std::string> split (const std::string& str, const char delim) {
|
||||||
|
std::stringstream ss(str);
|
||||||
|
std::string s;
|
||||||
|
std::vector<std::string> ret;
|
||||||
|
while (std::getline(ss, s, delim)) {
|
||||||
|
ret.push_back(s);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Trick::VariableServerThread::var_send_once(std::string in_name, int num_vars) {
|
||||||
|
std::vector<std::string> var_names = split(in_name, ',');
|
||||||
|
|
||||||
|
if (var_names.size() != num_vars) {
|
||||||
|
message_publish(MSG_ERROR, "Number of variables sent to var_send_once (%d) does not match num_vars (%d).\n", var_names.size(), num_vars);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<VariableReference *> given_vars;
|
||||||
|
for (auto& varName : var_names) {
|
||||||
|
given_vars.push_back(create_var_reference(varName));
|
||||||
|
}
|
||||||
|
copy_sim_data(given_vars, false);
|
||||||
|
write_data(given_vars);
|
||||||
|
|
||||||
|
return(0) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int Trick::VariableServerThread::var_remove(std::string in_name) {
|
int Trick::VariableServerThread::var_remove(std::string in_name) {
|
||||||
|
|
||||||
unsigned int ii ;
|
unsigned int ii ;
|
||||||
@ -218,6 +254,7 @@ int Trick::VariableServerThread::var_clear() {
|
|||||||
return(0) ;
|
return(0) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Trick::VariableServerThread::var_send() {
|
int Trick::VariableServerThread::var_send() {
|
||||||
copy_sim_data();
|
copy_sim_data();
|
||||||
write_data();
|
write_data();
|
||||||
|
@ -7,23 +7,24 @@
|
|||||||
#include "trick/exec_proto.h"
|
#include "trick/exec_proto.h"
|
||||||
|
|
||||||
int Trick::VariableServerThread::copy_sim_data() {
|
int Trick::VariableServerThread::copy_sim_data() {
|
||||||
|
return copy_sim_data(vars, true);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int ii ;
|
int Trick::VariableServerThread::copy_sim_data(std::vector<VariableReference *> given_vars, bool cyclical) {
|
||||||
VariableReference * curr_var ;
|
|
||||||
|
|
||||||
if ( vars.size() == 0 ) {
|
if (given_vars.size() == 0) {
|
||||||
return 0 ;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( pthread_mutex_trylock(©_mutex) == 0 ) {
|
if ( pthread_mutex_trylock(©_mutex) == 0 ) {
|
||||||
|
|
||||||
// Get the simulation time we start this copy
|
// Get the simulation time we start this copy
|
||||||
|
if (cyclical) {
|
||||||
time = (double)exec_get_time_tics() / exec_get_time_tic_value() ;
|
time = (double)exec_get_time_tics() / exec_get_time_tic_value() ;
|
||||||
|
}
|
||||||
|
|
||||||
for ( ii = 0 ; ii < vars.size() ; ii++ ) {
|
for (auto curr_var : given_vars ) {
|
||||||
curr_var = vars[ii] ;
|
|
||||||
|
|
||||||
// if this variable is unresolved, try to resolve it
|
|
||||||
if (curr_var->ref->address == &bad_ref_int) {
|
if (curr_var->ref->address == &bad_ref_int) {
|
||||||
REF2 *new_ref = ref_attributes(curr_var->ref->reference);
|
REF2 *new_ref = ref_attributes(curr_var->ref->reference);
|
||||||
if (new_ref != NULL) {
|
if (new_ref != NULL) {
|
||||||
@ -92,14 +93,13 @@ int Trick::VariableServerThread::copy_sim_data() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Indicate that sim data has been written and is now ready in the buffer_in's of the vars variable list.
|
// Indicate that sim data has been written and is now ready in the buffer_in's of the vars variable list.
|
||||||
|
if (cyclical) {
|
||||||
var_data_staged = true;
|
var_data_staged = true;
|
||||||
packets_copied++ ;
|
packets_copied++ ;
|
||||||
|
}
|
||||||
|
|
||||||
pthread_mutex_unlock(©_mutex) ;
|
pthread_mutex_unlock(©_mutex) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
return (0) ;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +179,9 @@ void * Trick::VariableServerThread::thread_body() {
|
|||||||
} catch (...) {
|
} catch (...) {
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#if __GNUC__ == 4 && __GNUC_MINOR__ == 1
|
#if (__GNUC__ == 4 && __GNUC_MINOR__ == 1) || __GNUC__ == 12
|
||||||
//for gcc 4.1.2 or whatever glib version in RHEL 5 that does not work with the abi::__forced_unwind
|
// for gcc 4.1.2 or whatever glib version in RHEL 5 that does not work with the abi::__forced_unwind
|
||||||
|
// Also seems to have a problem with gcc 12
|
||||||
throw;
|
throw;
|
||||||
#else
|
#else
|
||||||
message_publish(MSG_ERROR, "\nVARIABLE SERVER caught unknown exception\n" ) ;
|
message_publish(MSG_ERROR, "\nVARIABLE SERVER caught unknown exception\n" ) ;
|
||||||
|
@ -6,7 +6,6 @@ PROGRAMMERS: (((Alex Lin) (NASA) (8/06) (--)))
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "trick/VariableServer.hh"
|
#include "trick/VariableServer.hh"
|
||||||
#include "trick/variable_server_message_types.h"
|
|
||||||
#include "trick/parameter_types.h"
|
#include "trick/parameter_types.h"
|
||||||
#include "trick/bitfield_proto.h"
|
#include "trick/bitfield_proto.h"
|
||||||
#include "trick/trick_byteswap.h"
|
#include "trick/trick_byteswap.h"
|
||||||
@ -21,7 +20,9 @@ extern "C" {
|
|||||||
|
|
||||||
#define MAX_MSG_LEN 8192
|
#define MAX_MSG_LEN 8192
|
||||||
|
|
||||||
int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, int PacketNum ) {
|
|
||||||
|
int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, const std::vector<VariableReference *>& given_vars, VS_MESSAGE_TYPE message_type) {
|
||||||
|
int vars = 0;
|
||||||
int i;
|
int i;
|
||||||
int ret ;
|
int ret ;
|
||||||
int HeaderSize, MessageSize;
|
int HeaderSize, MessageSize;
|
||||||
@ -32,27 +33,28 @@ int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, int P
|
|||||||
char * address = 0 ;
|
char * address = 0 ;
|
||||||
char* param_name;
|
char* param_name;
|
||||||
|
|
||||||
//remove warning for unused PacketNum... to be deleted.
|
|
||||||
(void)PacketNum ;
|
|
||||||
|
|
||||||
/* start the offset 4 bytes into the message, we'll subtract the sizeof offset at the end */
|
/* start the offset 4 bytes into the message, we'll subtract the sizeof offset at the end */
|
||||||
offset = sizeof(msg_type) + sizeof(offset) ;
|
offset = sizeof(msg_type) + sizeof(offset) ;
|
||||||
|
|
||||||
/* if we are here the msg_type is good, so send a 0, swapped or not 0 is still 0 */
|
if (byteswap) {
|
||||||
msg_type = VS_VAR_LIST ;
|
/* Swap message type bytes */
|
||||||
|
msg_type = trick_byteswap_int((int)message_type) ;
|
||||||
|
} else {
|
||||||
|
msg_type = message_type;
|
||||||
|
}
|
||||||
memcpy(buf1, &msg_type , sizeof(msg_type)) ;
|
memcpy(buf1, &msg_type , sizeof(msg_type)) ;
|
||||||
HeaderSize = sizeof(msg_type);
|
HeaderSize = sizeof(msg_type);
|
||||||
|
|
||||||
offset += sizeof(unsigned int) ;
|
offset += sizeof(unsigned int) ;
|
||||||
HeaderSize += sizeof(unsigned int);
|
HeaderSize += sizeof(unsigned int);
|
||||||
|
|
||||||
for (i = Start; i < (int)vars.size() ; i++) {
|
for (i = Start; i < (int)given_vars.size() ; i++) {
|
||||||
|
|
||||||
// data to send was copied to buffer in copy_sim_data
|
// data to send was copied to buffer in copy_sim_data
|
||||||
address = (char *)vars[i]->buffer_out;
|
address = (char *)given_vars[i]->buffer_out;
|
||||||
size = vars[i]->size ;
|
size = given_vars[i]->size ;
|
||||||
|
|
||||||
param_name = vars[i]->ref->reference;
|
param_name = given_vars[i]->ref->reference;
|
||||||
len = strlen(param_name) ;
|
len = strlen(param_name) ;
|
||||||
// when var_binary_nonames, do not put the variable names into the message to be sent
|
// when var_binary_nonames, do not put the variable names into the message to be sent
|
||||||
if (binary_data_nonames) {
|
if (binary_data_nonames) {
|
||||||
@ -66,7 +68,7 @@ int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, int P
|
|||||||
message_publish(MSG_WARNING, "%p Variable Server buffer[%d] too small (need %d) for symbol %s, SKIPPING IT.\n",
|
message_publish(MSG_WARNING, "%p Variable Server buffer[%d] too small (need %d) for symbol %s, SKIPPING IT.\n",
|
||||||
&connection, MAX_MSG_LEN,
|
&connection, MAX_MSG_LEN,
|
||||||
(int)(HeaderSize + MessageSize),
|
(int)(HeaderSize + MessageSize),
|
||||||
vars[i]->ref->reference );
|
given_vars[i]->ref->reference );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +83,7 @@ int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, int P
|
|||||||
offset += len ;
|
offset += len ;
|
||||||
}
|
}
|
||||||
|
|
||||||
swap_int = trick_byteswap_int(vars[i]->ref->attr->type) ;
|
swap_int = trick_byteswap_int(given_vars[i]->ref->attr->type) ;
|
||||||
memcpy(&buf1[offset] , &swap_int , sizeof(int)) ;
|
memcpy(&buf1[offset] , &swap_int , sizeof(int)) ;
|
||||||
offset += sizeof(int) ;
|
offset += sizeof(int) ;
|
||||||
|
|
||||||
@ -90,7 +92,7 @@ int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, int P
|
|||||||
offset += sizeof(size) ;
|
offset += sizeof(size) ;
|
||||||
|
|
||||||
/* TODO: There is a bug here, this call will want to swap the entire buffer, we may not have the whole buffer */
|
/* TODO: There is a bug here, this call will want to swap the entire buffer, we may not have the whole buffer */
|
||||||
trick_bswap_buffer(&buf1[offset], address, vars[i]->ref->attr, 1);
|
trick_bswap_buffer(&buf1[offset], address, given_vars[i]->ref->attr, 1);
|
||||||
offset += size ;
|
offset += size ;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -105,21 +107,21 @@ int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, int P
|
|||||||
offset += len ;
|
offset += len ;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&buf1[offset] , &vars[i]->ref->attr->type , sizeof(int)) ;
|
memcpy(&buf1[offset] , &given_vars[i]->ref->attr->type , sizeof(int)) ;
|
||||||
offset += sizeof(int) ;
|
offset += sizeof(int) ;
|
||||||
|
|
||||||
memcpy(&buf1[offset] , &size , sizeof(size)) ;
|
memcpy(&buf1[offset] , &size , sizeof(size)) ;
|
||||||
offset += sizeof(size) ;
|
offset += sizeof(size) ;
|
||||||
|
|
||||||
switch ( vars[i]->ref->attr->type ) {
|
switch ( given_vars[i]->ref->attr->type ) {
|
||||||
case TRICK_BITFIELD:
|
case TRICK_BITFIELD:
|
||||||
temp_i = GET_BITFIELD(address , vars[i]->ref->attr->size ,
|
temp_i = GET_BITFIELD(address , given_vars[i]->ref->attr->size ,
|
||||||
vars[i]->ref->attr->index[0].start, vars[i]->ref->attr->index[0].size) ;
|
given_vars[i]->ref->attr->index[0].start, given_vars[i]->ref->attr->index[0].size) ;
|
||||||
memcpy(&buf1[offset] , &temp_i , (size_t)size) ;
|
memcpy(&buf1[offset] , &temp_i , (size_t)size) ;
|
||||||
break ;
|
break ;
|
||||||
case TRICK_UNSIGNED_BITFIELD:
|
case TRICK_UNSIGNED_BITFIELD:
|
||||||
temp_ui = GET_UNSIGNED_BITFIELD(address , vars[i]->ref->attr->size ,
|
temp_ui = GET_UNSIGNED_BITFIELD(address , given_vars[i]->ref->attr->size ,
|
||||||
vars[i]->ref->attr->index[0].start, vars[i]->ref->attr->index[0].size) ;
|
given_vars[i]->ref->attr->index[0].start, given_vars[i]->ref->attr->index[0].size) ;
|
||||||
memcpy(&buf1[offset] , &temp_ui , (size_t)size) ;
|
memcpy(&buf1[offset] , &temp_ui , (size_t)size) ;
|
||||||
break ;
|
break ;
|
||||||
case TRICK_NUMBER_OF_TYPES:
|
case TRICK_NUMBER_OF_TYPES:
|
||||||
@ -176,6 +178,65 @@ int Trick::VariableServerThread::write_binary_data( int Start, char *buf1, int P
|
|||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Trick::VariableServerThread::write_ascii_data(char * dest_buf, const std::vector<VariableReference *>& given_vars, VS_MESSAGE_TYPE message_type ) {
|
||||||
|
|
||||||
|
sprintf(dest_buf, "%d\t", message_type) ;
|
||||||
|
|
||||||
|
for (int i = 0; i < given_vars.size(); i++) {
|
||||||
|
char curr_buf[MAX_MSG_LEN];
|
||||||
|
int ret = vs_format_ascii( given_vars[i] , curr_buf);
|
||||||
|
|
||||||
|
if (ret < 0) {
|
||||||
|
message_publish(MSG_WARNING, "%p Variable Server string buffer[%d] too small for symbol %s, TRUNCATED IT.\n",
|
||||||
|
&connection, MAX_MSG_LEN, given_vars[i]->ref->reference );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure this message will fit in a packet by itself */
|
||||||
|
if( strlen( curr_buf ) + 2 > MAX_MSG_LEN ) {
|
||||||
|
message_publish(MSG_WARNING, "%p Variable Server buffer[%d] too small for symbol %s, TRUNCATED IT.\n",
|
||||||
|
&connection, MAX_MSG_LEN, given_vars[i]->ref->reference );
|
||||||
|
curr_buf[MAX_MSG_LEN - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(dest_buf) ;
|
||||||
|
|
||||||
|
/* make sure there is space for the next tab or next newline and null */
|
||||||
|
if( len + strlen( curr_buf ) + 2 > MAX_MSG_LEN ) {
|
||||||
|
// If there isn't, send incomplete message
|
||||||
|
if (debug >= 2) {
|
||||||
|
message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d ascii bytes:\n%s\n",
|
||||||
|
&connection, connection.client_tag, (int)strlen(dest_buf), dest_buf) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = tc_write(&connection, (char *) dest_buf, len);
|
||||||
|
if ( ret != len ) {
|
||||||
|
return(-1) ;
|
||||||
|
}
|
||||||
|
dest_buf[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(dest_buf, curr_buf);
|
||||||
|
strcat(dest_buf, "\t");
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = strlen(dest_buf) ;
|
||||||
|
|
||||||
|
if ( len > 0 ) {
|
||||||
|
dest_buf[ strlen(dest_buf) - 1 ] = '\n';
|
||||||
|
|
||||||
|
if (debug >= 2) {
|
||||||
|
message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d ascii bytes:\n%s\n",
|
||||||
|
&connection, connection.client_tag, (int)strlen(dest_buf), dest_buf) ;
|
||||||
|
}
|
||||||
|
int ret = tc_write(&connection, (char *) dest_buf, (int)strlen(dest_buf));
|
||||||
|
if ( ret != (int)strlen(dest_buf) ) {
|
||||||
|
return(-1) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int Trick::VariableServerThread::write_data() {
|
int Trick::VariableServerThread::write_data() {
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
@ -185,7 +246,7 @@ int Trick::VariableServerThread::write_data() {
|
|||||||
|
|
||||||
// do not send anything when there are no variables!
|
// do not send anything when there are no variables!
|
||||||
if ( vars.size() == 0 or packets_copied == 0 ) {
|
if ( vars.size() == 0 or packets_copied == 0 ) {
|
||||||
return(0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Acquire sole access to vars[ii]->buffer_in. */
|
/* Acquire sole access to vars[ii]->buffer_in. */
|
||||||
@ -204,77 +265,60 @@ int Trick::VariableServerThread::write_data() {
|
|||||||
pthread_mutex_unlock(©_mutex) ;
|
pthread_mutex_unlock(©_mutex) ;
|
||||||
|
|
||||||
if (binary_data) {
|
if (binary_data) {
|
||||||
int Index = 0;
|
int index = 0;
|
||||||
int PacketNumber = 0;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ret = write_binary_data( Index, buf1, PacketNumber );
|
ret = write_binary_data( index, buf1, vars, VS_VAR_LIST );
|
||||||
if ( ret >= 0 ) {
|
if ( ret >= 0 ) {
|
||||||
Index = ret ;
|
index = ret ;
|
||||||
} else {
|
} else {
|
||||||
return(-1) ;
|
return(-1) ;
|
||||||
}
|
}
|
||||||
PacketNumber++;
|
} while( index < (int)vars.size() );
|
||||||
} while( Index < (int)vars.size() );
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
} else { /* ascii mode */
|
} else { /* ascii mode */
|
||||||
char val[MAX_MSG_LEN];
|
return write_ascii_data(buf1, vars, VS_VAR_LIST );
|
||||||
|
}
|
||||||
sprintf(buf1, "0\t") ;
|
}
|
||||||
|
}
|
||||||
for (i = 0; i < vars.size(); i++) {
|
|
||||||
|
int Trick::VariableServerThread::write_data(std::vector<VariableReference *> given_vars) {
|
||||||
ret = vs_format_ascii( vars[i] , val);
|
// do not send anything when there are no variables!
|
||||||
|
if ( given_vars.size() == 0) {
|
||||||
if (ret < 0) {
|
return(0);
|
||||||
message_publish(MSG_WARNING, "%p Variable Server string buffer[%d] too small for symbol %s, TRUNCATED IT.\n",
|
}
|
||||||
&connection, MAX_MSG_LEN, vars[i]->ref->reference );
|
|
||||||
}
|
/* Acquire sole access to vars[ii]->buffer_in. */
|
||||||
|
if ( pthread_mutex_trylock(©_mutex) == 0 ) {
|
||||||
/* make sure this message will fit in a packet by itself */
|
// Swap buffer_in and buffer_out for each vars[ii].
|
||||||
if( strlen( val ) + 2 > MAX_MSG_LEN ) {
|
for (int i = 0 ; i < given_vars.size() ; i++ ) {
|
||||||
message_publish(MSG_WARNING, "%p Variable Server buffer[%d] too small for symbol %s, TRUNCATED IT.\n",
|
void *temp_p = given_vars[i]->buffer_in;
|
||||||
&connection, MAX_MSG_LEN, vars[i]->ref->reference );
|
given_vars[i]->buffer_in = given_vars[i]->buffer_out;
|
||||||
val[MAX_MSG_LEN - 1] = '\0';
|
given_vars[i]->buffer_out = temp_p;
|
||||||
}
|
}
|
||||||
|
/* Relinquish sole access to vars[ii]->buffer_in. */
|
||||||
len = strlen(buf1) ;
|
pthread_mutex_unlock(©_mutex) ;
|
||||||
|
|
||||||
/* make sure there is space for the next tab or next newline and null */
|
char buf1[ MAX_MSG_LEN ];
|
||||||
if( len + strlen( val ) + 2 > MAX_MSG_LEN ) {
|
|
||||||
|
if (binary_data) {
|
||||||
if (debug >= 2) {
|
int index = 0;
|
||||||
message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d ascii bytes:\n%s\n",
|
|
||||||
&connection, connection.client_tag, (int)strlen(buf1), buf1) ;
|
do {
|
||||||
}
|
int ret = write_binary_data( index, buf1, given_vars, VS_SEND_ONCE );
|
||||||
|
if ( ret >= 0 ) {
|
||||||
ret = tc_write(&connection, (char *) buf1, len);
|
index = ret ;
|
||||||
if ( ret != len ) {
|
} else {
|
||||||
return(-1) ;
|
return(-1) ;
|
||||||
}
|
}
|
||||||
buf1[0] = '\0';
|
} while( index < (int)given_vars.size() );
|
||||||
}
|
|
||||||
|
return 0;
|
||||||
strcat(buf1, val);
|
|
||||||
strcat(buf1, "\t");
|
} else { /* ascii mode */
|
||||||
}
|
return write_ascii_data(buf1, given_vars, VS_SEND_ONCE);
|
||||||
|
|
||||||
len = strlen(buf1) ;
|
|
||||||
|
|
||||||
if ( len > 0 ) {
|
|
||||||
buf1[ strlen(buf1) - 1 ] = '\n';
|
|
||||||
|
|
||||||
if (debug >= 2) {
|
|
||||||
message_publish(MSG_DEBUG, "%p tag=<%s> var_server sending %d ascii bytes:\n%s\n",
|
|
||||||
&connection, connection.client_tag, (int)strlen(buf1), buf1) ;
|
|
||||||
}
|
|
||||||
ret = tc_write(&connection, (char *) buf1, (int)strlen(buf1));
|
|
||||||
if ( ret != (int)strlen(buf1) ) {
|
|
||||||
return(-1) ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,24 @@ int var_exists(std::string in_name) {
|
|||||||
return(0) ;
|
return(0) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int var_send_once(std::string in_name) {
|
||||||
|
Trick::VariableServerThread * vst ;
|
||||||
|
vst = get_vst() ;
|
||||||
|
if (vst != NULL ) {
|
||||||
|
vst->var_send_once(in_name, 1) ;
|
||||||
|
}
|
||||||
|
return(0) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
int var_send_once(std::string in_name, int num) {
|
||||||
|
Trick::VariableServerThread * vst ;
|
||||||
|
vst = get_vst() ;
|
||||||
|
if (vst != NULL ) {
|
||||||
|
vst->var_send_once(in_name, num) ;
|
||||||
|
}
|
||||||
|
return(0) ;
|
||||||
|
}
|
||||||
|
|
||||||
int var_send() {
|
int var_send() {
|
||||||
Trick::VariableServerThread * vst ;
|
Trick::VariableServerThread * vst ;
|
||||||
vst = get_vst() ;
|
vst = get_vst() ;
|
||||||
|
Loading…
Reference in New Issue
Block a user