Spawn robot ROS2: spawn_robot.py now found on the libexec directory
I'm running ros2 Foxy in Ubuntu 20.04. I'm trying to spawn a robot, generated from a XACRO file into an empty world in gazebo. I've been launching gazebo with
ros2 launch gazebo_ros gazebo.launch.py
Then spawning my robot with
ros2 launch do_description spawn_robot.launch.py
But I keep getting the error
"executable 'spawn_robot.py' not found on the libexec directory '/home/samking7185/dev_ws/install/do_description/lib/do_description' "
Even though the spawn_robot.py shows up in the libexec directory. Do I need to do something else to convert this spawn_robot.py file to an actual executable?
I've create a python script to spawn a robot here, spawn_robot.py:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import sys
import rclpy
from gazebo_msgs.srv import SpawnEntity
def main(args=None):
rclpy.init(args=args)
node = rclpy.create_node('spawn entity')
cli = node.create_client(SpawnEntity, '/spawn_entity')
content = sys.argv[1]
req = SpawnEntity.Request()
req.name = "robot"
req.xml = content
req.robot_namespace = ""
req.reference_frame = "world"
while not cli.wait_for_service(timeout_sec=1.0):
node.get_logger().info('service not available, waiting again...')
future = cli.call_async(req)
rclpy.spin_until_future_complete(node, future)
if future.result() is not None:
node.get_logger().info(
'Result ' + str(future.result().success) + " " + future.result().status_message)
else:
node.get_logger().info('Service call failed %r' % (future.exception(),))
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
I've included the call to my executable in my launch file, spawn_robot.launch.py:
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
import xacro
def generate_launch_description():
use_sim_time = LaunchConfiguration('use_sim_time', default='true')
# urdf = os.path.join(get_package_share_directory('box_car_description'), 'robot/', 'box_bot.urdf')
# assert os.path.exists(urdf), "Thebox_bot.urdf doesnt exist in "+str(urdf)
xacro_file = os.path.join(get_package_share_directory('do_description'), 'urdf/', 'do_robot.xacro')
assert os.path.exists(xacro_file), "The do_robot.xacro doesnt exist in "+str(xacro_file)
robot_description_config = xacro.process_file(xacro_file)
robot_desc = robot_description_config.toxml()
return LaunchDescription([
DeclareLaunchArgument(
'use_sim_time',
default_value='false',
description='Use simulation (Gazebo) clock if true'),
Node(package='do_description', executable='spawn_robot.py', arguments=[robot_desc], output='screen'),
Node(
package="robot_state_publisher",
executable="robot_state_publisher",
name="robot_state_publisher",
parameters=[
{"robot_description": robot_desc}],
output="screen"),
])
And populated the PROGRAMS field in my CMAKE file:
cmake_minimum_required(VERSION 3.5)
project(do_description)
# Default to C99
if(NOT CMAKE_C_STANDARD)
set(CMAKE_C_STANDARD 99)
endif()
# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 14)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(ament_cmake REQUIRED)
find_package(urdf REQUIRED)
find_package(xacro REQUIRED)
if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
endif()
install(
DIRECTORY
launch
urdf
DESTINATION
share/${PROJECT_NAME}/
)
install(
PROGRAMS
launch/spawn_robot.py
DESTINATION lib/${PROJECT_NAME}
)
ament_package()