Complex types in RTI Prototyper with LUA

14 posts / 0 new
Last post
Offline
Last seen: 4 years 3 months ago
Joined: 06/13/2014
Posts: 3
Complex types in RTI Prototyper with LUA

Hi all,

I am attempting to use the RTI Prototyper with LUA to test message receivers without having to get the senders configured and running and to have greater control of the data being published.  Everything seems to be working well for simple messages that just contain basic data types. But, a few of the messages contain structs, sequences, etc. that I have so far been unable to publish without error.

A sample of what I'm trying to do in the LUA script:
local memberStruct = {}
baseStruct['d'] = 123.45
baseStruct['i'] = 12345
baseStruct['s'] = "12345"

local memberSeq = {}
for i=1,3 do
  memberSeq['str[i]'] = "This is string " .. i
end

local writer = CONTAINER.WRITER["MyMessagePublisher::MyMessage"]
writer.instance['name']="Name of the message"
writer.instance['data']=memberStruct
writer.instance['strings']=memberSeq
writer:write()

For any message member that gets set to a complex type, I receive the following output:
<-- BOTTOM | table | 'memberSeq' | table | userdata | <-- TOP
RTILuaDynamicData_set:not a primitive type

Does the prototyper support complex data types?  If so, am I just missing the correct syntax in the creation of the message data?

Thanks for any help,

Phil

 

gianpiero's picture
Offline
Last seen: 10 months 1 week ago
Joined: 06/02/2010
Posts: 177

*** EDIT ***

Hello Phil,

Yes: Prototyper with Lua supports complex data types!

I think what you are trying to do is to create a lua table and then assign the content of that value to a single field of the DDS instance. That is not possible yet. You can only set primitive filed of the DDS Type one by one. 

So, the memberSeq cannot be a lua table but has to be the sample you want to send.

The problem is how you are accessing the sequence: you have 'str[i]' as a string.. so i does not get evaluated in the loop.. it just stays as the string i. 

What you have to do is something like:

local instance = writer.instance
for i=1,3 do
  local tmp = 'memberSeq[' .. i .. ']'
  instance[tmp] = "This is string " .. i
end
writer:write() 

 

Whay I am doing is constructig a string called tmp that will be 

  • memberSeq[1]
  • memberSeq[2]
  • memberSeq[3]

depending on the value of i. The i use that string to access the complex type

Does it make sense?

We are coming up with a better way to do this, but in the version you are using is not available yet.

Does it make sense? Did I solve your issue? Please let me know!

Regards,
  Gianpiero

Offline
Last seen: 4 years 3 months ago
Joined: 06/13/2014
Posts: 3

Yes, that makes sense and I've been able to successfully test a small sequence.  It will be a little more work (especially for more complicated structures such as structs of structs), but it's good to know that it can be done.

Thank you very much

Offline
Last seen: 8 years 6 months ago
Joined: 08/15/2014
Posts: 7

I have somewhat of a followup question to eversp's post..

I have a structure defined in IDL which I'm trying to use/publish with prototyper. It contains a sequence - when I publish this structure using prototyper I can see via ddsspy that the sequence is empty. Via the LUA I can change the data for the basic data type fields no problem, however, I can't seem to find valid syntax to do the equivalent of the userdata.add method I'd call if I were trying to add data in C++/Java. Thanks in advance for any insight!

Gerardo Pardo's picture
Offline
Last seen: 3 weeks 5 hours ago
Joined: 06/02/2010
Posts: 602

Hi,

I think the answer is similar to the one Gianpiero posted. First you have to construct a Lua string with the correct syntax, and then use it to index into the Table that represents the data-sample the DataWriter uses when it writes.

Can you post a representative example of your IDL? That way we may be able to suggest the concrete syntax to use.

Gerardo

Offline
Last seen: 8 years 6 months ago
Joined: 08/15/2014
Posts: 7

Sure!

So given some IDL like this:

const unsigned long MAX_SIZE_EVENTS = 200;

typedef sequence < EventStruct, MAX_SIZE_EVENTS > EventSequence;

struct EventMessage {

CommonHeader msgHeader;

long sysId;

EventSequence events;

};

struct EventStruct {

boolean fooEnabled;

int foo;

int bar;

};


I've configured a writer with EventMessage as the datatype in the prototyper configuration XML. In my LUA script I'm doing something like this:

eventWriter = CONTAINER.WRITER['MyPublisher::EventWriter']

myEventMsg = eventWriter.instance

I don't care about dynamically incrementing the index into the sequence, I'm just trying to insert one EventStruct into the sequence so I tried to do the following:

myEventMsg['events[1].fooEnabled'] = false

and then when that didn't work, I tried:

event = ['events[1]']

myEventMsg[event .. '.fooEnabled'] = false

I'd have to go back and check my logs, but I expected both of these to do pretty much the same thing and I believe I got a message in the rti.log informing me that events was nil. Seemed to make sense based on what I was seeing published in ddsspy.

Then just for the heck of it I tried:

myEventMsg['events#length'] = 1


Hoping that might initialze an empty EventStruct in index 1 of the sequence but again I got an error.
I'm probably missing something very basic here. Thank you again for your assistance!

 

Offline
Last seen: 4 years 3 months ago
Joined: 06/13/2014
Posts: 3

Hi ericmcd81,

In your message, there is only one 'events' field.  The 'fooEnabled', 'foo', and 'bar' struct members are the data that can have multiple instances.  So, in order to set up the message, it looks like it should be

myEventMsg['events.fooEnabled[1]']=false

Hope that helps.

Offline
Last seen: 8 years 6 months ago
Joined: 08/15/2014
Posts: 7

Ok will give it a shot. I was thinking that since events is the actual sequence, I needed to do the indexing there. Thank you!

Offline
Last seen: 8 years 6 months ago
Joined: 08/15/2014
Posts: 7

So I might have misrepresented my IDL slightly. Below is a more appropriate example:

const unsigned long MAX_SIZE_EVENTS = 200;

typedef sequence < EventStruct, MAX_SIZE_EVENTS > EventSequence;

struct EventMessage {

CommonHeader msgHeader;

long sysId;

EventSequence events;

};

struct EventStruct {

SpecificSystemStruct sysStruct;

};

struct SpecficSystemStruct {

boolean fooEnabled;

int bar;

int foo;

};

As per eversp's suggestion I tried:

myEventMsg[events.sysStruct[1].fooEnabled] = 1

However, this produced the following errors in the rti.log:

DDS_DynamicData_bind_complex_member:field asParams (id=0) not found

DDS_DynamicData_autoBindAndExecuteOperation:invalid operaion, bound to member id 1

DDS_DynamicData_autoBindAndExecuteOperation:field sysStruct[1].fooEnabled (id=1) not found

RTILuaDynamicData_set:!get kind failed for 'events.sysStruct[1].fooEnabled'

It looks to me that the sequence has not been properly initalized and that I need to take some other step to prep the sequence before I can actually set any field values.. i.e. perform an add, etc

 

gianpiero's picture
Offline
Last seen: 10 months 1 week ago
Joined: 06/02/2010
Posts: 177

Hi,

So i tried to convert your IDL into xml using rtinddsgen and I was getting some errors.. but anyway I created this example that should be similar to yours. Please use this xml: http://community.rti.com/sites/default/files/users/gianpiero/simple.xml and this lua file: http://community.rti.com/sites/default/files/users/gianpiero/file.lua

run with 

rtiddsprototyper -cfgFile Simple.xml -luaFile file.lua

let me know 

best,
  Gianpiero

Offline
Last seen: 8 years 6 months ago
Joined: 08/15/2014
Posts: 7

Gianpiero - Thank you!

Your example works as expected. So I went back to my code to compare -  I think maybe I was referencing some fields incorrectly as I rewrote the section of my Lua script based on your examples. Appreciate the help from everyone.

gianpiero's picture
Offline
Last seen: 10 months 1 week ago
Joined: 06/02/2010
Posts: 177

Eric

I am glad I could help! Let me know if you need more help..

As a personal couriosity, how are you using Lua for your project?

Best,
  Gianpiero

Offline
Last seen: 8 years 6 months ago
Joined: 08/15/2014
Posts: 7

We're using prototyper with LUA to simulate the output of a piece of software that's still under development. We're concurrently developing another component that's processing that output and prototyper is making much easier to exercise the interface in question.

Eric

 

 

gianpiero's picture
Offline
Last seen: 10 months 1 week ago
Joined: 06/02/2010
Posts: 177

Eric,

Thanks for the explanation: I am glad Prototyper with Lua is making the difference.

Let me know if you have more questions! 

Regards,
  Gianpiero