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

Running two Publishers in same thread does not work #10

Open
antoabbot opened this issue Jun 29, 2020 · 3 comments
Open

Running two Publishers in same thread does not work #10

antoabbot opened this issue Jun 29, 2020 · 3 comments

Comments

@antoabbot
Copy link

antoabbot commented Jun 29, 2020

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;
        }
    }
}
@antoabbot
Copy link
Author

Update: This problem happens when the .NET code above runs on a different machine (Mac OS) to the Master (Ubuntu on Nvidia Jetson). When I run the .NET code on the Jetson, then the Publishers work concurrently as designed.

@andreaskoepf
Copy link
Member

Your code should generally work. Does a single publisher work with the ROS master running on a different machine (e.g. only the GeoffPanTilt and the Twist separately)? Are both topics visible on the master machine when you type rostopic list? Is the geoff_msgs definition compiled on the machine that runs the Master?

@antoabbot
Copy link
Author

antoabbot commented Jun 30, 2020 via email

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