Showing posts with label ROS. Show all posts
Showing posts with label ROS. Show all posts

Monday, December 12, 2022

How to read an array from a ROS1 launch file into a C++ vector variable

I was having problems reading an array of doubles in a ROS launch file into a vector variable in a C++ ROS1 program node. After some digging around, I found I was doing it the wrong way; instead of using the <param> tag in the ROS launch file, I should be using the <rosparam> tag. 

The example ROS launch file listing shows the correct way to enter an array, e.g. [0.01, 0.1, 0.2] with the <rosparam> tag:

?xml version="1.0" encoding="UTF-8"?>
<launch>
  <node pkg="learning_tutorial" type="my_node" name="my_node">
        <param name="my_string_param" value="hello" />
        <rosparam param="my_array_param">[0.01, 0.1, 0.2]</rosparam>
  </node>
</launch>

Then in the ROS C++ code, I could do the following to read the array:

// ...etc...

using namespace ros;
using namespace std;

vector<double> myArrayParam;
NodeHandle nh;

// Read the my_array_param from the launch file into the myArrayParam variable
nh.param<vector<double>> ( "my_array_param", myArrayParam, { 1, 2, 3});

// Just print out the array parameter
ROS_INFO ( "My array: %f, %f, %f", myArrayParam[0], myArrayParam[1], myArrayParam[2]);
 
// ...etc...

Hope this helps somebody.


Monday, October 11, 2021

Using rostopic to simulate publishing odometry topic messages

While developing (Robotic OS) ROS1 node callbacks, and you don't have any inertial motion devices on hand, you can use the rostopic utility command with pub option to simulate the publishing of odometry messages. Basically, before being able to use the command, you have to find out how the odometry message is structured. Once you have the fields - names and format, simply create a shell script and type in the rostopic command with the correct argument structure. More information about the rostopic command is available on http://wiki.ros.org/rostopic.

Identify the Odometry message fields

This can be done using the rosmsg command. In a Terminal, type in the following command:

$ rosmsg info nav_msgs/Odometry

The odometry fields are displayed.

Create a shell script

Using your favorite text editor, create a shell script e.g. test_rostopic.sh to publish odom topic messages of type nav_msgs/Odometry. Type in the following with the fields and corresponding values in yaml format. Make sure no tabs are used and be careful of the spaces.

rostopic pub /odom nav_msgs/Odometry '
{
header: {seq: 1, stamp: now},
pose: 
  { 
  pose: { 
    position: { x: 10, y: 20, z: 30}, 
    orientation: { x: 0.2, y: 0.1, z: 0}
  }, 
  covariance: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]},
}'
-r 0.1

Note: the last line "-r 0.1" simply says to repeat the rostopic pub command at 0.1 hz.

Run the shell script

 In a Terminal, type in the following to run the rostopic pub command.

$ bash /path/to/test_rostopic.sh

Optional. To see whether the odometry messages published by the script, open up another Terminal and run the following command:

$ rostopic echo odom

The odom topic is displayed.

Monday, May 4, 2020

Gazebo: make an animated box using a separate model file(s)

The Gazebo tutorial at http://gazebosim.org/tutorials?tut=actor&cat=build_robot shows how to make a box actor rotate around the vertical axis using only a world file. I wanted to use create a separate actor model and include it in the world file so I don't have to repeat the code. After fiddling around, I managed to figure out the procedure to do it. This post summarizes the steps.

Create an actor model
  1. In the user's home directory ~/.gazebo/models/, create a model folder, e.g. animated_box

    $ cd ~/.gazebo/models/
    $ mkdir -p animated_box/materials/scripts
    $ mkdir -p animated_box/materials/textures


  2. Change directory into the animated_box folder.

    $ cd animated_box


  3. Using a text editor, create a model.config file. Type in the following:
    <?xml version="1.0" encoding="utf-8"?>
    <model>
     <name>Animated Box</name>
     <version>1.0</version>
     <sdf version="1.4">model.sdf</sdf>
     <description>My animated box</description>
    </model>
    


  4. Using a text editor, create a model.sdf file. Type in the following:

    Note: instead of the model tag, use the actor tag.
    <?xml version="1.0" encoding="utf-8"?>
    <sdf version="1.4">
     <actor name="animated_box">
      <static>false</static>
       <link name="link">
        <visual name="visual">
         <geometry>
          <box>
           <size>0.2 0.2 0.2</size>
          </box>
         </geometry>
        </visual>
       </link>
       <script>
        <loop>true</loop>
        <delay_start>0.0</delay_start>
        <auto_start>true</auto_start>
        <trajectory id="0" type="square">
         <waypoint>
          <time>0.0</time>
          <pose>-1 -1 1 0 0 0</pose>
         </waypoint>
         <waypoint>
          <time>1.0</time>
          <pose>-1 1 1 0 0 0</pose>
         </waypoint>
         <waypoint>
          <time>2.0</time>
          <pose>1 1 1 0 0 0</pose>
         </waypoint>
         <waypoint>
          <time>3.0</time>
          <pose>1 -1 1 0 0 0</pose>
         </waypoint>
         <waypoint>
          <time>4.0</time>
          <pose>-1 -1 1 0 0 0</pose>
         </waypoint>
        </trajectory>
       </script>
    
     </actor>
    </sdf>
    


Create and run the world file
  1.  Using a text editor, create a world file, e.g. my_animated_box.world. Type in the following commands:
    <?xml version="1.0" ?>
    <sdf version="1.3">
     <world name="default">
      <include>
      <uri>model://sun</uri>
      </include>
      <include>
       <uri>model://ground_plane</uri>
      </include>
      <include>
       <uri>model://animated_box</uri>
      </include>
     </world>
    </sdf>
    

    Note: the previously created animated_box model is included as a model.

  2. Run the world file.

    $ gazebo my_animated_box.world

    Gazebo opens and an animated box is shown circling the z axis.

    Monday, April 13, 2020

    Setup to launch ROS nodes on a remote computer on a network

    ROS nodes can be setup to run on a remote computer from a local computer on the same network. However, there are some setup to be done. After reading the tutorials and trying out on my own, the following steps summarized what worked for me.

    Create known hosts
    On the local Linux computer e.g. a Raspberry Pi (local1) do the following:
    1. Open a Terminal.
       
    2. Type in the command.

      $  ssh -oHostKeyAlgorithms='ssh-rsa' remote_user1@remote1

      The prompt appears: Are you sure you want to continue connecting (yes/no)?
    3. Type in yes. Press RETURN.
    4. When prompted, type in the password for the remote1 computer's remote_user1.

      The Terminal is now connected to the computer remote1 and remote_user1 is logged in.

      The remote1 computer name is encrypted with the RSA encryption and stored in the Raspberry Pi's /home/local_user1/.ssh/known_hosts file.

    5. Type in exit.

      The connection to remote1 is closed.
    6. If necessary, repeat the previous steps 2 to 4 for the IP address of the computer remote1.

      $ ssh -oHostKeyAlgorithms='ssh-rsa' user1@192.168.8.101

      Note: where 192.168.8.101 is the IP address for the computer remote1.
    Create SSH public and private keys for authentication
    1. On the local1 computer, open a Terminal.
    2. Type in the command:

      $ ssh-keygen -t rsa

      Enter file in which to save the key (/home/local_user1/.ssh/id_rsa):
    3. Press RETURN.

      Enter passphrase (empty for no passphrase):
    4. Press RETURN.

      Enter same passphrase again:
    5. Press RETURN.

      The private key is generated in /home/local_user1/.ssh/id_rsa.
      The public key is generated in /home/local_user1/.ssh/id_rsa.pub
      .
    Install the public key(s) to the remote computer
    1. On the computer local1, open a Terminal.
    2. Type in the command:

      $ ssh-copy-id remote_user1@remote1
    3. When prompted, type in the password for remote_user1.

      The public keys are installed on computer remote1.
    Create a remote ROS environment shell script file
    The following steps should be executed on the remote computer remote1.
    1. Using a text editor, create a shell script file e.g. /opt/ros/melodic/env_remote1.sh with the following content.

      #!/bin/bash
      
      export ROS_MASTER_URI=http://remote1:11311
      
      source /opt/ros/melodic/setup.bash
      source /home/remote_user1/catkin_ws/devel/setup.bash
      
      exec "$@"
      

    2. Open a Terminal. Make the shell script executable.

      $ sudo chmod a+x env_remote1.sh

    Create and run local launch file
    The following should be done on the local computer local1.
    1. Using a text editor, create a launch file e.g. run_remote.launch.
      <launch>
              <machine
                      name="remote1"
                      address="remote1"
                      env-loader="/opt/ros/melodic/env_remote1.sh"
                      default="true"
                      user="remote_user1"
              />
              <node machine="remote1" pkg="beginner_tutorials" name="hello_doubles" type="hello_doubles" />
      </launch>
      

      Note: this launch file will run the hello_doubles node from the beginner_tutorials package on the remote1 computer.

    2. Open a Terminal. Type in the following command assuming the launch file is in the current directory:

      $ roslaunch remote.launch
      The following messages may appear. Ws06 in this example screenshot is the remote computer.

      Monday, March 16, 2020

      How to run a shell script from a ROS launch file

      I wanted to execute a bash shell script from the ROS launch file but the ROS Wiki were not very clear. After some trial and error, I figured out how to do it. The following steps illustrate the procedure I used:

      Create a shell script
      1. In the ROS workspace package, e.g. /path/to/workspace/package/script/ folder, create a shell script e.g. run_script.sh.
      2. Type in the script commands, e.g. see the code listing below.

        Note 1: ensure the shebang statement is at the top i.e. #!/bin/bash and a exit status code (0 for success or other values) is returned from the script.

        Note 2: Use the chmod command to make the script executable, e.g. $ chmod a+x run_script.sh

      #!/bin/bash
      
      # just print this out
      echo "Hello ROS world"
      
      # exit gracefully by returning a status 
      exit 0
      


      Create a launch file
      1. In the ROS workspace package launch folder, create a launch file e.g. /path/to/workspace/package/launch/hello_script.launch.
      2. Using a text editor, type in the following:

        Note: fill in the package name, e.g. beginner_tutorials, and the type, which should be the shell script name; name is any label you want to associate with the script node.


      <launch>
              <node pkg="beginner_tutorials"
                      type="run_script.sh" name="run_script"
                      output="screen"
              />
      </launch>
      

      Run the launch file
      1. In a terminal, type in the ros launch command:

        $ roslaunch beginner_tutorials hello_script.launch

        Note: change beginner_tutorials to your package name and hello_script.launch to the launch file created previously.

        The script is executed as shown in the print out of "Hello ROS world" below.

      Monday, October 21, 2019

      Setting and passing ROS double array parameters to a ROS C++ node

      I tried to pass an array or list of double parameters to a ROS node program through the ROS rosrun program but my C++ ROS node program could not read the double array parameter. For example, the screenshot below shows the command to run a ROS node (hello_doubles) from the package beginner_tutorials and setting my_doubles_array parameter with the double list [1.1, 2.2, 3.3]:

      $ rosrun beginner_tutorials hello_doubles _my_doubles_array:="[1.1,2.2,3.3]"

      Note that after running the command, the ROS parameter server contains a parameter /hello_doubles/my_doubles_array with a string value of '[1.1, 2.2., 3.3]' and not the expected double array [1.1, 2.2, 3.3].

      Eventually, I realized the rosrun program passes the list as a string instead of an array of doubles. In order to pass a double array parameter, the following methods could be used instead: (1) use the rosparam set command, or (2) use the rosparam load command.

      Use the rosparam set command to pass a double array parameter
      1. In a Terminal, type in the following command:

        $ rosparam set /hello_doubles/my_double_array "[1.1, 2.2, 3.3]"

      Use the rosparam load command to set a double array parameter
      1. Using a text editor, create a yaml file e.g. hello_doubles.yaml with the following lines:



        where my_doubles_array is the name of the double array parameter
      2. In a Terminal, type in the following command to load the yaml file:

        $ rosparam load /path/to/hello_doubles.yaml

      Monday, August 5, 2019

      Convert a Velodyne PCAP file into a ROS bag file

      Normally Velodyne laser sensors record LiDAR data packets in PCAP format (*.pcap) file. If later on you want to process this recorded PCAP file in some SLAM algorithm in ROS e.g. ROS Cartogropher, then it may be necessary to convert it into a ROS bag file.

      To convert the PCAP file e.g. HDL32-V2_Monterey_Highway.pcap, perform the following:
      1.  Open up a Terminal. Enter the command to record the messages under the ROS topic /velodyne_points to an output bag file.

        $ rosbag record -O /path/to/output.bag /velodyne_points
        Note: /velodyne_points is the message to record. Leave blank if you want to record all messages.
      2. Open up another Terminal. Change directory to the location of the PCAP file, e.g. /path/to/Downloads/.

        $ cd /path/to/Downloads
      3. Enter the command to playback the Velodyne PCAP file and publish as a point cloud.

        $ roslaunch velodyne_pointcloud 32e_points.launch pcap:=$(pwd)/HDL32-V2_Monterey_Highway.pcap readonce:=true


        Note: this command publishes a HDL-32E PCAP file as a point cloud.
      4. Wait until the PCAP file is fully read. You can use the following command in another Terminal to check if anymore data is published.

        $ rostopic echo /velodyne_points

        A stream of points appear.
      5. When no more messages appear, the PCAP file is fully read. In the first Terminal, press CTRL-C to interrupt and complete the recording process to the bag file.

        The bag file is created.

      Monday, July 29, 2019

      ROS: Fix "Unable to get message class for type custom_msgs/gnssSample"

      I recently received a ROS bag file recorded with a Velodyne VLP-16 LiDAR sensor and a XSens IMU-GPS sensor. When playing back the bag file, the ROS rqt plugins could not expand the XSens messages. The error message: can not get message class for type "custom_msgs/gnssSample" is shown in the screen shot below.
       
      I found a deprecated Github repository for the XSens MTi ROS node at https://github.com/xsens/xsens_mti_ros_node that has the definitions for the custom message gnssSample. However, the repository's package name is xsens_msgs while the bag file's package name is custom_msgs. I had to rename the package to get ROS to recognize the bag file's messages. So the following steps were how I resolved the problem.
      1. Follow the tutorial at https://wiki.ros.org/ROS/Tutorials/CreatingPackage to create a Catkin workspace e.g. /home/yourname/catkin_ws/.
      2. Open up a Terminal and change the directory to /home/yourname/catkin_ws/src/.

        $ cd /home/yourname/catkin_ws/src
      3. Download the XSens MTi ROS Node repository.

        $ git clone https://github.com/xsens/xsens_mti_ros_node
      4. Using a text editor, open up the file /home/yourname/catkin_ws/src/xsens_mti_ros_node/src/xsens_msgs/package.xml.


      5. Change the package name to custom_msgs as shown below.


      6. Open up the file /home/yourname/catkin_ws/src/xsens_mti_ros_node/src/xsens_msgs/CMakeLists.txt.



      7. Change the project name to custom_msgs as shown below.


      8. Now in a Terminal change to the catkin root directory.

        $ cd /home/yourname/catkin_ws
      9. Compile the package by entering the command:

        $ catkin_make
      If the compilation is successful, now when reviewing the messages with rqt, the custom_msgs/gnssSample message can be expanded, as shown below.

      Monday, June 3, 2019

      Installing and running the Velodyne Height Map package on ROS Melodic distribution

      The ROS Velodyne Height Map package (https://wiki.ros.org/velodyne_height_map) is a useful tool for identifying obstacles in a point cloud. An example of potential obstacles is shown below (the red squares).

      However the last supported ROS distribution seems to be Indigo, a few releases from the latest Melodic distribution. But it is still possible to install and run the package on the latest ROS distribution. To do that, the source code from https://github.com/jack-oquin/velodyne_height_map must be downloaded and compiled on the ROS installation. The following steps illustrate the procedure.

      Create a ROS Catkin workspace
      1. Follow the tutorial here at https://wiki.ros.org/catkin/Tutorials/create_a_workspace to create an empty workspace, e.g /path/to/catkin_ws/.
      Download the Velodyne Height Map source code
      1. Open up a Terminal. Change the directory to the location of the Catkin workspace's src directory created earlier.

        $ cd /path/to/catkin_ws/src
      2.  Assuming git is installed, clone the velodyne height map source code.

        $ git clone https://github.com/jack-oquin/velodyne_height_map.git
      Build the package
      1. In the Terminal, change the directory to the root of the Catkin workspace.

        $ cd /path/to/catkin_ws
      2. Type in the following command to build the packages.

        $ catkin_make
      Once the package is built, the Velodyne Height Map package can be executed according to the instructions here at https://wiki.ros.org/velodyne_height_map. For example,

      $ rosrun velodyne_height_map heightmap_node

      Monday, May 27, 2019

      Displaying Velodyne PCAP data in ROS' RViz

      Pre-recorded data in PCAP format from Velodyne's LiDAR sensors such as the HDL-32E, VLP-16, etc. can be displayed in the RViz application software from the Robotic Operating System (ROS). The following steps show how:
      1. In Ubuntu, open up a Terminal. Change directory to the location of the PCAP file e.g. /path/to/download/HDL32-V2_Monterey_Highway.pcap.

        $ cd /path/to/download/
        $ roslaunch velodyne_pointcloud 32e_points.launch pcap:=$(pwd)/HDL32-V2_Monterey_Highway.pcap


        Note 1: 32e_points.launch is the sample launch file for HDL-32E sensors (change this for different sensors),
        $(pwd) is a macro that points to the current working directory, and
        pcap:= points to the input PCAP file name
        .

        Note 2: By default, the LiDAR points are published in the velodyne coordinate reference frame, i.e. the points are relative to the Velodyne sensor.
      2. Open up another Terminal. Startup RViz by entering the following commands.

        $ rosrun rviz rviz -f velodyne

        Note: the -f option tells RViz to use the velodyne coordinate transformation frame.

        The RViz application starts up.

      3. Click the Add button as shown above.

        The Choose visualization dialog box appears.

      4. Click By topic and choose the topic /velodyne_points/PointCloud2. click OK.

        The PCAP point cloud is displayed.


        Note: the HDL-32E sensor is mounted on top of the car so the road is below zero as shown below.


      5. To transform the PCAP data to the car (so called odom frame), we have to define the transformation parameters from the odom frame to the velodyne frame. For example, say the HDL-32E is 2 meters above the odom frame origin. Open another Terminal and type in the following command:

        $ rosrun tf static_transform_publisher 0 0 2 0 0 0 odom velodyne 100
        Note: 0 0 2 0 0 0 values are equal to dx, dy, dz, and yaw, pitch, roll (in rads),
        odom is the parent or from frame,
        velodyne is the child or to frame, and
        100 is the time interval for publishing the transformation in msec
        .
      6. In the Fixed frame field of the RViz application, change the value to odom.

        The point cloud is displayed in the odom frame as shown below.

      Monday, May 20, 2019

      Setup Ubuntu network settings to Velodyne VLP-16 for ROS

      After installing ROS (Robotic Operating System) and the Velodyne drivers and utilities on Ubuntu 18.04 LTS, the computer needs to be able to communicate with the Velodyne VLP-16 sensor unit.

      Note: this post is specific to the VLP-16 unit but should be applicable to the other units, with some address changes.

      By default, the IP address of the VLP-16 is set to be 192.168.1.201 by the factory. The network interface for the computer should be set to be on the same network, i.e. 192.168.1.77 for example, with the network masks at 255.255.255.255 and the gateway to be 192.168.1.255.

      1. To set the Ubuntu network settings, click the network icon on the top left bar and choose Wired Settings in the pop down menu.


      2. In the Settings dialog box, click the gear icon as shown below.




        The Wired dialog box appears.

      3. Click the IPv4 tab. Toggle on the Manual IPv4 Method.


      4. Type in the following address values, as shown below.


      5. Scroll down. Type in the Routes (to the VLP-16) values as shown below.



      6. Click Apply. If all the values are correct, Ubuntu should show you a Network connected status. Otherwise, recheck the values and try again.
      7. Now to start ROS and run a sample Velodyne launch file, the following commands can be executed in separate terminals.


        $ roscore

        $ roslaunch velodyne_pointcloud VLP16_points.launch

        The VLP-16 /velodyne_points topic is published



      Monday, May 13, 2019

      Setting up Visual Studio Code for working with ROS C++ on Ubuntu

      In order to use Visual Studio Code on Ubuntu to develop ROS (Robotic Operating System) C++ packages, a couple of Visual Studio Code extensions can be helpful.

      If they are not already installed, simply run Visual Studio Code and install the following extensions:
      • Microsoft C/C++ extension
      • ROS extension

      Another thing that can be helpful is to configure the Microsoft C/C++ extension to include the ROS header include files. If the extension is unable to locate the ROS header files, the code editor will show wavy green lines under the header files, as shown in the screenshot below.

      To get rid of these wavy lines, the C/C++ properties (c_cpp_properties.json) file need to be edited to add in the ROS header include directory, e.g. /opt/ros/melodic/include/.

      The following screenshots show the c_cpp_properties.json file and the includePath configuration array.

      Append the path "/opt/ros/melodic/include" to the includePath array variable as shown below.

      Then save and restart Visual Studio Code. Observe that the green wavy lines are no longer displayed.