0
$\begingroup$

when we launched the following example in the Webots-ros2 tutorial, we got the following error, could you help us to get rid of that problem, thanks.

The example link: Setting up a robot simulation (Advanced)

ntukenmez3@ae-icps-407120:~/ros2_ws/src$ ros2 launch my_package robot_launch.py

[INFO] [launch]: All log files can be found below /home/ntukenmez3/.ros/log/2023-09-07-17-39-57-599365-ae-icps-407120-1653965
[INFO] [launch]: Default logging verbosity is set to INFO
WARNING: No valid Webots directory specified in `ROS2_WEBOTS_HOME` and `WEBOTS_HOME`, fallback to default installation folder /usr/local/webots.
[ERROR] [launch]: Caught exception in launch (see debug for traceback): Caught exception when trying to load file of format [py]: name 'Node' is not defined

my_robot_driver.py:

import rclpy
from geometry_msgs.msg import Twist

HALF_DISTANCE_BETWEEN_WHEELS = 0.045
WHEEL_RADIUS = 0.025

class MyRobotDriver:
    def init(self, webots_node, properties):
        self.__robot = webots_node.robot

        self.__left_motor = self.__robot.getDevice('left wheel motor')
        self.__right_motor = self.__robot.getDevice('right wheel motor')

        self.__left_motor.setPosition(float('inf'))
        self.__left_motor.setVelocity(0)

        self.__right_motor.setPosition(float('inf'))
        self.__right_motor.setVelocity(0)

        self.__target_twist = Twist()

        rclpy.init(args=None)
        self.__node = rclpy.create_node('my_robot_driver')
        self.__node.create_subscription(Twist, 'cmd_vel', self.__cmd_vel_callback, 1)

    def __cmd_vel_callback(self, twist):
        self.__target_twist = twist

    def step(self):
        rclpy.spin_once(self.__node, timeout_sec=0)

        forward_speed = self.__target_twist.linear.x
        angular_speed = self.__target_twist.angular.z

        command_motor_left = (forward_speed - angular_speed * HALF_DISTANCE_BETWEEN_WHEELS) / WHEEL_RADIUS
        command_motor_right = (forward_speed + angular_speed * HALF_DISTANCE_BETWEEN_WHEELS) / WHEEL_RADIUS

        self.__left_motor.setVelocity(command_motor_left)
        self.__right_motor.setVelocity(command_motor_right)

obstacle_avoider.py:

import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Range
from geometry_msgs.msg import Twist


MAX_RANGE = 0.15


class ObstacleAvoider(Node):
    def __init__(self):
        super().__init__('obstacle_avoider')

        self.__publisher = self.create_publisher(Twist, 'cmd_vel', 1)

        self.create_subscription(Range, 'left_sensor', self.__left_sensor_callback, 1)
        self.create_subscription(Range, 'right_sensor', self.__right_sensor_callback, 1)

    def __left_sensor_callback(self, message):
        self.__left_sensor_value = message.range

    def __right_sensor_callback(self, message):
        self.__right_sensor_value = message.range

        command_message = Twist()

        command_message.linear.x = 0.1

        if self.__left_sensor_value < 0.9 * MAX_RANGE or self.__right_sensor_value < 0.9 * MAX_RANGE:
            command_message.angular.z = -2.0

        self.__publisher.publish(command_message)


def main(args=None):
    rclpy.init(args=args)
    avoider = ObstacleAvoider()
    rclpy.spin(avoider)
    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    avoider.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

my_robot.urdf:

<?xml version="1.0" ?>
<robot name="My robot">
    <webots>
        <device reference="ds0" type="DistanceSensor">
            <ros>
                <topicName>/left_sensor</topicName>
                <alwaysOn>true</alwaysOn>
            </ros>
        </device>
        <device reference="ds1" type="DistanceSensor">
            <ros>
                <topicName>/right_sensor</topicName>
                <alwaysOn>true</alwaysOn>
            </ros>
        </device>
        <plugin type="my_package.my_robot_driver.MyRobotDriver" />
    </webots>
</robot>

robot_launch.py:

import os
import launch
from launch import LaunchDescription
from ament_index_python.packages import get_package_share_directory
from webots_ros2_driver.webots_launcher import WebotsLauncher
from webots_ros2_driver.webots_controller import WebotsController


def generate_launch_description():
    package_dir = get_package_share_directory('my_package')
    robot_description_path = os.path.join(package_dir, 'resource', 'my_robot.urdf')

    webots = WebotsLauncher(
        world=os.path.join(package_dir, 'worlds', 'my_world.wbt')
    )

    my_robot_driver = WebotsController(
        robot_name='my_robot',
        parameters=[
            {'robot_description': robot_description_path},
        ]
    )

    obstacle_avoider = Node(
        package='my_package',
        executable='obstacle_avoider',
    )

    return LaunchDescription([
        webots,
        my_robot_driver,
        obstacle_avoider,
        launch.actions.RegisterEventHandler(
            event_handler=launch.event_handlers.OnProcessExit(
                target_action=webots,
                on_exit=[launch.actions.EmitEvent(event=launch.events.Shutdown())],
            )
        )
    ])

setup.py:

from setuptools import find_packages, setup

package_name = 'my_package'
data_files = []
data_files.append(('share/ament_index/resource_index/packages', ['resource/' + package_name]))
data_files.append(('share/' + package_name + '/launch', ['launch/robot_launch.py']))
data_files.append(('share/' + package_name + '/worlds', ['worlds/my_world.wbt']))
data_files.append(('share/' + package_name + '/resource', ['resource/my_robot.urdf']))
data_files.append(('share/' + package_name, ['package.xml']))
setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=data_files,
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='user',
    maintainer_email='[email protected]',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'my_robot_driver = my_package.my_robot_driver:main',
            'obstacle_avoider = my_package.obstacle_avoider:main'
    ],
    },
)
$\endgroup$
3
  • $\begingroup$ We have several files, are there any options to upload here, thanks. $\endgroup$ Commented Sep 8, 2023 at 18:26
  • $\begingroup$ I'll edit the question now, thanks. $\endgroup$ Commented Sep 8, 2023 at 20:17
  • $\begingroup$ The related code was added. $\endgroup$ Commented Sep 8, 2023 at 20:42

3 Answers 3

0
$\begingroup$

Looking at the tutorial and without seeing your code I would say you're missing the Node definition, which is invoked with from rclpy.node import Node (as per the tutorial you mention), but please add your code nonetheless.

$\endgroup$
6
  • $\begingroup$ I added the code, could you check it, if possible. $\endgroup$ Commented Sep 8, 2023 at 20:27
  • $\begingroup$ It seems you're missing the line from rclpy.node import Node in your robot_launch.py, as it is used in the line where you define the obstacle_avoider. $\endgroup$
    – sniegs
    Commented Sep 14, 2023 at 9:08
  • $\begingroup$ I used rom launch_ros.actions import Node in the robot_launch.py. It works now. Is it same with your solution? How did you figure out this problem before, I mean How did you realize this is the problem, thanks. $\endgroup$ Commented Sep 19, 2023 at 15:30
  • $\begingroup$ I guess it's not exactly the same solution, as from launch_ros.actions import Node is the appropriate import for launch files. but it was still about imports, so there are similarities. In the future I would really suggest you follow the error messages first, before posting a question, as the line name 'Node' is not defined clearly states you're not defining Node. I just used the simple tools of Ctrl + F to find where the word Node is located and compared it with your posted code. I can edit my answer so you can accept it or you can write a new answer and accept it. $\endgroup$
    – sniegs
    Commented Sep 21, 2023 at 7:32
  • $\begingroup$ I'll try your solution. $\endgroup$ Commented Sep 21, 2023 at 22:38
0
$\begingroup$

The solution is:

in the launch.py file: from launch_ros.actions import Node

$\endgroup$
-1
$\begingroup$

Those instructions say to run the launch file from the ROS workspace and you're running it from the SCR folder. Try it exactly as the instruction call for. This might not correct your issue but you should always start by checking you're following the instructions.

$\endgroup$
2
  • $\begingroup$ Two things 1. "the SCR folde..." you mean the src folder?. 2. I am sorry but you can invoke ROS commands from anywhere. $\endgroup$
    – ravi
    Commented Sep 8, 2023 at 4:10
  • $\begingroup$ I could not get it this answer. $\endgroup$ Commented Sep 8, 2023 at 20:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.