ROS TCP Connector C# Lost Publishers & Freezing
Hello there,
I am trying to set envirovment variables and then, do roslaunch ros_tcp_endpoint endpoint.launch
from Unity. Where, i am connecting to a master selected before from a menu by click of a button, then subscribing to master for getting a live video feed and publishing some messages again on click of a button. Here is my code:
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.SceneManagement;
using Unity.Robotics.ROSTCPConnector;
using UnityEngine.InputSystem;
using RosImage = RosMessageTypes.Sensor.CompressedImageMsg;
using ROString = RosMessageTypes.Std.StringMsg;
using RosMessageTypes.Geometry;
using UnityEngine.UI;
using TMPro;
public class SubnPub : MonoBehaviour
{
private Process process = new Process();
ROString directionMsg;
ROSConnection directionPublisher;
private Texture2D liveFeedTexture;
public string topic = "/camera/image/compressed";
public RawImage TheScreen;
private bool isStopped = false;
public TextMeshProUGUI startstopText;
public Button upButton, downButton, leftButton, rightButton;
// Start is called before the first frame update
void Start()
{
UnityEngine.Debug.Log("Current Device IP: "+DataKeeper.currentDeviceIP);
//In order to prevent cmd from closing and killing the running commands in the process, /k added before commands.
private string command;
command = "/c cd \\ && .\\my_catkin_wp\\devel\\setup.bat && set ROS_MASTER_URI=http://" + DataKeeper.currentDeviceIP + ":11311 && roslaunch ros_tcp_endpoint endpoint.launch";
//This function will open the cmd and then, run the commands to set the ROS_MASTER_URI to ip of the selected
// device and to launch the "ros_tcp_endpoint.launch" file to start the connection between ROS and Unity.
SetRosEnv();
UnityEngine.Debug.Log("Current Device IP: " + DataKeeper.currentDeviceIP);
liveFeedTexture = new Texture2D(1832, 1920, TextureFormat.RGB8, false);
TheScreen.texture = liveFeedTexture;
ROSConnection.GetOrCreateInstance().Subscribe<RosImage>(topic, ChangeFeedTexture);
UnityEngine.Debug.Log("Subscribed to the image.");
UnityEngine.Debug.Log("Current Button is: "+startstopText.text);
UnityEngine.Debug.Log("Is Stop button clicked :"+isStopped.ToString());
directionPublisher = ROSConnection.GetOrCreateInstance();
directionPublisher.RegisterPublisher<ROString>("/unity/direction");
}
void ChangeFeedTexture(RosImage videoFeed)
{
if (isStopped == false)
{
liveFeedTexture.LoadImage(videoFeed.data);
//FlipTextureVertical(liveFeedTexture);
liveFeedTexture.Apply();
}
}
private void SetRosEnv()
{
//Creates process start info object for setting starting options
ProcessStartInfo startInfo = new ProcessStartInfo();
//Sets file to be opened the cmd.exe for opening the command prompt
startInfo.FileName = "cmd.exe";
// Set UseShellExecute to false to redirect input/output
startInfo.UseShellExecute = false;
//Set verb to "runas" for running as administrator
startInfo.Verb = "runas";
//Hide and prevent creation of cmd window
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
//Redirect standard input/output/error to receive output from the ROS command
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
// Create and start the process
process.StartInfo = startInfo;
process.OutputDataReceived += (sender, args1) => UnityEngine.Debug.Log("Output: \n" + "\n" + args1.Data);
process.ErrorDataReceived += (sender, args1) => UnityEngine.Debug.Log("Error: \n" + "\n" + args1.Data);
process.Start();
DataKeeper.currentProcessID = process.Id;
process.BeginOutputReadLine();
process.StandardInput.WriteLine("cd /d C:");
process.StandardInput.WriteLine("cd \\");
process.StandardInput.WriteLine(".\\my_catkin_wp\\devel\\setup.bat");
process.StandardInput.WriteLine("set ROS_MASTER_URI=http://" + DataKeeper.currentDeviceIP + ":11311");
process.StandardInput.WriteLine("roslaunch ros_tcp_endpoint endpoint.launch");
}
public void OnStartStopClicked()
{
isStopped = !isStopped;
UnityEngine.Debug.Log("Changed to "+isStopped.ToString());
if (isStopped == false)
{
UnityEngine.Debug.Log("Starting the live stream!");
startstopText.text = "Stop";
}
else
{
UnityEngine.Debug.Log("Stopping the live stream!");
startstopText.text = "Start";
}
}
public void OnUPButton()
{
directionMsg = new ROString("forward");
directionPublisher.Publish("/unity/direction", directionMsg);
}
public void OnDownButton()
{
directionMsg = new ROString("backward");
directionPublisher.Publish("/unity/direction", directionMsg);
}
public void OnLeftButton()
{
directionMsg = new ROString("left");
directionPublisher.Publish("/unity/direction", directionMsg);
}
public void OnRightButton()
{
directionMsg = new ROString("right");
directionPublisher.Publish("/unity/direction", directionMsg);
}
public void OnExitButton()
{
process.OutputDataReceived += (sender, args1) => UnityEngine.Debug.Log("Output: \n" + "\n" + args1.Data);
process.ErrorDataReceived += (sender, args1) => UnityEngine.Debug.Log("Error: \n" + "\n" + args1.Data);
process.StandardInput.WriteLine("\x3");
process.Kill();
DataKeeper.currentProcessID = null;
DataKeeper.currentDeviceIP = "";
SceneManager.LoadScene("DevicesMenu");
}
}
This code works and i can see the live feed. The problem with this code is after a few seconds when i run rostopic list
i can't see the "/unity/direction" topic and publisher is lost.
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using UnityEngine.SceneManagement;
using Unity.Robotics.ROSTCPConnector;
using UnityEngine.InputSystem;
using RosImage = RosMessageTypes.Sensor.CompressedImageMsg;
using ROString = RosMessageTypes.Std.StringMsg;
using RosMessageTypes.Geometry;
using ROSPose = RosMessageTypes.Geometry.PoseMsg;
using UnityEngine.UI;
using TMPro;
public class SubnPub: MonoBehaviour
{
private Process process = new Process();
ROString directionMsg;
ROSConnection directionPublisher;
private Texture2D liveFeedTexture;
public string topic = "/camera/image/compressed";
public RawImage TheScreen;
private bool isStopped = false;
public TextMeshProUGUI startstopText;
public Button upButton, downButton, leftButton, rightButton;
// Start is called before the first frame update
void Start()
{
UnityEngine.Debug.Log("Current Device IP: "+DataKeeper.currentDeviceIP);
//In order to prevent cmd from closing and killing the running commands in the process, /k added before commands.
private string command;
command = "/c cd \\ && .\\my_catkin_wp\\devel\\setup.bat && set ROS_MASTER_URI=http://" + DataKeeper.currentDeviceIP + ":11311 && roslaunch ros_tcp_endpoint endpoint.launch";
//This function will open the cmd and then, run the commands to set the ROS_MASTER_URI to ip of the selected
// device and to launch the "ros_tcp_endpoint.launch" file to start the connection between ROS and Unity.
SetRosEnv();
UnityEngine.Debug.Log("Current Device IP: " + DataKeeper.currentDeviceIP);
liveFeedTexture = new Texture2D(1832, 1920, TextureFormat.RGB8, false);
TheScreen.texture = liveFeedTexture;
ROSConnection.GetOrCreateInstance().Subscribe<RosImage>(topic, ChangeFeedTexture);
UnityEngine.Debug.Log("Subscribed to the image.");
UnityEngine.Debug.Log("Current Button is: "+startstopText.text);
UnityEngine.Debug.Log("Is Stop button clicked :"+isStopped.ToString());
directionPublisher = ROSConnection.GetOrCreateInstance();
directionPublisher.RegisterPublisher<ROString>("/unity/direction");
}
void ChangeFeedTexture(RosImage videoFeed)
{
if (isStopped == false)
{
liveFeedTexture.LoadImage(videoFeed.data);
//FlipTextureVertical(liveFeedTexture);
liveFeedTexture.Apply();
}
}
private void SetRosEnv()
{
//Creates process start info object for setting starting options
ProcessStartInfo startInfo = new ProcessStartInfo();
//Sets file to be opened the cmd.exe for opening the command prompt
startInfo.FileName = "cmd.exe";
//Starting arguements set to commands wanted to be runned
startInfo.Arguments = command;
// Set UseShellExecute to false to redirect input/output
startInfo.UseShellExecute = false;
//Set verb to "runas" for running as administrator
startInfo.Verb = "runas";
//Hide and prevent creation of cmd window
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
//Redirect standard input/output/error to receive output from the ROS command
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
// Create and start the process
Process process = new Process();
process.StartInfo = startInfo;
UnityEngine.Debug.Log("Commands to be run: \n" + process.StartInfo.Arguments);
process.Start();
//process.WaitForExit();
UnityEngine.Debug.Log("OUTPUT: \n\n" + process.StandardOutput.ReadToEnd());
UnityEngine.Debug.Log("OUTPUT: \n\n" + process.StandardOutput.ReadToEnd());
}
public void OnStartStopClicked()
{
isStopped = !isStopped;
UnityEngine.Debug.Log("Changed to "+isStopped.ToString());
if (isStopped == false)
{
UnityEngine.Debug.Log("Starting the live stream!");
startstopText.text = "Stop";
}
else
{
UnityEngine.Debug.Log("Stopping the live stream!");
startstopText.text = "Start";
}
}
public void OnUPButton()
{
directionMsg = new ROString("forward");
directionPublisher.Publish("/unity/direction", directionMsg);
}
public void OnDownButton()
{
directionMsg = new ROString("backward");
directionPublisher.Publish("/unity/direction", directionMsg);
}
public void OnLeftButton()
{
directionMsg = new ROString("left");
directionPublisher.Publish("/unity/direction", directionMsg);
}
public void OnRightButton()
{
directionMsg = new ROString("right");
directionPublisher.Publish("/unity/direction", directionMsg);
}
public void OnExitButton()
{
process.Dispose();
DataKeeper.currentDeviceIP = "";
SceneManager.LoadScene("DevicesMenu");
}
}
The problem is the process in this code doesn't exits and can't get to see the live feed.
I would appreciate any help, any advice,
Thanks in advance.
Asked by mericgeren on 2023-07-25 16:41:17 UTC
Comments