Nested Structure IDL

8 posts / 0 new
Last post
Offline
Last seen: 8 years 1 month ago
Joined: 07/22/2014
Posts: 9
Nested Structure IDL

Hi,

This is my first attempt in using rtiddsgen to generate code by using IDL as input file.

I had attached my IDL file here, but not sure whether i had typed correctly in terms of syntax.

Im still confused about setting key to datatype after reading the knowledge base.

Portion of the auto-generated code:

 
static DDS_TypeCode_Member Hums_PBit_Info_T_g_tc_members[4]=
	{
		{
			(char *)"resourceId",/* Member name */
			{
			0,/* Representation ID */
			DDS_BOOLEAN_FALSE,/* Is a pointer? */
			-1, /* Bitfield bits */
			NULL/* Member type code is assigned later */
		},
		0, /* Ignored */
		0, /* Ignored */
		0, /* Ignored */
		NULL, /* Ignored */
		RTI_CDR_KEY_MEMBER, /* Member flags */
		DDS_PRIVATE_MEMBER,/* Ignored */
		1,
		NULL/* Ignored */
	};

............

resourceId should be IdentifierType_T datatype as stated in my IDL file, but code stated char *

Appreciate if someone can enlighten me.

AttachmentSize
Binary Data sample.idl2.03 KB
Gerardo Pardo's picture
Offline
Last seen: 11 hours 44 min ago
Joined: 06/02/2010
Posts: 601

Hi Jeslene,

The IDL is correct as far as syntax. The resourceId is indeed a  IdentifierType_T datatype as you said. This can be seen in the generated header file sample.h (see below).

// This appears in the sample.h file:

 typedef struct Hums_PBit_Info_T {
    IdentifierType_T   resourceId ;
    HumsHealthBIT_E   result ;
    String500_T   extendedResult ;
    VsiTime_T   timeOfDataGeneration ;
} Hums_PBit_Info_T ;

The code you referenced from the sample.c file:

static DDS_TypeCode_Member Hums_PBit_Info_T_g_tc_members[4]=
...

Is used con construct a runtime description of the type used for internal purposes. You do not need to be concerned by that syntax. It is not intended for you to use it directly. If you are curious what is saying there is that there is a member with name "resourceId" that has a number of properties among which the fact that it is a "key" member... But you should ignore this syntax and just look at the declaration itself in the file sample.h

Inspecting the rest of the IDL file I did find a couple things that seemed unnecessay or perhaps even undesirable.

1) The combination of a typedef and struct declaration is not needed in IDL. Therefore the IDL declaration:

typedef struct tag_VsiTime_T {	
	long long	seconds; 
	unsigned long	nanoseconds; 
} VsiTime_T;	

Can be replaced with the simpler one:

struct VsiTime_T {	
	long long	seconds; 
	unsigned long	nanoseconds; 
};	

The C/C++ code generation from this latter version will already define both the type VsiTime_T as well as the type struct VsiTime_T. So the more complex IDL syntax of the top variation is not needed and may not work on other IDL compilers.

2) The inclusion of the members with type VsiTime_T as part of the "key" for the corresponding type seems odd to me. For example you have defined the following two types:

//Topic Name
struct Hums_PBit_Info_T {	
	IdentifierType_T        resourceId;   //@key
	HumsHealthBIT_E    	result;
	String500_T             extendedResult;
	VsiTime_T               timeOfDataGeneration;  //@key
};	

//Topic Name
struct Hums_Bit_Info_T {	
	IdentifierType_T         resourceId;  //@key
	HumsHealthBIT_E          result;
	String500_T              extendedResult;
	VsiTime_T                timeOfDataGeneration;  //@key
};

I understand that the IdentifierType_T would form part of the key as this looks like the kind of member that would uniquely identify a data source or some specific object in your system. However the VsiTime_T is a timestamp so it would seem like it represents a snapshot of the value of the object. Since this it identifies a particular sample (value at a point in time) but nor the object itself it does not (generally) make sense to make it part of the key. Thus it would seem more natural to define the type as:

//Topic Name
struct Hums_PBit_Info_T {	
	IdentifierType_T        resourceId;   //@key
	HumsHealthBIT_E    	result;
	String500_T             extendedResult;
	VsiTime_T               timeOfDataGeneration;  
};	

3) It seems odd that the types Hums_PBit_Info_T, Hums_Bit_Info_T and IBit_Info_T are all identical. From the comments it looks like you want these to be Topics. Note that it is OK to have multiple Topic names with the same data-type...

Just like on a programming language you can have multiple variables of the same data type, in DDS you can have multiple Topics (and multiple DataWriters and DataReaders) of the same data type. Since the Topic is different these will still be kept independent. Reusing the type saves a lot of code generation and generally also makes the code more reusable and simpler to maintain. The reasoning for this is explained in the best practice named Don't force Topic names to be the same as Type names.

 -Gerardo

Offline
Last seen: 8 years 1 month ago
Joined: 07/22/2014
Posts: 9

Hi Gerado,

Your explanation is great, i have a better understanding now. I had managed to write simple publishing and subscribing codes based on the sample.idl. It works perfectly. Thanks a lot.

Thanks & Regards,

Jeslene

Offline
Last seen: 8 years 1 month ago
Joined: 07/22/2014
Posts: 9

Hi Gerado,

I got another question here:

I created nested structures in .IDL with 2 topic names Hums_PBit_Info_T & Hums_Parameter_Info_T

typedef string<500> String500_T;
typedef string<50> String50_T;

enum ResourceType_E {
	RESOURCE_TYPE__APPLICATION,
	RESOURCE_TYPE__BRAKE,
	RESOURCE_TYPE__CREWSTATION,
	RESOURCE_TYPE__ACOUSTIC,
	RESOURCE_TYPE__CAMERA
};

enum HumsHealthBIT_E {
	HUMS_HEALTH_BIT__GOOD,
	HUMS_HEALTH_BIT__SERVICE,
	HUMS_HEALTH_BIT__WARNING,
	HUMS_HEALTH_BIT__DEGRADED,
	HUMS_HEALTH_BIT__FAILED
};

typedef struct tag_VsiTime_T { 
	long long seconds; 
	unsigned long nanoseconds; 
}VsiTime_T;

typedef struct tag_IdentifierType_T { 
	long id; 
	ResourceType_E idType; 
}IdentifierType_T;

struct Hums_PBit_Info_T { 
	IdentifierType_T resourceId; 
	HumsHealthBIT_E result;
	String500_T extendedResult;
	VsiTime_T timeOfDataGeneration; 
};

struct Hums_Parameter_Info_T { 
	IdentifierType_T resourceId; 
	String50_T parameterId;
	double value;
	VsiTime_T timeOfDataGeneration; 
};
 

After writing publishing codes as below, my subscription software can receive the data. And from admin console, i can see the datatype of topic Hums_Parameter_Info_T.

However, if i change the code to use topic Hums_PBit_Info_T, my subscribing software is not receiving any data and at admin console i cannot see any datatype of topic Hums_PBit_Info_T.

I understand that i can have multiple writers in 1 publisher and multiple readers in 1 subscriber (which i already coded). Im just doing a quick code change and check as the prior is also not reading my Hums_PBit_Info_T too.

I had spent hours on it but cannot find what i did wrong.

 

Thanks & Regards,

Jeslene

Offline
Last seen: 8 years 1 month ago
Joined: 07/22/2014
Posts: 9

Hi Gerado,

By the way, my publishing codes as follows:

public class Hums_Publisher
{

    public static void Main(string[] args)
    {

        // --- Get domain ID --- //
        int domain_id = 0;
        if (args.Length >= 1)
        {
            domain_id = Int32.Parse(args[0]);
        }

        // --- Get max loop count; 0 means infinite loop --- //
        int sample_count = 0;
        if (args.Length >= 2)
        {
            sample_count = Int32.Parse(args[1]);
        }

        // --- Run --- //
        try
        {
            Hums_Publisher.publish(
                domain_id, sample_count);
        }
        catch (DDS.Exception)
        {
            Console.WriteLine("error in publisher");
        }
    }

    static void publish(int domain_id, int sample_count)
    {

        // --- Create participant --- //

        DDS.DomainParticipant participant =
        DDS.DomainParticipantFactory.get_instance().create_participant(
            domain_id,
            DDS.DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT,
            null /* listener */,
            DDS.StatusMask.STATUS_MASK_NONE);
        if (participant == null)
        {
            shutdown(participant);
            throw new ApplicationException("create_participant error");
        }

        // --- Create publisher --- //

        DDS.Publisher publisher = participant.create_publisher(
            DDS.DomainParticipant.PUBLISHER_QOS_DEFAULT,
            null /* listener */,
            DDS.StatusMask.STATUS_MASK_NONE);
        if (publisher == null)
        {
            shutdown(participant);
            throw new ApplicationException("create_publisher error");
        }

        // --- Create topic --- //

        /* Register type before creating topic */
        System.String type_name = Hums_Parameter_Info_TTypeSupport.get_type_name();
        try
        {
            Hums_Parameter_Info_TTypeSupport.register_type(
            participant, type_name);
        }
        catch (DDS.Exception e)
        {
            Console.WriteLine("register_type error {0}", e);
            shutdown(participant);
            throw e;
        }

        DDS.Topic topic = participant.create_topic(
            "Example Hums_Parameter_Info_T",
            type_name,
            DDS.DomainParticipant.TOPIC_QOS_DEFAULT,
            null /* listener */,
            DDS.StatusMask.STATUS_MASK_NONE);
        if (topic == null)
        {
            shutdown(participant);
            throw new ApplicationException("create_topic error");
        }

        // --- Create writer --- //

        DDS.DataWriter writer = publisher.create_datawriter(
            topic,
            DDS.Publisher.DATAWRITER_QOS_DEFAULT,
            null /* listener */,
            DDS.StatusMask.STATUS_MASK_NONE);
        if (writer == null)
        {
            shutdown(participant);
            throw new ApplicationException("create_datawriter error");
        }
        Hums_Parameter_Info_TDataWriter Hums_Parameter_Info_T_writer =
            (Hums_Parameter_Info_TDataWriter)writer;

        // --- Write --- //

        /* Create data sample for writing */
        Hums_Parameter_Info_T instance = Hums_Parameter_Info_TTypeSupport.create_data();
        if (instance == null)
        {
            shutdown(participant);
            throw new ApplicationException(
            "Hums_Parameter_Info_TTypeSupport.create_data error");
        }

        DDS.InstanceHandle_t instance_handle = DDS.InstanceHandle_t.HANDLE_NIL;

        /* Main loop */
        const System.Int32 send_period = 4000; // milliseconds
        for (int count = 0;
           (sample_count == 0) || (count < sample_count);
           ++count)
        {
            Console.WriteLine("Writing Hums_Parameter_Info_T, count {0}", count);

            /* My Data */
            instance.resourceId.id = 2;
            instance.resourceId.idType = ResourceType_E.RESOURCE_TYPE__BATTERY;
            //instance.result = HumsHealthBIT_E.HUMS_HEALTH_BIT__GOOD; 
            //instance.extendedResult = "Hello there";
            instance.parameterId = "Para_1";
            instance.value = 40;
            instance.timeOfDataGeneration.nanoseconds = 333;
            instance.timeOfDataGeneration.seconds = 12;
            //

            try
            {
                Hums_Parameter_Info_T_writer.write(instance, ref instance_handle);
            }
            catch (DDS.Exception e)
            {
                Console.WriteLine("write error {0}", e);
            }

            System.Threading.Thread.Sleep(send_period);
        }
    }
}

..........

Thanks & Regards,

Jeslene

Gerardo Pardo's picture
Offline
Last seen: 11 hours 44 min ago
Joined: 06/02/2010
Posts: 601

Hi Jeslene,

I suspect you made an error when you changed the type from Hums_Parameter_Info_T to Hums_PBit_Info_T. Perhaps on one of the two sides (publish or subscribe) you did not change the Topic name passed to the  create_topic() call. Of the type name passed to the register_type() call.

If you run AdminConsole anf open the "Match Graph" you should be able to see the Topic names and types being published and subscribed and troubleshoot why they do not match.

I tested your IDL and the change from Hums_Parameter_Info_T to Hums_PBit_Info_T. I was able to change the type and see the new applications communicate as expected. I have uploaded a ZIP file to the FileExchange with a C# example that modifies what rtiddsgen created from your IDL. You can download it from here: https://community.rti.com/filedepot?cid=1&fid=34.  In the comments you can see what I changed) and these work as expected. take a look at them and maybe it can help you find what you missed...

On a different subject. This discussion is more appropriate for the dds community forums instead of the HOWTOs. The HOWTOs were intended for posting informal worked-out recipes/solutions to common problems/challenges... Because of this some posting features are limited (e.g. uploading files). Also the interface is not as well suited to having a dialog... Putting it in the forum will also help other members of the community find it.  I have asked the RTI community admins to move this discussion from the HOWTO to the forums. Hopefully no information will be lost. I wanted to let you know so you are not susprised by the change.

Regards,

Gerardo

Update: On  November 5, 2015 this discussion was moved from the HOWTO to the Technical forum.

Offline
Last seen: 8 years 1 month ago
Joined: 07/22/2014
Posts: 9

Hi Gerado,

Thanks for the code. I know where i made the mistake. 

Noted on your comments on where i should post my queries. Sorry for the trouble.

 

Gerardo Pardo's picture
Offline
Last seen: 11 hours 44 min ago
Joined: 06/02/2010
Posts: 601

No worries :)   I am glad you figured it all out!!

Gerardo