In today’s video we are going to learn how to compile a ROS Message.
For that we are going to use Robot Ignite Academy, which is the best tool if you want Learn ROS Fast.
Before we start, if you are new to ROS and want to Learn ROS Fast, I highly recommend you to take any of the following courses on Robot Ignite Academy:
We love feedback, so, whether you like the video or not, please share your thoughts on the comments section below.
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 ROS Basic in 5 days course unit 4 as an example today.
Step2. Create a package
We’ll create a package for our code with the following command.
cd ~/catkin_ws/src
catkin_create_pkg financial_market rospy
We also need one folder for our message definition
cd financial_market
mkdir msg
Let’s call our message SharePrice.msg with the following definition
string name
float32 price
In the package.xml file, please uncomment the following part.
Then we compile the message with the following command
cd ~/catkin_ws
catkin_make
Please source the file after compile.
source devel/setup.bash
You can then check the message with
rosmsg info financial_market/SharePrice
In your python code, you can then add from financial_market.msg import SharePrice to use the message.
Want to learn more?
If you are interested in this topic, please check our ROS Basics In 5 Days (Python) course. You’ll learn how to create service and action message in ROS as well.
How does your robot know which way is forward? Is it in the x-axis, or y-axis? Positive or negative?
In this video we are going to look at the convention for coordinate frames. This convention is specified in REP 103 – Standard Units of Measure and Coordinate Conventions. In this part 1, we will look at the coordinate frame for linear motion.
Step 1. Create a project in ROS Development Studio(ROSDS)
According to the REP03 standard, the positive x means forward, the positive y means left and positive z means up. Although you can check the REP03 standard with your hand, it’s better to see how it works in ROS. The 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 launch a AR Drone simulation from Simulations->AR.Drone.
Step 2. Check it with the command
You can publish to the cmd_vel topic to move the drone with the following command.
rostopic pub -1 /cmd_vel [TAB] [TAB]
When you press tab while typing the command, ROS will do auto-compilation for you. You can see that it directly find the message type is called geometry msgs/Twist and there are linear x y z and angular x y x value in this message. To check it, change the value of linear x to some positive value. The drone will move forward like the REP03 standard said. You can also send to the linear y and z to check if it’s true. In the next post. We will talk about the angular part.
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.
In this series of videos we are going to learn how to use MoveIt! package with industrial robots. In this series we are going to use the Sawyer robot by Rethink Robotics.
Remember that you can follow all the steps with us at the same time by using the ROS Development Studio, without having to install anything in your system, and by using any operating system (yes, you can learn ROS with Windows!!!). The instructions and steps provided here can be also made in your local computer with a proper installation of ROS.
[Movelt! Camp] Week 1: Get the Robot up and running.
In the first week of Movelt! Camp, we will learn how to get the Sawyer simulation up and running.
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 sawyer_simulation.
Step 1. Clone and compile the simulation
You can find the Sawyer simulation in this github repo. Inside ROSDS, we put all the packages related to simulation to the simulation_ws. So, let’s clone the repo into it and compile.
cd ~/simulation_ws/src
git clone https://github.com/RethinkRobotics/sawyer_simulator.git
cd ~/simulation_ws/src
ws_tool init .
wstool merge sawyer_simulator/sawter_simulator.rosinstall
wstool updatecd
cd ~/simulation_ws
catkin_make
Step 2. Run the simulation
You can now launch the simulation from Simulations->select launch file->sawyer_pick_and_place_demo.launch. You should see the sawyer robot and a desk in the simulation window now.
[Movelt! Camp] Week 2: Create the Movelt! package for Robot.
In the second week, you will learn how to create the MoveIt! configuration package for Sawyer the robot, using the moveit_setup_assistant
Step 3. Reconfigure the gripper
To use the gripper in our simulation, we need to modify the sawyer.urdf.xarco file under the ~/simulaiton_ws/src/sawyer_robot/sawyer_description/urdf folder. Please change both the gazebo and electric_gripper tags to true.
In this video, we’ll use another simulation called sawyer_world. We also need to configure it. You can find the launch file sawyer_world.launch under the ~/simulation_ws/src/sawyer_simulator/launch folder. Remember to change the electric_gripper tag to true.
Then we can finally launch the simulation from Simulations->select launch file->sawyer_world.launch.
To check if the simulation works properly, let’s try to move the joint by sending a command to the /robot/right_joint_position_controller/joints/right_j1_controller/command topic with the following command.
You should see the robot moves a little, so the simulation is working properly.
It’s not practical if we need to send command ourselves everytime we want to move the robot. We can use the moveit package to simplify the process for us. To configure it, we can use a graphical tool provided by moveit with the following command.
Then go tho the Tools->graphical tool and select the urdf file we just defined.
Then, in the next page, we generate the collision matrix using the default value.
In the planning group page, let’s click add group and fill the group name as right_arm and select kdl solver, then click add joint.
Then select the joints as the following image
We also need one additional group called right_gripper
In the robot pose page, please set up a pose called tesing_pose for testing. You can choose any value you want.
In the end_effector page, please select the links as following image.
The last step is to generate the moveit package, let’s put it in a new folder called sawyer_moveit_config under the catkin_ws/src
Step 4. Use the moveit package
Now you can launch the package with the following command
roslaunch sawyer_moveit_config demo.launch
In the graphical tool, you should see the moveit, but it’s on a weird position. Please type the following command in a new shell to recenter the window.
wmctrl -r :ACTIVE: -e 0,65,24,1500,550
Then we can test the moveit package with our testing_pose
You should see the shadow of the robot move in the rviz tool. Then you can click plan to plan the trajectory move from the current state to the goal state- testing pose. Then you can click execute to execute the planned trajectory. How ever, this won’t move the robot in the gazebo simulation. We’ll talk about this in then next video.
ROS Manipulation is the term used to refer to any robot that manipulates something in its environment.
The main goal of this Course is to teach you the basic tools you need to know in order to be able to understand how ROS Manipulation works, and teach you how to implement it for any manipulator robot.
[Movelt! Camp] Week 3: How to connect your MoveIt Setup with a Real/ Simulated Robot.
For this week, we will be looking at how you can connect your MoveIt Setup from “MoveIt Camp: Week 2” to a Real/ Simulated Robot running ROS.
Step 5. Controller configuration
In order to move the robot in the gazebo simulation, we have to configure the controller. We can create a controller config file called controller.yaml file under the catkin_ws/src/sawyer_moveit_config folder with the following content
We also need one launch file to launch the controller and one for the connection. We can use the sawyer_moveit_controller_manager.launch.xml file that moveit prepared for us in the sawyer_moveit_config/launch folder and modify the content as the following.
<launch>
<!-- Set the param that trajectory_execution_manager needs to find the controller plugin -->
<arg name="moveit_controller_manager" default="moveit_simple_controller_manager/MoveItSimpleController"
<param name="moveit_controller_manager" value="$(arg moveit_controller_manager)" />
<!-- The rest of the params are specific to this plugin -->
<!-- If a controller manager is running (the generic one, not the MoveIt! one>
<arg name="controller_manager_name" default="simple_controller_manager" />
<param name="controller_manager_name value="$(arg controller_manager_name)" />
<!-- Flag indicating whether the controller manager should be used or not -->
<arg name="use_controller_manager" default="true" />
<param name="use_controller_manager" value="$(arg use_controller_manager)" />
<!-- load controller_list and controller_manager_ns -->
<rosparam file="$(find sawyer_moveit_config)/config/controllers.yaml"/>
</launch>
Another launch file we need is for the connection. We name it my_connect.launch with the following content
Then run the moveit package again with the controller.
roslaunch sawyer_moveit_config my_connect.launch
Try to plan the trajectory and execute again, you should see the robot move while executing the trajectory.
Then you should go to the moveit interface from Tools->Graphical tool. Please use the following commend to reconfigure the window.
wmctrl -r :ACTIVE: -e 0,65,24,1500,550
[Movelt! Camp] Week 4: MoveIt Planning Interface: Obstacles in the robot workspace and how to avoid them.
The Robot workspace can get cluttered and it most certainly is 90% of the time. As a result, it is necessary for the Robot to know its workcell in order to allow it to effect and or plan reachable goals. This week, we will focus on the MoveIt Planning Interface and how to send goal(s) and also make and execute a calculated plan(s).
Step 7. Some changes
We’ll start using the demo.launch file to launch the project. Please change the following part.
line 32: <rosparam param=”/source_list”>[/robot/joint_states]</rosparam>
line 41: <arg name=”fake_execution” value=”false”/>
<launch>
<!-- By default, we do not start a database (it can be large) -->
<arg name="db" default="false" />
<!-- Allow user to specify database location -->
<arg name="db_path" default="$(find sawyer_moveit_config)/default_warehouse_mongo_db" />
<!-- By default, we are not in debug mode -->
<arg name="debug" default="false" />
<!--
By default, hide joint_state_publisher's GUI
MoveIt!'s "demo" mode replaces the real robot driver with the joint_state_publisher.
The latter one maintains and publishes the current joint configuration of the simulated robot.
It also provides a GUI to move the simulated robot around "manually".
This corresponds to moving around the real robot without the use of MoveIt.
-->
<arg name="use_gui" default="false" />
<!-- Load the URDF, SRDF and other .yaml configuration files on the param server -->
<include file="$(find sawyer_moveit_config)/launch/planning_context.launch">
<arg name="load_robot_description" value="true"/>
</include>
<!-- If needed, broadcast static tf for robot root -->
<!-- We do not have a robot connected, so publish fake joint states -->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher">
<param name="/use_gui" value="$(arg use_gui)"/>
<rosparam param="/source_list">[/robot/joint_states]</rosparam>
</node>
<!-- Given the published joint states, publish tf for the robot links -->
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="true" output="screen" />
<!-- Run the main MoveIt executable without trajectory execution (we do not have controllers configured by default) -->
<include file="$(find sawyer_moveit_config)/launch/move_group.launch">
<arg name="allow_trajectory_execution" value="true"/>
<arg name="fake_execution" value="false"/>
<arg name="info" value="true"/>
<arg name="debug" value="$(arg debug)"/>
</include>
<!-- Run Rviz and load the default config to see the state of the move_group node -->
<include file="$(find sawyer_moveit_config)/launch/moveit_rviz.launch">
<arg name="config" value="true"/>
<arg name="debug" value="$(arg debug)"/>
</include>
<!-- If database loading was enabled, start mongodb as well -->
<include file="$(find sawyer_moveit_config)/launch/default_warehouse_db.launch" if="$(arg db)">
<arg name="moveit_warehouse_database_path" value="$(arg db_path)"/>
</include>
</launch>
The you can source the file and run the following script to enable the robot
This file includes the packages that we need for planning and create several objects. Then we create a planning.cpp file under the src folder with the following content.
#include <planning.h>
namespace my_planning
{
void MyPlanningClass::goToPoseGoal()
{
move_group.setPoseTarget(target_pose1);
bool success = (move_group.plan(my_plan) == moveit::planning_interface::MoveItErrorCode::SUCCESS);
if(!success) //execute
throw std::runtime_error("No plan found");
move_group.move(); //blocking
}
void MyPlanningClass::goToPoseGoal(geometry_msgs::Pose &pose)
{
move_group.setPoseTarget(pose);
ros::Duration(0.5).sleep();
bool success = (move_group.plan(my_plan) == moveit::planning_interface::MoveItErrorCode::SUCCESS);
/*while (!success) //keep trying until a plan is found
{
success = (move_group.plan(my_plan) == moveit::planning_interface::MoveItErrorCode::SUCCESS);
}*/
if(!success) //execute
throw std::runtime_error("No plan found");
move_group.move(); //blocking
}
void MyPlanningClass::goToJointState()
{
robot_state::RobotState current_state = *move_group.getCurrentState();
//moveit::core::RobotStatePtr current_state = move_group.getCurrentState();
std::vector<double> joint_positions;
joint_model_group = current_state.getJointModelGroup(PLANNING_GROUP);
current_state.copyJointGroupPositions(joint_model_group, joint_positions);
//joint_positions = move_group.getCurrentJointValues();
joint_positions[0] = -1.0;
joint_positions[3] = 0.7;
move_group.setJointValueTarget(joint_positions);
bool success = (move_group.plan(my_plan) == moveit::planning_interface::MoveItErrorCode::SUCCESS);
if(!success)
throw std::runtime_error("No plan found");
move_group.move(); //blocking
}
void MyPlanningClass::cartesianPath()
{
std::vector<geometry_msgs::Pose> waypoints;
waypoints.push_back(target_pose1);
geometry_msgs::Pose target_pose2 = target_pose1;
target_pose2.position.z -= 0.2;
waypoints.push_back(target_pose2);
target_pose2.position.y -= 0.2;
waypoints.push_back(target_pose2);
target_pose2.position.z += 0.2;
target_pose2.position.y += 0.2;
target_pose2.position.x -= 0.2;
waypoints.push_back(target_pose2);
move_group.setMaxVelocityScalingFactor(0.1);
// We want the Cartesian path to be interpolated at a resolution of 1 cm
// which is why we will specify 0.01 as the max step in Cartesian
// translation. We will specify the jump threshold as 0.0, effectively disabling it.
// Warning - disabling the jump threshold while operating real hardware can cause
// large unpredictable motions of redundant joints and could be a safety issue
moveit_msgs::RobotTrajectory trajectory;
const double jump_threshold = 0.0;
const double eef_step = 0.01;
double fraction = move_group.computeCartesianPath(waypoints, eef_step, jump_threshold, trajectory);
move_group.move();
ROS_INFO_STREAM("Percentage of path followed: " << fraction);
}
void MyPlanningClass::resetValues()
{
//set the start state and operational speed
move_group.setStartStateToCurrentState();
move_group.setMaxVelocityScalingFactor(1.0);
}
void MyPlanningClass::makeBox(std::string blk_name, double *pose)
{
moveit_msgs::CollisionObject box;
//set the relative frame
box.header.frame_id = move_group.getPlanningFrame();
box.id = blk_name;
shape_msgs::SolidPrimitive primitive;
primitive.type = primitive.BOX;
primitive.dimensions.resize(3);
primitive.dimensions[0] = 0.2;
primitive.dimensions[1] = 0.2;
primitive.dimensions[2] = 1.0;
geometry_msgs::Pose box_pose;
box_pose.orientation.w = 1.0;
box_pose.position.x = pose[0];
box_pose.position.y = pose[1];
box_pose.position.z = pose[2];
box.primitives.push_back(primitive);
box.primitive_poses.push_back(box_pose);
box.operation = box.ADD;
std::vector<moveit_msgs::CollisionObject> collisionObjects;
collisionObjects.push_back(box);
ros::Duration(2).sleep();
virtual_world.addCollisionObjects(collisionObjects);
ROS_INFO_STREAM("Added: " << blk_name);
}
void MyPlanningClass::addObjects()
{
double box_pose1[3] = {0.60, -0.67, 0.0,};
makeBox("block_1", box_pose1);
double box_pose2[3] = {0.0, 0.77, 0.0,};
makeBox("block_2", box_pose2);
}
void MyPlanningClass::removeObjects()
{
std::vector<std::string> object_ids;
object_ids.push_back("block_1");
object_ids.push_back("block_2");
virtual_world.removeCollisionObjects(object_ids);
}
}
Let’s create another file called run.cpp under the src folder with the following content
#include <planning.h>
int main(int argc, char **argv)
{
ros::init(argc, argv, "custom_interfacing");
ros::NodeHandle node_handle;
ros::AsyncSpinner spinner(2);
spinner.start();
if(argc != 2)
{
ROS_INFO(" ");
ROS_INFO("\tUsage:");
ROS_INFO(" ");
ROS_INFO("\trosrun planning run n");
return 1;
}
my_planning::MyPlanningClass my_planning_;
int selection = atoi(argv[1]);
switch(selection)
{
my_planning_.resetValues();
case 1:
my_planning_.goToPoseGoal();
break;
case 2:
my_planning_.goToJointState();
break;
case 3:
my_planning_.cartesianPath();
break;
case 4:
my_planning_.addObjects();
break;
case 5:
my_planning_.removeObjects();
}
spinner.stop();
return 0;
}
In order to compile the code, we have to change some parts in the CMakeLists.txt
cd ~/catkin_ws
catkin_make
source devel/setup.bash
rospack profile
Then we can run the executable with
rosrun planning run 3
[Movelt! Camp] Week 5: 3D Perception with MoveIt.
So you might have read about or thought of incorporating Point Cloud data into MoveIt. With this being the fifth and final week on MoveIt Camp, let’s do just that. We are going to integrate 3D Perception into MoveIt and also look at some related applications.
Pick a Shell from the Tools menu and run the following commands.
First, start the ROS master – we need this to run any ROS commands. We’re starting this program in the background:
user:~$ nohup roscore &
[1] 1501
user:~$ nohup: ignoring input and appending output to 'nohup.out'
user:~$
Before we proceed, let’s check the ROS topics currently available:
user:~$ rostopic list
/rosout
/rosout_agg
Now start the obiwan_pub.py program:
user:~$ cd catkin_ws/src
user:~/catkin_ws/src$ ./obiwan_pub.py
Again, check the list of available ROS topics. Pick another Shell from the Tools menu and run:
user:~$ rostopic list
/help_msg
/rosout
/rosout_agg
Now we have a new topic /help_msg, obviously created by the obiwan_pub.py program. Running it is the only thing we have done since the last time we checked the list of messages, right?
Okay, do not take my word for it; let’s spy on the /help_msg topic to confirm:
Now we know that that topic uses a message of type std_msgs/String and has a Publisher named /sos_2.
But what has this got to with the obiwan_pub node? Everything – let’s see that in the next step.
Step 3: Unravel the mysterious “Publisher” /sos_2
In the previous step, we saw that /sos_2 was listed as a Publisher on the topic /help_msg, and we suspected that this has to do with the obiwan_pub.py program. Now, let’s examine the obiwan_pub.py code to see if we have some clues.
obiwan_pub.py
#! /usr/bin/env python
import rospy
from std_msgs.msg import String
rospy.init_node("sos_2")
rate = rospy.Rate(2)
help_msg = String()
help_msg.data = "help me Obi-Wan Kenobi, you're my only hope"
pub = rospy.Publisher('/help_msg', String, queue_size = 1)
while not rospy.is_shutdown():
pub.publish(help_msg)
rate.sleep()
On line 6, we have the statement rospy.init_node("sos_2"), so we now know that:
/sos_2 was created by this program!
/sos_2 is a ROS node, because it says rospy.init_node...
Also on line 10, we have this statement: pub=rospy.Publisher('/help_msg',String,queue_size=1), confirming that:
The code actually creates a Publisher on the /help_msg topic. Bingo!
Step 4: Master the Concept – What is a ROS Publisher?
Combining all the points in the previous steps, we can see that a ROS Publisher…
is a ROS node (program).
creates a particular type of ROS message. In this case, it’s std_msgs/String, as can be seen on lines 4,7-8 of the code.
sends (publishes) a message over a channel called “topic”, as can be seen on lines 10 then 12 of the code.
In short, a ROS publisher is a ROS node that publishes a specific type of ROS message over a given ROS topic. “Interested” nodes (Subscribers) can access messages so published.
And that was it!
Extra: Video
Prefer to watch a video demonstrating the steps above? We have one for you below!
Related Resources
A previous video about ROS nodes: [irp posts=”10305″ name=”ROS in 5 mins – 005 – What is a ROS Node?”]
If you are a ROS beginner and want to learn ROS basics fast, we recommend you take any of the following courses on Robot Ignite Academy:
In today’s video we are going to see what is ROS Subscriber and how to see a list of them in a ROS Topic.
Before we start, if you are new to ROS and want to Learn ROS Fast, I highly recommend you to take any of the following courses on Robot Ignite Academy:
We love feedback, so, whether you like the video or not, please leave a comment on the comments section below so that we can interact and learn from each other.
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 ROS Basics in 5 Days course unit 0 as an example today.
Step2. What is ROS Subscriber?
Let’s start by visualizing the relationship between nodes with
rqt_graph
You can see that the nodes are communicating using the topics. A node can be a publisher publishing some topic or a subscriber to some topic. A topic can even have as many subscribers as you want.
Step 2: Examine the structure of the String message type
In the code, we used a ROS message type called String. Let’s examine the structure of this message.
Pick a Shell from the Tools menu and run the following command:
user:~$ rosmsg show String
[std_msgs/String]:
string data
[roseus/String]:
string data
Pick the IDE from the Tools menu, navigate to catkin_ws/src and open the obiwan_pub.pyprogram. You should see something like:
obiwan_pub.py
#! /usr/bin/env python
import rospy
from std_msgs.msg import String
rospy.init_node("sos_2")
rate = rospy.Rate(2)
help_msg = String()
help_msg.data = "help me Obi-Wan Kenobi, you're my only hope"
pub = rospy.Publisher('/help_msg', String, queue_size = 1)
while not rospy.is_shutdown():
pub.publish(help_msg)
rate.sleep()
We see that the String message is defined in two different packages (roseus and std_msgs), but we used the one defined in the std_msgs package, as can be seen on line 4 of the code block.
We also see that the String message has a single attribute named data, which should be a string. So, when creating a message of type String, we need to set a value for data, and the value must be a string (lines 8-9).
Now also take a look at the obiwan_sub.py program:
We see that on lines 6-7 when accessing a message of type String, we take it for granted that it has an attribute data, therefore we could reference msg.data.
Step 3: Determine the proper ROS message type to use for a given topic
In the obiwan_pub program above, we created a new topic called /help_msg. What if you are trying to publish to an existing topic and you are not sure the kind of message to send over it or you’re trying to subscribe to the topic and want to know what to expect? PS: every topic has a message type you must publish over it, or things will not work properly.
Let’s pretend we didn’t know the kind of message /help_msg uses – we just know the name of the topic. Let’s see how we can find out:
Start the obiwan_pub node, so that the help_msg topic is created.
user:~$ cd catkin_ws/src
user:~/catkin_ws/src$ ./obiwan_pub.py
Now pick another Shell from the Tools menu and run rostopic info /help_msg to find out the type of message it uses:
So now we see that it uses the message std_msgs/String, and we can know about this message by running. Here, we are specifying the package name (std_msgs) also, since we know it for sure:
user:~$ rosmsg show std_msgs/String
string data
Step 4: Wrapping it up
In summary, in order to use a ROS message properly, you need to know its structure. If you are working with an existing ROS topic, you can check what kind of message it uses and then check the structure of that message.
Extra: Video
Prefer to watch a video demonstrating the steps above? We have one for you below!
Related Resources
If you are a ROS beginner and want to learn ROS basics fast, we recommend you take any of the following courses on Robot Ignite Academy: