Linux Basics in ROS 2

dive dapper in packages
now to create a catkin package $catkin_create_pkg [dependency1 dependency2 …], there are just two files in it: just two files: CMakeLists.txt and package.xml. There are lot of packages: scripts, src, msg, srv(for service message definition), include (headers/libraries that are needed as dependencies), config, launch, other folders may include urdf, meshes, worlds.
Then the major task is to write ROS Nodes. What are ROS Nodes? In ROS (Robot Operating System), a Node is the smallest executable unit of computing. How ROS publishes work in C++? Publishers allow a node to send messages to a topic, a typical publisher in ROS looks like ros::Publisher pub1 = n.advertise(“/topic_name”, queue_size); the pub1 object is a publisher object instantiated from the ros::Publisher class. we need NodeHandle to communicate with ROS master in C++, here the node handle is n, which will fully initialize the node.
then advertise() function is used communicate with ROS and inform that you want to publish a mesage on a given topic name, message_type could be string std_msgs::String. (In C++, the double colon (::) is a scope resolution operator. It’s used to identify and specify the context in which an identifier is defined.

In the case of std_msgs::String, std_msgs is the namespace (or scope), and String is a class or type within that namespace. It means the String class is located in the std_msgs namespace.

In the context of ROS (Robot Operating System), std_msgs::String refers to a String data type from the std_msgs package, which is a standard package in ROS providing many basic message types.)

Once the publisher object pub1 has been created, as above, a message with the specified data type can be published as follows: pub1.publish(msg);

Start from the simple_mover node, The goal of the simple_mover node is to command each joint in the simple arm and make it swing between -pi/2 to pi/2 over time. to do so, it must publish joint angle command messages to the following topics:

  1. /simple_arm/joint_1_position_controller/command, note to comand joint 1 to move counter-clockwise and units in radians.
  2. /simple_arm/joint_2_position_controller/command, commanding joint 2 to move counter clockwise, units radians.
    To create a new node, first create the src dirctory within the simple_arm package $cd /home/workspace/catkin_ws/src/simple_arm/ $ mkdir src
    then add scripts to the pakcage $touch simple_mover.cpp
#include "ros/ros.h"
#include "std_msgs/Float64.h"
int main(int argc, char** argv)
{
    // Initialize the arm_mover node
    ros::init(argc, argv, "arm_mover");
    // Create a handle to the arm_mover node
    ros::NodeHandle n;
    // Create a publisher that can publish a std_msgs::Float64 message on the /simple_arm/joint_1_position_controller/command topic
    ros::Publisher joint1_pub = n.advertise<std_msgs::Float64>("/simple_arm/joint_1_position_controller/command", 10);
    // Create a publisher that can publish a std_msgs::Float64 message on the /simple_arm/joint_2_position_controller/command topic
    ros::Publisher joint2_pub = n.advertise<std_msgs::Float64>("/simple_arm/joint_2_position_controller/command", 10);
    // Set loop frequency of 10Hz
    ros::Rate loop_rate(10);
    int start_time, elapsed;
    // Get ROS start time
    while (not start_time) {
        start_time = ros::Time::now().toSec();
    }
    while (ros::ok()) {
        // Get ROS elapsed time
        elapsed = ros::Time::now().toSec() - start_time;
        // Set the arm joint angles
        std_msgs::Float64 joint1_angle, joint2_angle;
        joint1_angle.data = sin(2  *M_PI*  0.1  *elapsed)*  (M_PI / 2);
        joint2_angle.data = sin(2  *M_PI*  0.1  *elapsed)*  (M_PI / 2);
        // Publish the arm joint angles
        joint1_pub.publish(joint1_angle);
        joint2_pub.publish(joint2_angle);
        // Sleep for the time remaining until 10 Hz is reached
        loop_rate.sleep();
    }
    return 0;
}

Now to compile the C++ script, first modifying CMakelists.txt, then build the package, then run simple_mover. CMake is the build tool and CMakeLists.txt is a CMake script used by catkin. similar concept of makefiles. now use gedit to oepn it $gedit CMakeLists.txt, find_package() macro lists std_msgs, message_generation and controller_manager as required packages, it looks as
find_package(catkin REQUIRED COMPONENTS std_msgs message_generation controller_manager ), then add the following at the bottom of the file
include_directories(include ${catkin_INCLUDE_DIRS}) add_executable(simple_mover src/simple_mover.cpp) target_link_libraries(simple_mover ${catkin_LIBRARIES}) add_dependencies(simple_mover simple_arm_generate_messages_cpp)

add all the linked libraries to the compiler
add_dependencies(node_name package_name_generate_messages_cpp)
launch simple_arm as follows:
$ cd /home/workspace/catkin_ws/
$ source devel/setup.bash
$ roslaunch simple_arm robot_spawn.launch

then open a new terminal and type
$ cd/home/workstapce/catkin_ws/
$ source devel/setup.bash
$ rosrun simple_arm simple_mover

ROS Services Now that you’ve written your first ROS node, you’ve seen how publishing to a topic works, and you were able to control the robotic arm by publishing to the /simple_arm/joint_1_position_controller/command topic and /simple_arm/joint_2_position_controller/command topic. Next, we’ll see another node called arm_mover, which implements the safe_move service to allow service calls to control the arm.

ROS service server can be created using the following definition format:
ros :: ServiceServer service = n.advertiseService(‘service_name’, handler);
Using Services by command line: $ rosservice call service_name “request”, then wait for an answer

another way to use ROS service programmatically from within a node:
ros::ServiceClient client = n.serviceClient(“service_name”);
send reqeusts client.call(srv); // request a service

break down the line ros::ServiceServer service = n.advertiseService('service_name', handler);:

  1. ros::ServiceServer service: This is declaring a variable service of the type ros::ServiceServer. The ros::ServiceServer is a ROS type that allows a node to provide a service. A service is a function or action that your ROS node can do when it is asked to.
  2. n.advertiseService('service_name', handler);: This is a function call that tells ROS that the node n is providing a service. This service can be requested by other nodes in the system.
    • 'service_name' is the name of the service that you’re providing. Other nodes in your system will use this name to call your service.
    • handler is the function that will be called when your service is requested. This function will contain the actual code that performs whatever action the service is supposed to provide.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.