rclpy: Accessing ros2 launch args from main function
I have a node in a package that I set up using ros2 pkg create --build-type ament_python --node-name my_node my_package
my_node.py
looks like this:
import rclpy
from rclpy.node import Node
class MyNode(Node):
def __init__(self, arg):
super().__init__("my_node")
self.arg = arg
def main(args = None):
rclpy.init(args = args)
node = MyNode(9)
node.get_logger().info("Hello from my_node")
try:
rclpy.spin(node)
except:
pass
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
And my launch file looks like this:
from launch import LaunchDescription from launch_ros.actions import Node import launch
def generate_launch_description():
return LaunchDescription([
Node(
package='my_package',
node_namespace='test',
node_executable='my_node',
emulate_tty=True,
node_name='my_node',
),
launch.actions.DeclareLaunchArgument('arg1')
])
I am launching the node using ros2 launch -a ./launch/my_launch.py arg1:=9
How do I access arg1
from inside the main function? I want to use it to pass into the constructor of the Node.
Alternatively, is there another way to pass parameters into the main function? I just want to populate the args
in the def main(args = None)
function, but it needs to work when launched from a launch file.
Thanks
Asked by CraigH92 on 2020-05-20 03:58:32 UTC
Answers
same i cant find it anywhere... their is no way to put it to your node? you can only put whole launch files with
parameters= ["path/params.yaml"]
and if you want to just add a normal argument with:
arguments= ["test"]
you can but if you want to parse it from your launch file its just yikes since you cant just give a normal argument to the launch command it has to be:
arg1:= test
you have to do some big yikes stuff in python like getting argv[position] and than split on := get the second part and than use that in the arguments array and than in your main you have to do argv[position'] again.....
Asked by teunes1 on 2020-05-20 07:15:25 UTC
Comments
I've found a workaround. I'll post it as an answer here in a moment.
Asked by CraigH92 on 2020-05-20 08:44:08 UTC
I've found a workaround, but I don't think this is the idiomatic way to do it.
Use the launch file to accept an argument:
def generate_launch_description():
return LaunchDescription([
DeclareLaunchArgument("simulation_mode"),
Node(
package='my_package',
node_executable='my_node',
emulate_tty=True,
arguments = [launch.substitutions.LaunchConfiguration('simulation_mode')]
)
])
Then launch the launch file with:
ros2 launch -a launch/my_launch.py simulation_mode:=False
And then this argument can be used in the node like this:
import rclpy
from rclpy.node import Node
import sys
import typing
class MyNode(Node):
def __init__(self, simMode : bool):
super().__init__("my_node")
self.simMode = simMode
def main():
rclpy.init()
print(str(sys.argv[1]))
node = MyNode(sys.argv[1])
node.get_logger().info("Hello from my_node")
try:
rclpy.spin(node)
except:
pass
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
argv[1]
becomes the right-hand side of the assignment simulation_mode:=False
. It's a positional argument instead of a named argument, so it could be more prone to errors, but it will do until I find a better solution.
Asked by CraigH92 on 2020-05-20 08:50:05 UTC
Comments
@CraigH92 Did you find a better solution?
Asked by ljaniec on 2022-03-25 12:23:24 UTC
Comments