Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Creation of one connector blocking another? #127

Closed
aris-t opened this issue Feb 17, 2022 · 5 comments
Closed

Creation of one connector blocking another? #127

aris-t opened this issue Feb 17, 2022 · 5 comments
Assignees

Comments

@aris-t
Copy link

aris-t commented Feb 17, 2022

Interesting case where creating one DDS reader appears to block the reading ability of another? If the creation of the first is commented out the second will receive messages. Holding off on XML unless necessary. Have confirmed both connectors will be created and operate independently so doubt it is an XML issue.

connectors.py

def ddsReader(subscriberType,readerType):
    DDS_config = "DomainParticipantLibrary::DomainParticipant"
    DDS_xml = "./myQOS.xml"
    connector=rti.Connector(config_name=DDS_config,url=DDS_xml)
    dds_reader = connector.get_input(f"{subscriberType}::{readerType}")
    return dds_reader

invoke.py

from connectors import ddsReader
A_Listener = ddsReader("Subscriber","TopicAReader")
B_Listener = ddsReader("Subscriber","TopicBReader")

while True:
    A_Listener.take()
    for sample in A_Listener.samples.valid_data_iter:
        print(sample)

    B_Listener.take() # Never gets sample if A_Listener is created first
    for sample in B_Listener.samples.valid_data_iter:
        print(sample)
@samuelraeburn
Copy link
Collaborator

samuelraeburn commented Feb 17, 2022

Hey,

I just ran a quick test and cannot reproduce your behaviour. I modified the simple example shipped with Connector to contain two readers (MySquareReader1 and MySquareReader2):

        <domain_participant name="MySubParticipant" domain_ref="MyDomainLibrary::MyDomain">
            <subscriber name="MySubscriber">
                <data_reader name="MySquareReader1" topic_ref="Square" />
                <data_reader name="MySquareReader2" topic_ref="Square" />
            </subscriber>
        </domain_participant>

I then modified the reader.py to do:

with rti.open_connector(
        config_name="MyParticipantLibrary::MySubParticipant",
        url=file_path + "/../ShapeExample.xml") as connector:

    input1 = connector.get_input("MySubscriber::MySquareReader1")
    input2 = connector.get_input("MySubscriber::MySquareReader2")

    print("Input 1 - Waiting for publications...")
    input1.wait_for_publications() # wait for at least one matching publication
    print("Input 2 - Waiting for publications...")
    input2.wait_for_publications() # wait for at least one matching publication

    while True:
        input1.take()
        for sample in input1.samples.valid_data_iter:
            print("Input 1 ")
            print(sample)

        input2.take() # Never gets sample if A_Listener is created first
        for sample in input2.samples.valid_data_iter:
            print("Input 2")
            print(sample)

And I see samples arriving to both Inputs.

I also modified it to create a separate connector object for each reader (like you are doing in your example):

def ddsReader(readerType):
    connector = rti.Connector(config_name="MyParticipantLibrary::MySubParticipant",url=file_path + "/../ShapeExample.xml")
    dds_reader = connector.get_input(readerType)
    return dds_reader

input1 = ddsReader("MySubscriber::MySquareReader1")
input2 = ddsReader("MySubscriber::MySquareReader2")

print("Input 1 - Waiting for publications...")
input1.wait_for_publications() # wait for at least one matching publication
print("Input 2 - Waiting for publications...")
input2.wait_for_publications() # wait for at least one matching publication

while True:
    input1.take()
    for sample in input1.samples.valid_data_iter:
        print("Input 1 ")
        print(sample)

    input2.take() # Never gets sample if A_Listener is created first
    for sample in input2.samples.valid_data_iter:
        print("Input 2")
        print(sample)

and it still works:

Input 2
<rticonnextdds_connector.rticonnextdds_connector.ValidSampleIterator object at 0x7fa7b3e5fe50>
Input 1 
<rticonnextdds_connector.rticonnextdds_connector.ValidSampleIterator object at 0x7fa7b3e5fd30>
Input 1 
<rticonnextdds_connector.rticonnextdds_connector.ValidSampleIterator object at 0x7fa7b3e5fe50>
Input 2
<rticonnextdds_connector.rticonnextdds_connector.ValidSampleIterator object at 0x7fa7b3e5fd30>
Input 1 
<rticonnextdds_connector.rticonnextdds_connector.ValidSampleIterator object at 0x7fa7b3e5fe50>
Input 2
<rticonnextdds_connector.rticonnextdds_connector.ValidSampleIterator object at 0x7fa7b3e5fd30>

@aris-t
Copy link
Author

aris-t commented Feb 17, 2022

So I am not crazy. I had run a similar test last night.

How would you expect the above to change if I were not talking to another RTI DDS connection. For instance is there any reason to believe the behavior would be different when talking with a computer running twin oaks DDS? Both are using DDS and should be interoperable? I am writing 1/2 of a software stack and another group is working on the other 1/2. I only have their XML and some pre compiled test scripts.

@samuelraeburn
Copy link
Collaborator

It shouldn't have an effect AFAIK.

Could you run a quick test for me and modify your code such that only one Connector object is created (and then that Connector is used to create both of the inputs, as opposed to creating a Connector per reader)?

Out of interest, are your DataReaders both defined under the same DomainParticipant? And the DataWriter too?

@aris-t
Copy link
Author

aris-t commented Feb 17, 2022

So if I am understanding you right this should be the new connector generator:

def ddsReader(subscriberType, readerTypeA, readerTypeB):
    DDS_config = "DomainParticipantLibrary::DiscoveryDomainParticipant"
    DDS_xml = os.environ["DDSPATH"]
    connector=rti.Connector(config_name=DDS_config,url=DDS_xml)
    dds_reader_A = connector.get_input(f"{subscriberType}::{readerTypeA}")
    dds_reader_B = connector.get_input(f"{subscriberType}::{readerTypeB}")
    return dds_reader_A, dds_reader_B

xml (redacted)

	<domain_participant_library name="DomainParticipantLibrary">
		<domain_participant name="DiscoveryDomainParticipant" domain_ref="DomainLibrary::DiscoveryDomain">
			<participant_qos base_name="participantQos"/>
			<subscriber name="Subscriber">
				<subscriber_qos base_name="subscriberQos"/>
				<data_reader topic_ref="TopicA" name="TopicAReader">
					<datareader_qos base_name="readerQOSA"/>
				</data_reader>
                               	<data_reader topic_ref="TopicB" name="TopicBReader">
					<datareader_qos base_name="readerQOSB"/>
				</data_reader>

They are both defined under the same domain participant as well as subscriber. I have tried splitting them into different subscribers with no effect. Oddly the QOS xml I am using is being used as it with another group working on an electron application and they do not encounter the issue.

I will test the multi reader from a single connector solution as soon as I can track down where the testing box walked off to...

@aris-t
Copy link
Author

aris-t commented Feb 18, 2022

Update:

Could you run a quick test for me and modify your code such that only one Connector object is created (and then that Connector is used to create both of the inputs, as opposed to creating a Connector per reader)?

I can say with preliminary confidence that this appears to be a solution. Generate a single connector with multiple readers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants