-
Notifications
You must be signed in to change notification settings - Fork 11
Description
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;
}
}
}