[ROS Q&A] 145 – Customize plot axis with rqt_multiplot

In this video we are going to see how to customize the axis of your plot, using the rqt_multiplot tool.

Step1. Create a project in Robot Ignite Academy(RIA)

We have the best online ROS course available in RIA. It helps you learn ROS in the easiest way without setting up ROS environment locally. The only thing you need is a browser! Create an account here and start to browse the trial course for free now! We’ll use the Using OpenAI with ROS unit 0 as an example today.

Step2. Plot with rqt_plot and rqt_multiplot

Let’s start by running the example

roslaunch cartpole_v0_training start_training.launch

You’ll see that the robot starts to move and learning to stand. The reward of each episode is publishing to the topic /openai/reward. You can see that with the following command

rostopic echo /openai/reward

It’s hard to tell the trend of the reward in the terminal. It will be nicer if we can plot it into a figure. We can use the rqt_plot tool to do it. You can run the following command to open rqt_plot.

rosrun rqt_plot rqt_plot

Then you have to open the graphical tool by click the monitor icon next to the simulation.

You can select the topic that you want to plot in rqt_plot. Let’s type openai/reward.  The tool plot the reward for us, but it’s not updating.

With rqt_plot, the x-axis is always the timestamp. The problem is, in openai gym, the environment keeps resetting itself, so the reward value is overriding itself.

To solve this problem, we need another tool called rqt_multiplot.

rosrun rqt_multiplot rqt_multiplot

After opening it, click on the configure plot button(gear shape) and select the /openai/reward topic again. We select the episode number as our x-axis and the reward as our y-axis. Then hit enter.

Select the curve and click ok. Then click the play button. You should see it’s plotting. The rewards over episodes plot show the training progress much better in this case!

Want to learn more?

If you are interested in this topic, you can check our Using OpenAI with ROS Online Course.

 

Edit by: Tony Huang


RELATED LINKS

ROS Development Studio (RDS)
Robot Ignite Academy
Using OpenAI with ROS Online Course


Feedback

Did you like this video? Do you have questions about what is explained? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.

If you want to learn about other ROS topics, please let us know on the comments area and we will do a video about it.

[ROS Q&A] 144 – What is the difference between ROS topics and messages?

In this video we are going to explain and show in a practical way the difference between ROS topics and messages.

We show two nodes running, one publishing to a given topic and another subscribing to this same topic. RQT graph is used to see the big picture of the environment.

 

Step 0. Create a project in ROS Development Studio(ROSDS)

ROSDS helps you follow our tutorial in a fast pace without dealing without setting up an environment locally. If you haven’t had an account yet, you can create a free account here. Let’s create a new project and call it ros_q_a_topics_messages.

Step 1. Difference between ros topic and ros message

We’ll start by creating a package for the code in catkin_ws

cd catkin_ws/src
catkin_create_pkg my_pkg rospy std_msgs

Let’s also create a scripts folder for our scripts. Then two script called my_subscriber.py and my_publisher.py file in it with the following content.

#!/usr/bin/env python

import rospy
from std_msgs.msg import String

def main():
    pub = rospy.Publisher('my_topic', String, queue_size=10)
    rospy.init_node('my_publisher')

    rate = rospy.Rate(1)
    
    while not rospy.is_shutdown():
        hello_str = 'hello world %s' % rospy.get_time()

        rospy.loginfo(hello_str)

        pub.publish(hello_str)

        rate.sleep()

if __name__ == '__main__':
    try:
        main()
    except rospy.ROSInterruptExeception:
        pass

Basically, a message is data through a channel called topic. In this code, the message is String type and the topic is called my_topic.

#!/usr/bin/env python

import rospy
from std_msgs import String

def main():
    pub = rospy.Publisher('my_topic', String, queue_size = 10)

    rospy.init_node('my_publisher')

    rate = rospy.Rate(1)

    while not rospy.is_shutdown():
        hello_str = "hello world %s" % rospy.get_time()

        rospy.loginfo(hello_str)

        pub.publish(hello_str)

        rate.sleep()

if __name__ == '__main__' :
    try:
        main()
    except rospy.ROSInterruptExeception:
        pass

This script established a subscriber for the message through the topic my_topic.

To run the code, we have to give the scripts permission to execute with chmod +x my_publisher.py and chmod +x my_subscriber.py

Then we can run it with

cd catkin_ws
catkin_make
source devel/setup.bash
rosrun my_pkg my_publisher.py

You should see the publisher is publishing message into the topic.

Open another shell and run

rosrun my_pkg my_subscriber.py

Open the third shell and type rqt_graph , then go to Tools->graphical tool to open the GUI.

You should see the nodes are marked with circles. You can find the /my_publisher and /my_subscriber nodes in the graph.

The topic is marked with the square. In this example, the topic is called my_topic. The two node is communicating though this topic.

Want to learn more?

If you are interested in learning ROS, please check our ROS Basics Python course.

 

Edit by: Tony Huang


RELATED LINKS

▸ Original question: https://answers.ros.org/question/63511/what-is-the-difference-between-a-topic-and-a-message/
ROS Development Studio (ROSDS)
Robot Ignite Academy
ROS Basics Python
ROS Basics C++


Feedback

Did you like this video? Do you have questions about what is explained? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.

If you want to learn about other ROS topics, please let us know on the comments area and we will do a video about it.

[ROS Projects] – Use OpenAI_ROS with TurtleBot2 Step-by-Step #Part 2

[ROS Projects] – Use OpenAI_ROS with TurtleBot2 Step-by-Step #Part 2

 

In this second part, you will continue by creating your own TaskEnvironment for a different TurtleBot simulation environment with a wall.
You will create this Task Env that allows the robot to learn how to reach a certain position in the map without running into the wall.

Related links and resources:

[irp posts=”10259″ name=”[ROS Projects] – Use OpenAI_ROS with Turtlebot2 Step by Step #Part 1″]

[ROS Q&A] 143 – How to connect MoveIt to the Robot

In this tutorial of ROS Q&A Series, we’re going to see how to connect movit to the (simulated, in this case) robot.

This is a video trying to answer the following question posted at the ROS answers forum: https://answers.ros.org/question/298508/how-do-i-interact-the-actual-robot-with-visualization-by-rviz-in-moveit/

Step 1. Create a project in ROS Development Studio(ROSDS)

ROSDS helps you follow our tutorial in a fast pace without dealing without setting up an environment locally. If you haven’t had an account yet, you can create a free account here. Let’s create a new project and call it moveit_real.

Step 2. Use the moveit package

In this tutorial, we have already preconfigured the Sia Robot and moveit package for it. If you want to know how to configure the moveit package, please check our ROS-Industrial 101 course. If you launch the moveit package, you’ll see that no matter what trajectory you are planning in the moveit, it won’t affect the real robot(we use a simulation as an example here). That’s because of missing controllers. To apply the controller, a file called controller.yaml should be created in the config folder of the robot. We also have to specify the controller type in the sia10f.urdf file.  In order to use the controller, a transmission tag should be added to the urdf. You’ll also need a joint_names.yaml file in the config folder which defines the joints will be controlled. In the end, you’ll need to create launch files to launch the package.

Step 3. Plan the trajectory

After launching the controller, you can plan the trajectory with moveit package. The robot should move as the planning in the moveit package.

Want to learn more?

If you are interested in this topic and want to learn how to configure the moveit package and all the files you need to move the robot, please check our ROS-Industrial 101 course.

 

Edit by: Tony Huang

 

Related Courses

ROS Manipulation Course Cover - ROS Online Courses - Robot Ignite Academy

ROS Manipulation Course


Feedback

Did you like this video? Do you have questions about what is explained? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.

If you want to learn about other ROS topics, please let us know on the comments area and we will do a video about it.

[ROS Q&A] 142 – How to create launch file for URDF and open in Gazebo

In this video, we are going to show how to create a launch file to spawn a URDF robot model in a given gazebo world.

Up to the end of the video, you will be able to spawn any robot model you may have described in URDF in Gazebo.

Step 1. Create a project in ROS Development Studio(ROSDS)

ROSDS helps you follow our tutorial in a fast pace without dealing without setting up an environment locally. If you haven’t had an account yet, you can create a free account here. Let’s create a new project and call it launch_urdf_model_in_gazebo.

Step 2. Create a package

Let’s create a ROS package for our code by using the following command.

cd ~/catkin_ws/src
catkin_create_pkg my_robot_urdf rospy

Then we create a m2wr.urdf file under the my_robot_urdf/urdf folder.

<?xml version="1.0"?>
<robot name="m2wr" xmlns:xacro="http://www.ros.org/wiki/xacro">
  <material name="black">
    <color rgba="0.0 0.0 0.0 1.0"/>
  </material>
  <material name="blue">
    <color rgba="0.203125 0.23828125 0.28515625 1.0"/>
  </material>
  <material name="green">
    <color rgba="0.0 0.8 0.0 1.0"/>
  </material>
  <material name="grey">
    <color rgba="0.2 0.2 0.2 1.0"/>
  </material>
  <material name="orange">
    <color rgba="1.0 0.423529411765 0.0392156862745 1.0"/>
  </material>
  <material name="brown">
    <color rgba="0.870588235294 0.811764705882 0.764705882353 1.0"/>
  </material>
  <material name="red">
    <color rgba="0.80078125 0.12890625 0.1328125 1.0"/>
  </material>
  <material name="white">
    <color rgba="1.0 1.0 1.0 1.0"/>
  </material>
  
    <gazebo reference="link_chassis">
    <material>Gazebo/Orange</material>
  </gazebo>
  <gazebo reference="link_left_wheel">
    <material>Gazebo/Blue</material>
  </gazebo>
  <gazebo reference="link_right_wheel">
    <material>Gazebo/Blue</material>
  </gazebo>
  
  <gazebo>
    <plugin filename="libgazebo_ros_diff_drive.so" name="differential_drive_controller">
      <alwaysOn>true</alwaysOn>
      <updateRate>20</updateRate>
      <leftJoint>joint_left_wheel</leftJoint>
      <rightJoint>joint_right_wheel</rightJoint>
      <wheelSeparation>0.4</wheelSeparation>
      <wheelDiameter>0.2</wheelDiameter>
      <torque>0.1</torque>
      <commandTopic>cmd_vel</commandTopic>
      <odometryTopic>odom</odometryTopic>
      <odometryFrame>odom</odometryFrame>
      <robotBaseFrame>link_chassis</robotBaseFrame>
    </plugin>
  </gazebo>
  
  <gazebo reference="sensor_laser">
    <sensor type="ray" name="head_hokuyo_sensor">
      <pose>0 0 0 0 0 0</pose>
      <visualize>false</visualize>
      <update_rate>20</update_rate>
      <ray>
        <scan>
          <horizontal>
            <samples>720</samples>
            <resolution>1</resolution>
            <min_angle>-1.570796</min_angle>
            <max_angle>1.570796</max_angle>
          </horizontal>
        </scan>
        <range>
          <min>0.10</min>
          <max>10.0</max>
          <resolution>0.01</resolution>
        </range>
        <noise>
          <type>gaussian</type>
          <mean>0.0</mean>
          <stddev>0.01</stddev>
        </noise>
      </ray>
      <plugin name="gazebo_ros_head_hokuyo_controller" filename="libgazebo_ros_laser.so">
        <topicName>/m2wr/laser/scan</topicName>
        <frameName>sensor_laser</frameName>
      </plugin>
    </sensor>
  </gazebo>
  
   <link name="link_chassis">
    <!-- pose and inertial -->
    <pose>0 0 0.1 0 0 0</pose>
    <inertial>
      <mass value="5"/>
      <origin rpy="0 0 0" xyz="0 0 0.1"/>
      <inertia ixx="0.0395416666667" ixy="0" ixz="0" iyy="0.106208333333" iyz="0" izz="0.106208333333"/>
    </inertial>
    <!-- body -->
    <collision name="collision_chassis">
      <geometry>
        <box size="0.5 0.3 0.07"/>
      </geometry>
    </collision>
    <visual>
      <origin rpy="0 0 0" xyz="0 0 0"/>
      <geometry>
        <box size="0.5 0.3 0.07"/>
      </geometry>
      <material name="blue"/>
    </visual>
    <!-- caster front -->
    <collision name="caster_front_collision">
      <origin rpy=" 0 0 0" xyz="0.35 0 -0.05"/>
      <geometry>
        <sphere radius="0.05"/>
      </geometry>
      <surface>
        <friction>
          <ode>
            <mu>0</mu>
            <mu2>0</mu2>
            <slip1>1.0</slip1>
            <slip2>1.0</slip2>
          </ode>
        </friction>
      </surface>
    </collision>
    <visual name="caster_front_visual">
      <origin rpy=" 0 0 0" xyz="0.2 0 -0.05"/>
      <geometry>
        <sphere radius="0.05"/>
      </geometry>
    </visual>
  </link>
  
  <link name="link_right_wheel">
    <inertial>
      <mass value="0.2"/>
      <origin rpy="0 1.5707 1.5707" xyz="0 0 0"/>
      <inertia ixx="0.000526666666667" ixy="0" ixz="0" iyy="0.000526666666667" iyz="0" izz="0.001"/>
    </inertial>
    <collision name="link_right_wheel_collision">
      <origin rpy="0 1.5707 1.5707" xyz="0 0 0"/>
      <geometry>
        <cylinder length="0.04" radius="0.1"/>
      </geometry>
    </collision>
    <visual name="link_right_wheel_visual">
      <origin rpy="0 1.5707 1.5707" xyz="0 0 0"/>
      <geometry>
        <cylinder length="0.04" radius="0.1"/>
      </geometry>
    </visual>
  </link>
  
  <joint name="joint_right_wheel" type="continuous">
    <origin rpy="0 0 0" xyz="-0.05 0.15 0"/>
    <child link="link_right_wheel"/>
    <parent link="link_chassis"/>
    <axis rpy="0 0 0" xyz="0 1 0"/>
    <limit effort="10000" velocity="1000"/>
    <joint_properties damping="1.0" friction="1.0"/>
  </joint>
  
  <link name="link_left_wheel">
    <inertial>
      <mass value="0.2"/>
      <origin rpy="0 1.5707 1.5707" xyz="0 0 0"/>
      <inertia ixx="0.000526666666667" ixy="0" ixz="0" iyy="0.000526666666667" iyz="0" izz="0.001"/>
    </inertial>
    <collision name="link_left_wheel_collision">
      <origin rpy="0 1.5707 1.5707" xyz="0 0 0"/>
      <geometry>
        <cylinder length="0.04" radius="0.1"/>
      </geometry>
    </collision>
    <visual name="link_left_wheel_visual">
      <origin rpy="0 1.5707 1.5707" xyz="0 0 0"/>
      <geometry>
        <cylinder length="0.04" radius="0.1"/>
      </geometry>
    </visual>
  </link>
  
  <joint name="joint_left_wheel" type="continuous">
    <origin rpy="0 0 0" xyz="-0.05 -0.15 0"/>
    <child link="link_left_wheel"/>
    <parent link="link_chassis"/>
    <axis rpy="0 0 0" xyz="0 1 0"/>
    <limit effort="10000" velocity="1000"/>
    <joint_properties damping="1.0" friction="1.0"/>
  </joint>
  
  
</robot>

This file defines the physical parameters of our robot and the type of controller that we want to use.

We’ll create a launch file to launch this description. We name it spawn_urdf.launch and put it under the launch folder.

<?xml version="1.0" encoding="UTF-8"?>
<launch>
    <param name="robot_description" command="cat '$(find my_robot_urdf)/urdf/m2wr.urdf'" />
    
    <node name="mybot_spawn" pkg="gazebo_ros" type="spawn_model" output="screen"
          args="-urdf -param robot_description -model m2wr" />
          
</launch>

You can see that the launch file try to find the description file from the my_robot_urdf package.

Now we have to compile it with the following command

cd ~/catkin_ws
catkin_make
source devel/setup.bash

Now you can launch an empty world simulation from Simulations->Empty, then use the command roslaunch my_robot_urdf spawn_urdf.launch  to spawn the robot!

If you are interested in this topic and want to learn more about URDF, please check our Robot Creation with URDF course.

 

Edit by: Tony Huang

Related resources and links:

[ROS Q&A] 141 – How to Modify Logger Level in ROS (C++)

 

In this video we are going to see how to modify the Logger Level in ROS using C++.

This is a video trying to answer the following question posted at the ROS answers forum: https://answers.ros.org/question/98521/problems-with-logger-levels/

RELATED LINKS

▸ Original question: https://answers.ros.org/question/98521/problems-with-logger-levels/
ROS Development Studio (RDS)
Robot Ignite Academy

Step 1. Create a project in ROS Development Studio(ROSDS)

ROSDS helps you follow our tutorial in a fast pace without dealing without setting up an environment locally. If you haven’t had an account yet, you can create a free account here.

Step 2. Create package and file

Let’s create a package for testing in RDS by typing the following command.

cd ~/catkin_ws/src
catkin_create_pkg logs_test roscpp

Then we create a source file under the logs_test/src directory called logs.cpp with the following content.

#include <ros/ros.h>
#include <ros/console.h>
#include <stdlib.h>

int main(int argc, char** argv) {
    if (ros::console::set_logger_level(ROSCONSOLE_DEFAULT_NAME, ros::console::levels::Debug))
    {
        ros::console::notifyLoggerLevelsChanged();
    }
    
    ros::init(argc,argv,"log_demo");
    ros::NodeHandle nh;
    ros::Rate loop_rate(0.5); // We create a Rate object of 2Hz
    
    while (ros::ok()) //Endless loop until Ctrl+c
    {
        ROS_DEBUG("This is a DEBUG message");
        ROS_INFO("This is a INFO message");
        ROS_WARN("This is a WARN message");
        ROS_ERROR("This is a ERROR message");
        ROS_FATAL("This is a FATAL message");
        
        loop_rate.sleep();
        ros::spinOnce();
    }
    
    return 0;
}

In the CMakeLists.txt, please change the following content in build part.

...

## Declare a C++ executable
## With catkin_make all packages are built within a single CMake context
## The recommended prefix ensures that target names across packages don't collide
add_executable(logs_test src/logs.cpp)

...

## Add cmake target dependencies of the executable
## same as for the library above
add_dependencies(logs_test ${logs_test_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

## Specify libraries to link a library or executable target against
target_link_libraries(logs_test
  ${catkin_LIBRARIES}
)

...

Then we can compile the code with the following command

cd ~/catkin_ws
catkin_make

While waiting for compilation, let’s create a launch file to launch the code much easier. Please create a launch folder under the logs_test directory and create a file called logs_test.launch under it with the following code.

<launch>
    <node pkg = "logs_test" type="logs_test" name="log_demo" output="screen" />
</launch>

Then we can run the following command in shell to launch the node.

roslaunch logs_test logs_test.launch

Since we set the lowest level logger in our code(DEBUG) we’ll see all 5 levels logs are printing. If you change it(e.g. to ERROR) and compile again, you should only see the ERROR and FATAL message.

 

Edit by: Tony Huang


Feedback

Did you like this video? Do you have questions about what is explained? Whatever the case, please leave a comment on the comments section below, so we can interact and learn from each other.

If you want to learn about other ROS topics, please let us know on the comments area and we will do a video about it.

Pin It on Pinterest