ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

ROS2 listener not entering the callback function

asked 2018-08-06 05:12:34 -0600

aks gravatar image

updated 2018-08-07 02:44:56 -0600

I am interfacing a ROS2 subscriber with a native RTI DDS publisher.

I have the following message structure for the message named DetectedObjectList

int16 id

//an array of objects of another message type

DetectedObject[ ] objects

and the DetectedObject.msg is defined as follows :

int16 id

int16 x

int16 y

I am publishing an id and an object of type DetectedObject

To Simplify the problem, now my msg file contains only int16 id.

If I look at the RTI Admin Console, the datatypes in the ROS2 listener and RTI are matched and everything seems to be ok.

I feel I am doing something wrong in the ROS2 listener node. Here is the snippet for my ROS2 listener

EDIT : Full ROS2 code.

import sys
import rclpy
from rclpy.node import Node

from openadx_msg.msg import (DetectedObjectList, DetectedObject)

class DemoNode(Node):

    def __init__(self):
        super().__init__('ros2_listener')
        self.sub = self.create_subscription(DetectedObjectList, 'vehicle/objects', self.object_callback)

    def object_callback(self,msg):
        print("entering callback")
        log = self.get_logger().info
        log('Received a message')
        log('id: {}.format(msg.id)')

def main(args=None):
    if args is None:
        args=sys.argv
    node=DemoNode()    // EDIT2
    rclpy.spin(node)

    node.destroy_node()
    rclpy.shutdown()

if __name__=='__main__':  //EDIT3
    main()

Here is the code for the RTI DDS python connector :

from __future__ import print_function
from ctypes import *
import sys
import os
from sys import path as sysPath
from os import path as osPath
from time import sleep
import math
filepath = osPath.dirname(osPath.realpath(__file__))
sysPath.append(filepath + "/../../../")
import rticonnextdds_connector as rti

def main():


    connector = rti.Connector("MyParticipantLibrary::Zero",
                          filepath + "/../ROS2_demo_nodes_py.xml")
    outputDDS = connector.getOutput("MyPublisher::VehicleObjectWriter")


    for i in range(1,50000):


            outputDDS.instance.setNumber("id_",i)
            outputDDS.write()

            toPrint = "id_ : " + repr(i)
            print(toPrint)





if __name__== "__main__":
    main()

And here is the xml file used by this connector. The xml is a translated version of the ROS2 IDL file.

<dds xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:noNamespaceSchemaLocation="http://community.rti.com/schema/5.1.0/rti_dds_profiles.xsd" version="5.1.0">

    <!-- Qos Library -->
    <qos_library name="QosLibrary">
        <qos_profile name="DefaultProfile" is_default_qos="true" base_name="BuiltinQosLib::Generic.510TransportCompatibility">
            <datawriter_qos>
                <property>
                    <value>
                        <element>
                        <name>dds.data_writer.history.memory_manager.fast_pool.pool_buffer_max_size</name>
                        <value>2147483647</value>
                        </element>
                    </value>
                </property>
            </datawriter_qos>

            <datareader_qos>
                <property>
                    <value>
                        <element>
                        <name>dds.data_writer.history.memory_manager.fast_pool.pool_buffer_max_size</name>
                        <value>2147483647</value>
                        </element>
                    </value>
                </property>
            </datareader_qos>
            <publisher_qos>
                <partition>
                    <name>
                        <element>rt/vehicle</element>
                    </name>
                </partition>
            </publisher_qos>
            <subscriber_qos>
                <partition>
                    <name>
                        <element>rt/vehicle</element>
                    </name>
                </partition>
            </subscriber_qos>
            <participant_qos>
                <transport_builtin>
                    <mask>UDPV4 | SHMEM</mask>
                </transport_builtin>
            </participant_qos>
        </qos_profile>
    </qos_library>

    <!-- types -->
    <types>
    <module name="openadx_msgs">
    <module name="msg">
    <module name="dds_">
      <const name="VehicleControl__GEAR_KEEP" type="int32" value="-1"/>
      <const name="VehicleControl__GEAR_PARK" type="int32" value="0"/>
      <const name="VehicleControl__GEAR_NEUTRAL" type="int32" value="1"/>
      <const name="VehicleControl__GEAR_DRIVE" type="int32" value="2"/>
      <const name="VehicleControl__GEAR_REVERSE" type="int32" value="3"/>
      <struct name= "VehicleControl_">
        <member name="accelerator_pedal_" type="float64"/>
        <member name="brake_pedal_" type="float64"/>
        <member name="steering_wheel_" type="float64"/>
        <member name="gear_" type="int32"/>
      </struct>
    </module>
    </module>
    </module>

    <module name="openadx_msgs">
    <module name="msg">
    <module name="dds_">
     <struct ...
(more)
edit retag flag offensive close merge delete

Comments

Would you mind posting a full source file showing the issue? I suspect rclpy.spin() isn't being called, but I can't say for sure without seeing more of the code.

sloretz gravatar image sloretz  ( 2018-08-06 09:38:11 -0600 )edit

@sloretz : I have updated the code

aks gravatar image aks  ( 2018-08-06 10:16:37 -0600 )edit

Have you tried publishing a dummy message using the command line tool ros2 topic pub ...? That should at least show you if the problem is in your subscriber or on the publisher side.

Dirk Thomas gravatar image Dirk Thomas  ( 2018-08-06 14:28:29 -0600 )edit

Yes, I have tried that. Publishing from ROS2, I can subscribe on the native DDS Application. I have also broken down the problem , publishing a simple string on the topic chatter and run the listener.py node in ROS2 but it still doesnt subscribe. Debugging it->doesnt enter callback. dont know y

aks gravatar image aks  ( 2018-08-06 14:38:10 -0600 )edit

If none of the tutorials work for you you might want to check if your network interface support multicasts.

Dirk Thomas gravatar image Dirk Thomas  ( 2018-08-06 15:30:51 -0600 )edit

The machine on which I run native DDS does not support multicast but i guess this should not be a problem as the communication is working in one direction.

aks gravatar image aks  ( 2018-08-07 02:35:19 -0600 )edit

2 Answers

Sort by ยป oldest newest most voted
2

answered 2018-08-07 08:41:40 -0600

aks gravatar image

updated 2018-08-07 08:51:00 -0600

I found the problem.

RTI interprets unbounded string as MAX_SIZE_INT32 which is 2147483647. I had a variable in header as string frame_id. To establish communication between ROS2 and native DDS, the types should be same. So, in the QoS.xml, I gave the maxStringLength = 2147483647. This gave an error create DataWriter buffer pool. Refering to the RTI community, I created an extra QoS setting for the data_writer and data_reader :

    <datawriter_qos>
        <property>
            <value>
                <element>
                <name>dds.data_writer.history.memory_manager.fast_pool.pool_buffer_max_size</name>
                <value>2147483647</value>
                </element>
            </value>
        </property>
    </datawriter_qos>
    <datareader_qos>
        <property>
            <value>
                <element>
                <name>dds.data_writer.history.memory_manager.fast_pool.pool_buffer_max_size</name>
                <value>2147483647</value>
                </element>
            </value>
        </property>
    </datareader_qos>

This somehow lead to improper memory management and ROS2 wasnt able to subscribe any messages (not enterin the callback). I reduced the buffer size of the datawriter to 2046 and now it works perfectly fine.

Question : Although I have found out the error, I am still not sure what are the possible reasons for it. Is it only memory creation problem ?

edit flag offensive delete link more
1

answered 2018-08-06 11:05:07 -0600

The problem is you're not creating an instance of your DemoNode object at any point. If you look at this subscriber example you can see the structure you need.

Your main should look something like this:

def main(args=None):
    if args is None:
        args=sys.argv

    demo_node = DemoNode()
    rclpy.spin(demo_node)

    demo_node.destroy_node()
    rclpy.shutdown()

Hope this helps.

edit flag offensive delete link more

Comments

@PeterBlackerThe3rd...Thanks for noticing that. I already had that in my code but while typing the code manually in this post, I missed it by mistake. Sorry for the confusion.

aks gravatar image aks  ( 2018-08-06 14:24:11 -0600 )edit

It might be another copy n paste error but you're second to last line should be

if __name__ == '__main__':
PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-08-06 15:51:19 -0600 )edit

You could put a couple of print statements in main and DemoNode.__init__ to check they're being setup properly.

PeteBlackerThe3rd gravatar image PeteBlackerThe3rd  ( 2018-08-06 15:54:20 -0600 )edit

The easiest would be to share the complete code of a package as well as the exact line of a publisher cli invocation. Than readers can try your case in literally a minute and comment if it is a problem in your code or not.

Dirk Thomas gravatar image Dirk Thomas  ( 2018-08-06 16:31:40 -0600 )edit

Updated the entire code

aks gravatar image aks  ( 2018-08-07 02:35:33 -0600 )edit

Question Tools

3 followers

Stats

Asked: 2018-08-06 05:12:34 -0600

Seen: 2,128 times

Last updated: Aug 07 '18