ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange |
![]() | 1 | initial version |
I've just found a way to perform a remote launch from a python launch file using the ExecuteProcess launch action. There are several problems you're going to face if you go this way, so here are the workarounds I used to solve them (on Ubuntu 20.04).
First, let's state what we are trying to achieve:
ssh pi@192.168.0.20
from machine A (without a password, i.e. use ssh-keygen -t rsa -b 2048 && ssh-copy-id pi@192.168.0.20
first)drinks_hmi_launch.py
in drinks_hmi_bringup
package on machine B (we can launch it from machine B via ros2 launch drinks_hmi_bringup drinks_hmi_launch.py
)drinks_bringup_launch.py
in drinks_bringup
package on machine A which is supposed (among other actions) to launch drinks_hmi_launch.py
on machine BNow the following command should work from machine A, i.e. it launches the nodes, prints out output and can be terminated via SIGINT (Ctrl+C):
ssh -t pi@192.168.0.20 'bash -i -c "ros2 launch drinks_hmi_bringup drinks_hmi_launch.py"'
However, after putting it directly into ExecuteProcess
action in drinks_bringup_launch.py
, the process complains about not having a proper tty
console and the nodes on machine B are not terminated after terminating the ros2 launch drinks_bringup drinks_bringup_launch.py
process.
A workaround is to call the above command inside a detached screen
. This, however, raises two further problems:
screen
does not pass SIGINT from calling process to inner processes, so it does not terminate the nodes when Ctrl+C is pressed. However it can be terminated explicitly using a remote_launch_terminator
node which calls screen -S hmi -X quit
(see the complete solution below)screen
does not pass output from inner processes to calling process, so this needs to be done explicitly by redirecting inner output to outerThe complete solution is as follows:
/home/machine_A/drink_ws/src/launch_utils/launch_utils/remote_launch_terminator.py
:
import rclpy
from rclpy.node import Node
import os
def main(args=None):
rclpy.init(args=args)
node = Node('remote_launch_terminator')
node.declare_parameter('screen_pid', 'remote')
screen_pid = node.get_parameter('screen_pid').get_parameter_value().string_value
try:
rclpy.spin(node)
except:
pass
print('Terminating ' + screen_pid)
os.system('screen -S ' + screen_pid + ' -X quit')
if __name__ == '__main__':
main()
/home/machine_A/drink_ws/src/drinks_bringup/launch/drinks_bringup_launch.py
:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions.execute_process import ExecuteProcess
def generate_launch_description():
return LaunchDescription([
# other actions
# remote launch
ExecuteProcess(
name='hmi',
cmd=['{ outer_stdout=$(readlink -f /proc/self/fd/3); } 3>&1 && screen -DmS hmi bash -i -c "ssh -t pi@192.168.0.20 \'bash -i -c \\"ros2 launch drinks_hmi_bringup drinks_hmi_launch.py\\"\' > $outer_stdout"'],
output="screen",
shell=True
),
Node(
package='launch_utils',
executable='remote_launch_terminator',
name='remote_launch_terminator',
output='screen',
parameters=[{'screen_pid': 'hmi'}]
),
])
Note: ExecuteProcess
action does not work inside OnShutdown
event, that's why the remote_launch_terminator
must be used
![]() | 2 | No.2 Revision |
I've just found a way to perform a remote launch from a python launch file using the ExecuteProcess launch action. There are several problems you're going to face if you go this way, so here are the workarounds I used to solve them (on Ubuntu 20.04).
First, let's state what we are trying to achieve:
ssh pi@192.168.0.20
from machine A (without a password, i.e. use ssh-keygen -t rsa -b 2048 && ssh-copy-id pi@192.168.0.20
first)drinks_hmi_launch.py
in drinks_hmi_bringup
package on machine B (we can launch it from machine B via ros2 launch drinks_hmi_bringup drinks_hmi_launch.py
)drinks_bringup_launch.py
in drinks_bringup
package on machine A which is supposed (among other actions) to launch drinks_hmi_launch.py
on machine BNow the following command should work from machine A, i.e. it launches the nodes, prints out output and can be terminated via SIGINT (Ctrl+C):
ssh -t pi@192.168.0.20 'bash -i -c "ros2 launch drinks_hmi_bringup drinks_hmi_launch.py"'
However, after putting it directly into ExecuteProcess
action in drinks_bringup_launch.py
, the process complains about not having a proper tty
console and the nodes on machine B are not terminated after terminating the ros2 launch drinks_bringup drinks_bringup_launch.py
process.
A workaround is to call the above command inside a detached screen
. (use sudo apt install screen
if not present). This, however, raises two further problems:
screen
does not pass SIGINT from calling process to inner processes, so it does not terminate the nodes when Ctrl+C is pressed. However it can be terminated explicitly using a remote_launch_terminator
node which calls screen -S hmi -X quit
(see the complete solution below)screen
does not pass output from inner processes to calling process, so this needs to be done explicitly by redirecting inner output to outerThe complete solution is as follows:
/home/machine_A/drink_ws/src/launch_utils/launch_utils/remote_launch_terminator.py
:
import rclpy
from rclpy.node import Node
import os
def main(args=None):
rclpy.init(args=args)
node = Node('remote_launch_terminator')
node.declare_parameter('screen_pid', 'remote')
screen_pid = node.get_parameter('screen_pid').get_parameter_value().string_value
try:
rclpy.spin(node)
except:
pass
print('Terminating ' + screen_pid)
os.system('screen -S ' + screen_pid + ' -X quit')
if __name__ == '__main__':
main()
/home/machine_A/drink_ws/src/drinks_bringup/launch/drinks_bringup_launch.py
:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions.execute_process import ExecuteProcess
def generate_launch_description():
return LaunchDescription([
# other actions
# remote launch
ExecuteProcess(
name='hmi',
cmd=['{ outer_stdout=$(readlink -f /proc/self/fd/3); } 3>&1 && screen -DmS hmi bash -i -c "ssh -t pi@192.168.0.20 \'bash -i -c \\"ros2 launch drinks_hmi_bringup drinks_hmi_launch.py\\"\' > $outer_stdout"'],
output="screen",
shell=True
),
Node(
package='launch_utils',
executable='remote_launch_terminator',
name='remote_launch_terminator',
output='screen',
parameters=[{'screen_pid': 'hmi'}]
),
])
Note: ExecuteProcess
action does not work inside OnShutdown
event, that's why the remote_launch_terminator
must be used
![]() | 3 | No.3 Revision |
I've just found a way to perform a remote launch from a python launch file using the ExecuteProcess launch action. There are several problems you're going to face if you go this way, so here are the workarounds I used to solve them (on Ubuntu 20.04).
First, let's state what we are trying to achieve:
ssh pi@192.168.0.20
from machine A (without a password, i.e. use ssh-keygen -t rsa -b 2048 && ssh-copy-id pi@192.168.0.20
first)drinks_hmi_launch.py
in drinks_hmi_bringup
package on machine B (we can launch it from machine B via ros2 launch drinks_hmi_bringup drinks_hmi_launch.py
)drinks_bringup_launch.py
in drinks_bringup
package on machine A which is supposed (among other actions) to launch drinks_hmi_launch.py
on machine BNow the following command should work from machine A, i.e. it launches the nodes, prints out output and can be terminated via SIGINT (Ctrl+C):
ssh -t pi@192.168.0.20 'bash -i -c "ros2 launch drinks_hmi_bringup drinks_hmi_launch.py"'
However, after putting it directly into ExecuteProcess
action in drinks_bringup_launch.py
, the process complains about not having a proper tty
console and the nodes on machine B are not terminated after terminating the ros2 launch drinks_bringup drinks_bringup_launch.py
process.
A workaround is to call the above command inside a detached screen
(use sudo apt install screen
if not present). This, however, raises two further problems:
screen
does not pass SIGINT from calling process to inner processes, so it does not terminate the nodes when Ctrl+C is pressed. However it can be terminated explicitly using a remote_launch_terminator
node which calls screen -S hmi -X quit
(see the complete solution below)screen
does not pass output from inner processes to calling process, so this needs to be done explicitly by redirecting inner output to outerThe complete solution is as follows:
/home/machine_A/drink_ws/src/launch_utils/launch_utils/remote_launch_terminator.py
:
import rclpy
from rclpy.node import Node
import os
def main(args=None):
rclpy.init(args=args)
node = Node('remote_launch_terminator')
node.declare_parameter('screen_pid', 'remote')
screen_pid = node.get_parameter('screen_pid').get_parameter_value().string_value
try:
rclpy.spin(node)
except:
pass
print('Terminating ' + screen_pid)
os.system('screen -S ' + screen_pid + ' -X quit')
if __name__ == '__main__':
main()
/home/machine_A/drink_ws/src/drinks_bringup/launch/drinks_bringup_launch.py
:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions.execute_process import ExecuteProcess
def generate_launch_description():
return LaunchDescription([
# other actions
# remote launch
ExecuteProcess(
name='hmi',
cmd=['{ outer_stdout=$(readlink -f /proc/self/fd/3); } 3>&1 && screen -DmS hmi bash -i -c "ssh -t pi@192.168.0.20 \'bash -i -c \\"ros2 launch drinks_hmi_bringup drinks_hmi_launch.py\\"\' > $outer_stdout"'],
output="screen",
shell=True
),
Node(
package='launch_utils',
executable='remote_launch_terminator',
name='remote_launch_terminator',
output='screen',
parameters=[{'screen_pid': 'hmi'}]
),
])
Hope this helps, cheers! ;)
Note: ExecuteProcess
action does not work inside OnShutdown
event, that's why the remote_launch_terminator
must be used
![]() | 4 | No.4 Revision |
I've just found a way to perform a remote launch from a python launch file using the ExecuteProcess launch action. There are several problems you're going to face if you go this way, so here are the workarounds I used to solve them (on Ubuntu 20.04).
First, let's state what we are trying to achieve:
ssh pi@192.168.0.20
from machine A (without a password, i.e. use ssh-keygen -t rsa -b 2048 && ssh-copy-id pi@192.168.0.20
first)drinks_hmi_launch.py
in drinks_hmi_bringup
package on machine B (we can launch it from machine B via ros2 launch drinks_hmi_bringup drinks_hmi_launch.py
)drinks_bringup_launch.py
in drinks_bringup
package on machine A which is supposed (among other actions) to launch drinks_hmi_launch.py
on machine BNow the following command should work from machine A, i.e. it launches the nodes, prints out output and can be terminated via SIGINT (Ctrl+C):
ssh -t pi@192.168.0.20 'bash -i -c "ros2 launch drinks_hmi_bringup drinks_hmi_launch.py"'
However, after putting it directly into ExecuteProcess
action in drinks_bringup_launch.py
, the process complains about not having a proper tty
console and the nodes on machine B are not terminated after terminating the ros2 launch drinks_bringup drinks_bringup_launch.py
process.
A workaround is to call the above command inside a detached screen
(use sudo apt install screen
if not present). This, however, raises two further problems:
screen
does not pass SIGINT from calling process to inner processes, so it does not terminate the nodes when Ctrl+C is pressed. However it can be terminated explicitly using a remote_launch_terminator
node which calls screen -S hmi -X quit
(see the complete solution below)screen
does not pass output from inner processes to calling process, so this needs to be done explicitly by redirecting inner output to outerThe complete solution is as follows:
/home/machine_A/drink_ws/src/launch_utils/launch_utils/remote_launch_terminator.py
:
import rclpy
from rclpy.node import Node
import os
def main(args=None):
rclpy.init(args=args)
node = Node('remote_launch_terminator')
node.declare_parameter('screen_pid', 'remote')
screen_pid = node.get_parameter('screen_pid').get_parameter_value().string_value
try:
rclpy.spin(node)
except:
pass
print('Terminating ' + screen_pid)
os.system('screen -S ' + screen_pid + ' -X quit')
if __name__ == '__main__':
main()
/home/machine_A/drink_ws/src/drinks_bringup/launch/drinks_bringup_launch.py
:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions.execute_process import ExecuteProcess
def generate_launch_description():
return LaunchDescription([
# other actions
# remote launch
ExecuteProcess(
name='hmi',
cmd=['{ outer_stdout=$(readlink -f /proc/self/fd/3); } 3>&1 && screen -DmS hmi bash -i -c "ssh -t pi@192.168.0.20 \'bash -i -c \\"ros2 launch drinks_hmi_bringup drinks_hmi_launch.py\\"\' > $outer_stdout"'],
output="screen",
shell=True
),
Node(
package='launch_utils',
executable='remote_launch_terminator',
name='remote_launch_terminator',
output='screen',
parameters=[{'screen_pid': 'hmi'}]
),
])
Hope this helps, cheers! ;)
Note: ExecuteProcess
action does not work inside OnShutdown
event, that's why the remote_launch_terminator
must be used
emulate_tty:=true
didn't work for me either, that's why I had to use screen
, if you are more lucky, please share how you proceeded ![]() | 5 | No.5 Revision |
I've just found a way to perform a remote launch from a python launch file using the ExecuteProcess launch action. There are several problems you're going to face if you go this way, so here are the workarounds I used to solve them (on Ubuntu 20.04).
First, let's state what we are trying to achieve:
ssh pi@192.168.0.20
from machine A (without a password, i.e. use ssh-keygen -t rsa -b 2048 && ssh-copy-id pi@192.168.0.20
first)drinks_hmi_launch.py
in drinks_hmi_bringup
package on machine B (we can launch it from machine B via ros2 launch drinks_hmi_bringup drinks_hmi_launch.py
)drinks_bringup_launch.py
in drinks_bringup
package on machine A which is supposed (among other actions) to launch drinks_hmi_launch.py
on machine BNow the following command should work from machine A, i.e. it launches the nodes, prints out output and can be terminated via SIGINT (Ctrl+C):
ssh -t pi@192.168.0.20 'bash -i -c "ros2 launch drinks_hmi_bringup drinks_hmi_launch.py"'
However, after putting it directly into ExecuteProcess
action in drinks_bringup_launch.py
, the process complains about not having a proper tty
console and the nodes on machine B are not terminated after terminating the ros2 launch drinks_bringup drinks_bringup_launch.py
process.
A workaround is to call the above command inside a detached screen
(use sudo apt install screen
if not present). This, however, raises two further problems:
screen
does not pass SIGINT from calling process to inner processes, so it does not terminate the nodes when Ctrl+C is pressed. However it can be terminated explicitly using a remote_launch_terminator
node which calls screen -S hmi -X quit
(see the complete solution below)screen
does not pass output from inner processes to calling process, so this needs to be done explicitly by redirecting inner output to outerThe complete solution is as follows:
/home/machine_A/drink_ws/src/launch_utils/launch_utils/remote_launch_terminator.py
:
import rclpy
from rclpy.node import Node
import os
def main(args=None):
rclpy.init(args=args)
node = Node('remote_launch_terminator')
node.declare_parameter('screen_pid', 'remote')
screen_pid = node.get_parameter('screen_pid').get_parameter_value().string_value
try:
rclpy.spin(node)
except:
pass
print('Terminating ' + screen_pid)
os.system('screen -S ' + screen_pid + ' -X quit')
if __name__ == '__main__':
main()
/home/machine_A/drink_ws/src/drinks_bringup/launch/drinks_bringup_launch.py
:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions.execute_process import ExecuteProcess
def generate_launch_description():
return LaunchDescription([
# other actions
# remote launch
ExecuteProcess(
name='hmi',
cmd=['{ outer_stdout=$(readlink -f /proc/self/fd/3); } 3>&1 && screen -DmS hmi bash -i -c "ssh -t pi@192.168.0.20 \'bash -i -c \\"ros2 launch drinks_hmi_bringup drinks_hmi_launch.py\\"\' > $outer_stdout"'],
output="screen",
shell=True
),
Node(
package='launch_utils',
executable='remote_launch_terminator',
name='remote_launch_terminator',
output='screen',
parameters=[{'screen_pid': 'hmi'}]
),
])
Hope this helps, cheers! ;)
Note: ExecuteProcess
action does not work inside OnShutdown
event, that's why the remote_launch_terminator
must be used
used
Note: emulate_tty:=true
didn't work for me either, that's why I had to use screen
, if you are more lucky, please share how you proceeded
![]() | 6 | No.6 Revision |
I've just found a way to perform a remote launch from a python launch file using the ExecuteProcess launch action. There are several problems you're going to face if you go this way, so here are the workarounds I used to solve them (on Ubuntu 20.04).
First, let's state what we are trying to achieve:
ssh pi@192.168.0.20
from machine A (without a password, i.e. use ssh-keygen -t rsa -b 2048 && ssh-copy-id pi@192.168.0.20
first)drinks_hmi_launch.py
in drinks_hmi_bringup
package on machine B (we can launch it from machine B via ros2 launch drinks_hmi_bringup drinks_hmi_launch.py
)drinks_bringup_launch.py
in drinks_bringup
package on machine A which is supposed (among other actions) to launch drinks_hmi_launch.py
on machine BNow the following command should work from machine A, i.e. it launches the nodes, prints out output and can be terminated via SIGINT (Ctrl+C):
ssh -t pi@192.168.0.20 'bash -i -c "ros2 launch drinks_hmi_bringup drinks_hmi_launch.py"'
However, after putting it directly into ExecuteProcess
action in drinks_bringup_launch.py
, the process complains about not having a proper tty
console and the nodes on machine B are not terminated after terminating the ros2 launch drinks_bringup drinks_bringup_launch.py
process.
A workaround is to call the above command inside a detached screen
(use sudo apt install screen
if not present). This, however, raises two further problems:
screen
does not pass SIGINT from calling process to inner processes, so it does not terminate the nodes when Ctrl+C is pressed. However it can be terminated explicitly using a remote_launch_terminator
node which calls screen -S hmi -X quit
(see the complete solution below)screen
does not pass output from inner processes to calling process, so this needs to be done explicitly by redirecting inner output to outerThe complete solution is as follows:
/home/machine_A/drink_ws/src/launch_utils/launch_utils/remote_launch_terminator.py
:
import rclpy
from rclpy.node import Node
import os
def main(args=None):
rclpy.init(args=args)
node = Node('remote_launch_terminator')
node.declare_parameter('screen_pid', 'remote')
screen_pid = node.get_parameter('screen_pid').get_parameter_value().string_value
try:
rclpy.spin(node)
except:
pass
print('Terminating ' + screen_pid)
os.system('screen -S ' + screen_pid + ' -X quit')
if __name__ == '__main__':
main()
/home/machine_A/drink_ws/src/drinks_bringup/launch/drinks_bringup_launch.py
:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions.execute_process import ExecuteProcess
def generate_launch_description():
return LaunchDescription([
DeclareLaunchArgument(
'emulate_tty', default_value='true',
description='This must be true in order to make `screen` work'),
# other actions
# remote launch
ExecuteProcess(
name='hmi',
cmd=['{ outer_stdout=$(readlink -f /proc/self/fd/3); } 3>&1 && screen -DmS hmi bash -i -c "ssh -t pi@192.168.0.20 \'bash -i -c \\"ros2 launch drinks_hmi_bringup drinks_hmi_launch.py\\"\' > $outer_stdout"'],
output="screen",
shell=True
),
Node(
package='launch_utils',
executable='remote_launch_terminator',
name='remote_launch_terminator',
output='screen',
parameters=[{'screen_pid': 'hmi'}]
),
])
Hope this helps, cheers! ;)
Note: ExecuteProcess
action does not work inside OnShutdown
event, that's why the remote_launch_terminator
must be used
Note: emulate_tty:=true
didn't work for me either, that's why I had to use screen
, if you are more lucky, please share how you proceeded
![]() | 7 | No.7 Revision |
I've just found a way to perform a remote launch from a python launch file using the ExecuteProcess launch action. There are several problems you're going to face if you go this way, so here are the workarounds I used to solve them (on Ubuntu 20.04).
First, let's state what we are trying to achieve:
ssh pi@192.168.0.20
from machine A (without a password, i.e. use ssh-keygen -t rsa -b 2048 && ssh-copy-id pi@192.168.0.20
first)drinks_hmi_launch.py
in drinks_hmi_bringup
package on machine B (we can launch it from machine B via ros2 launch drinks_hmi_bringup drinks_hmi_launch.py
)drinks_bringup_launch.py
in drinks_bringup
package on machine A which is supposed (among other actions) to launch drinks_hmi_launch.py
on machine BNow the following command should work from machine A, i.e. it launches the nodes, prints out output and can be terminated via SIGINT (Ctrl+C):
ssh -t pi@192.168.0.20 'bash -i -c "ros2 launch drinks_hmi_bringup drinks_hmi_launch.py"'
However, after putting it directly into ExecuteProcess
action in drinks_bringup_launch.py
, the process complains about not having a proper tty
console and the nodes on machine B are not terminated after terminating the ros2 launch drinks_bringup drinks_bringup_launch.py
process.
A workaround is to call the above command inside a detached screen
(use sudo apt install screen
if not present). This, however, raises two further problems:
screen
does not pass SIGINT from calling process to inner processes, so it does not terminate the nodes when Ctrl+C is pressed. However it can be terminated explicitly using a remote_launch_terminator
node which calls screen -S hmi -X quit
(see the complete solution below)screen
does not pass output from inner processes to calling process, so this needs to be done explicitly by redirecting inner output to outerThe complete solution is as follows:
/home/machine_A/drink_ws/src/launch_utils/launch_utils/remote_launch_terminator.py
:
import rclpy
from rclpy.node import Node
import os
def main(args=None):
rclpy.init(args=args)
node = Node('remote_launch_terminator')
node.declare_parameter('screen_pid', 'remote')
screen_pid = node.get_parameter('screen_pid').get_parameter_value().string_value
try:
rclpy.spin(node)
except:
pass
print('Terminating ' + screen_pid)
os.system('screen -S ' + screen_pid + ' -X quit')
if __name__ == '__main__':
main()
/home/machine_A/drink_ws/src/drinks_bringup/launch/drinks_bringup_launch.py
:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions.execute_process import ExecuteProcess
def generate_launch_description():
return LaunchDescription([
DeclareLaunchArgument(
'emulate_tty', default_value='true',
description='This must be true in order to make `screen` work'),
# other actions
# remote launch
ExecuteProcess(
name='hmi',
cmd=['{ outer_stdout=$(readlink -f /proc/self/fd/3); } 3>&1 && screen -DmS hmi bash -i -c "ssh -t pi@192.168.0.20 \'bash -i -c \\"ros2 launch drinks_hmi_bringup drinks_hmi_launch.py\\"\' > $outer_stdout"'],
output="screen",
shell=True
shell=True,
emulate_tty=True
),
Node(
package='launch_utils',
executable='remote_launch_terminator',
name='remote_launch_terminator',
output='screen',
parameters=[{'screen_pid': 'hmi'}]
),
])
Hope this helps, cheers! ;)
Note: ExecuteProcess
action does not work inside OnShutdown
event, that's why the remote_launch_terminator
must be used
![]() | 8 | No.8 Revision |
I've just found a way to perform a remote launch from a python launch file using the ExecuteProcess launch action. There are several problems you're going to face if you go this way, so here are the workarounds I used to solve them (on Ubuntu 20.04).
First, let's state what we are trying to achieve:
ssh pi@192.168.0.20
from machine A (without a password, i.e. use ssh-keygen -t rsa -b 2048 && ssh-copy-id pi@192.168.0.20
first)drinks_hmi_launch.py
in drinks_hmi_bringup
package on machine B (we can launch it from machine B via ros2 launch drinks_hmi_bringup drinks_hmi_launch.py
)drinks_bringup_launch.py
in drinks_bringup
package on machine A which is supposed (among other actions) to launch drinks_hmi_launch.py
on machine BNow the following command should work from machine A, i.e. it launches the nodes, prints out output and can be terminated via SIGINT (Ctrl+C):
ssh -t pi@192.168.0.20 'bash -i -c "ros2 launch drinks_hmi_bringup drinks_hmi_launch.py"'
However, after putting it directly into ExecuteProcess
action in drinks_bringup_launch.py
, the process complains about not having a proper tty
console and the nodes on machine B are not terminated after terminating the ros2 launch drinks_bringup drinks_bringup_launch.py
process.
A workaround is to call the above command inside a detached screen
(use sudo apt install screen
if not present). This, however, raises two further problems:
screen
does not pass SIGINT from calling process to inner processes, so it does not terminate the nodes when Ctrl+C is pressed. However it can be terminated explicitly using a remote_launch_terminator
node which calls screen -S hmi -X quit
(see the complete solution below)screen
does not pass output from inner processes to calling process, so this needs to be done explicitly by redirecting inner output to outerThe complete solution is as follows:
/home/machine_A/drink_ws/src/launch_utils/launch_utils/remote_launch_terminator.py
:
import rclpy
from rclpy.node import Node
import os
def main(args=None):
rclpy.init(args=args)
node = Node('remote_launch_terminator')
node.declare_parameter('screen_pid', 'remote')
screen_pid = node.get_parameter('screen_pid').get_parameter_value().string_value
try:
rclpy.spin(node)
except:
pass
print('Terminating ' + screen_pid)
os.system('screen -S ' + screen_pid + ' -X quit')
if __name__ == '__main__':
main()
/home/machine_A/drink_ws/src/drinks_bringup/launch/drinks_bringup_launch.py
:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch_ros.actions import Node
from launch.actions.execute_process import ExecuteProcess
def generate_launch_description():
return LaunchDescription([
# other actions
# remote launch
ExecuteProcess(
name='hmi',
cmd=['{ outer_stdout=$(readlink -f /proc/self/fd/3); } 3>&1 && screen -DmS hmi bash -i -c "ssh -t pi@192.168.0.20 \'bash -i -c \\"ros2 launch drinks_hmi_bringup drinks_hmi_launch.py\\"\' > $outer_stdout"'],
output="screen",
shell=True,
emulate_tty=True
),
Node(
package='launch_utils',
executable='remote_launch_terminator',
name='remote_launch_terminator',
output='screen',
parameters=[{'screen_pid': 'hmi'}]
),
])
Hope this helps, cheers! ;)
Note: ExecuteProcess
action does not work inside OnShutdown
event, that's why the remote_launch_terminator
must be used