Skip to content

Running two Publishers in same thread does not work #10

@antoabbot

Description

@antoabbot

Hi

I am attempting to run two publishers in the same thread. I can get either to run fine and publish messages to my robot (one is a camera Pan/Tilt and one is a velocity command). However when both are instantiated, neither run, and sometimes (I believe) I have had one or the other intermittently running. The firing frequency is high for the Velocity message as it will timeout on the bot

My sample code is attached and the behaviour can be triggered via command line arguments.
Please advise how to run multiple publishers in an application? In my real micro service, each Publish is triggered by some incoming signalR requests, but I get the same behaviour

It seems that even the instantiation of the Publisher via Node.Advertise<>() causes the issue

using System;
using Uml.Robotics.Ros;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.Globalization;

namespace ROSTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var localIp = GetLocalIPAddress();

            // Pass a commandline and work out what to run
            // C will run the camera, V the motors , and CV both
            var runCam = (args.Length == 1 && args[0].Contains('c', StringComparison.InvariantCultureIgnoreCase));
            var runVel = (args.Length == 1 && args[0].Contains('v', StringComparison.InvariantCultureIgnoreCase));

            // Global ROS initialisation
            if (string.IsNullOrEmpty(ROS.ROS_MASTER_URI))
                ROS.ROS_MASTER_URI = "http://192.168.8.141:11311";

            ROS.ROS_HOSTNAME = localIp;
            ROS.Init(new string[0], "XoXoTest" + DateTime.UtcNow.Ticks.ToString());
            var spinner = new SingleThreadSpinner();
            var node = new NodeHandle();

            // Predeclare the publishers and set to null.
            Publisher<Messages.geoff_msgs.GeoffPanTilt> cameraPublisher = null;
            Publisher<Messages.geometry_msgs.Twist> velPublisher = null;

            // Only instantiate if needed. This is to test the behaviour of two Publishers in the same thread
            if (runCam)
            {
                cameraPublisher = node.Advertise<Messages.geoff_msgs.GeoffPanTilt>("/pan_tilt", 1000);
                Console.WriteLine("Runnning Camera");
            }

            // Only instantiate if needed. This is to test the behaviour of two Publishers in the same thread
            if (runVel)
            {
                velPublisher = node.Advertise<Messages.geometry_msgs.Twist>("/cmd_vel", 1000);
                Console.WriteLine("Runnning Motors");
            }


            var dt = 50; // Time delay for the message loop in milliseconds
            uint i = 0;

            unchecked // To allow the int to overflow if it reaches the end
            {
                while (ROS.OK && !Console.KeyAvailable)
                {
                    // Generate some sinusoidal inputs
                    var pan = (short)(Math.Sin(i / (0.5 * dt)) * 32767);
                    var tilt = (short)(Math.Cos(i / (0.3 * dt)) * 32767);
                    var vel = Math.Sin(i / (1.0 * dt));
                    var twist = Math.Cos(i / (0.7 * dt));

                    if (velPublisher != null)
                    {
                        var vmsg = new Messages.geometry_msgs.Twist();
                        vmsg.linear.x = vel;
                        vmsg.angular.z = twist;
                        velPublisher.Publish(vmsg);
                        spinner.SpinOnce();
                    }

                    if (cameraPublisher != null)
                    {
                        var msg = new Messages.geoff_msgs.GeoffPanTilt { pan = pan, tilt = tilt };
                        cameraPublisher.Publish(msg);
                        spinner.SpinOnce();
                    }

                    Thread.Sleep(dt);
                    i++;
                }
            }

            ROS.Shutdown();
            Console.WriteLine("Done");
        }

        private static string GetLocalIPAddress()
        {
            string localIP;
            using (Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0))
            {
                socket.Connect("8.8.8.8", 65530);
                IPEndPoint endPoint = socket.LocalEndPoint as IPEndPoint;
                localIP = endPoint.Address.ToString();
            }

            return localIP;
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions