ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question

morten's profile - activity

2023-06-26 04:01:32 -0500 received badge  Famous Question (source)
2023-06-26 04:01:32 -0500 received badge  Popular Question (source)
2023-06-26 04:01:32 -0500 received badge  Notable Question (source)
2023-02-19 07:57:04 -0500 received badge  Famous Question (source)
2022-12-22 04:38:07 -0500 received badge  Famous Question (source)
2022-12-22 04:38:07 -0500 received badge  Notable Question (source)
2022-11-29 14:44:48 -0500 received badge  Famous Question (source)
2022-11-29 14:44:48 -0500 received badge  Notable Question (source)
2022-09-23 13:57:12 -0500 marked best answer [ROS2 Foxy] Passing argument from one launch file to another

I have compartmentalized my launch files into different purposes, I currently have a main launch file from which I would like to call one of the others. I have partly done this to be able to separate some of the functionalities, but also so the main launch doesn't become to verbose.

The main launch file gets passed an argument for the vehicle platform architecture, such as to find a specific config file highlighting some necessary parameters. This argument that is to be passed is platform.

How can I pass this argument from the main launch file to its children.

I included an example of the main.launch.py so one can see how the platform arg is being used.

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions.declare_launch_argument import DeclareLaunchArgument
from launch.actions.include_launch_description import IncludeLaunchDescription
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node  

def generate_launch_description():
    # defining platform
    # select either newholland_t7 or fort_rd25
    platforms = ["newholland_t7", "fort_rd25"]
    for id, plat in enumerate(platforms):
        print(f"\t{id} for {plat}")
    platform_id = int(input("Select a platform: "))

    try:
        platform = platforms[platform_id]
    except IndexError as ex:
        print(f"[ERROR]: {ex}, please select valid index")
        return LaunchDescription()
    print(f"Selected {platform}")

    urdf_path = os.path.join(
        get_package_share_directory("main_pkg"), "urdf", platform + ".urdf.xml"
    )
    with open(urdf_path, "r") as infp:
        robot_description = infp.read()
    urdf_publisher = Node(
        package="robot_state_publisher",
        executable="robot_state_publisher",
        name="robot_state_publisher",
        parameters=[{"robot_description": robot_description}],
        arguments=[urdf_path],
        output="screen",
    )

    danger_zone_config = os.path.join(
        get_package_share_directory("agrirobot"), "config", platform + ".yaml"
    )
    visualize_markers = Node(
        package="visualize_markers",
        executable="visualize_markers_node",
        name="visualize_markers",
        parameters=[danger_zone_config],
        output="screen",
    )

    # some other things

    ld = LaunchDescription()
    ld.add_action(urdf_publisher)
    ld.add_action(visualize_markers)

    return ld
2022-09-13 07:33:10 -0500 marked best answer Robot localization ekf capped at 10Hz

I'm using the ekf in robot_localization, for some reason it doesn't seem to want to go above the odd 10Hz. I've checked my imu and odometry rates, and they're both 50Hz as I've set them.

I launch the ekf node by ros2 launch tractor_gazebo ekf.launch.py use_sim_time:=true and I check the individual frequencies:

$ ros2 param get /ekf_localization_odom frequency 
Double value is: 30.0
$ ros2 topic hz /imu/data 
average rate: 49.887
    min: 0.020s max: 0.021s std dev: 0.00020s window: 51
$ ros2 topic hz /odometry/wheel 
average rate: 49.910
    min: 0.020s max: 0.021s std dev: 0.00018s window: 51
average rate: 49.853
    min: 0.020s max: 0.021s std dev: 0.00020s window: 101
$ ros2 topic hz /odometry/filtered/odom 
average rate: 9.956
    min: 0.100s max: 0.101s std dev: 0.00033s window: 11
average rate: 9.961
    min: 0.099s max: 0.101s std dev: 0.00043s window: 21

with the launch and config files added at the bottom.

Note: I have tried setting the ekf frequency to less than 10Hz, and this is can follow fine. So, e.g. changing the parameter in the yaml to 5Hz results in publishing to /odometry/filtered/odom at 5Hz, setting it to 15Hz instead results in the topic publishing at 10Hz. This is the core of the problem

ekf.launch.py:

import os
from ament_index_python.packages import get_package_share_directory

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration

from launch_ros.actions import Node

def generate_launch_description():
    # get directories
    tractor_gazebo_dir = get_package_share_directory("tractor_gazebo")

    # Create the launch configuration variables
    use_sim_time = LaunchConfiguration("use_sim_time")

    # declare launch arguments
    declare_use_sim_time = DeclareLaunchArgument("use_sim_time")

    # Specify the actions
    robot_localization_odom = Node(
        package="robot_localization",
        executable="ekf_node",
        name="ekf_localization_odom",
        output="screen",
        parameters=[
            {"use_sim_time": use_sim_time},
            os.path.join(
                tractor_gazebo_dir,
                "config",
                "dual_ekf_navsat_toolcarrier.yaml",
            ),
        ],
        remappings=[("odometry/filtered", "odometry/filtered/odom")],
    )

    return LaunchDescription(
        [
            declare_use_sim_time,
            robot_localization_odom,
        ]
    )

config file:

ekf_localization_odom:
  ros__parameters:
    frequency: 30.0
    sensor_timeout: 0.0 #0.1
    two_d_mode: true
    transform_time_offset: 0.0 #0.01
    transform_timeout: 0.0
    print_diagnostics: true
    debug: false

    map_frame: map
    odom_frame: odom
    base_link_frame: base_link
    world_frame: odom

    odom0: odometry/wheel
    odom0_config: [false, false, false,
                   false, false, false,
                   true,  true,  false,
                   false, false, true,
                   false, false, false]
    odom0_queue_size: 10
    odom0_nodelay: true
    odom0_differential: false
    odom0_relative: false

    imu0: imu/data
    imu0_config: [false, false, false,
                  true,  true,  true,
                  false, false, false,
                  true,  true,  true,
                  true,  true,  true]
    imu0_nodelay: false
    imu0_differential: false
    imu0_relative: false
    imu0_queue_size: 10
    imu0_remove_gravitational_acceleration: true

    use_control: false

Edit: Following @osilva's comments I have checked the sim time parameter of all the nodes:

morten@agrirobot:~$ ros2 param list
/ackermann_drive:
  use_sim_time
/camera_controller_front:
  use_sim_time
/camera_controller_middle:
  use_sim_time
/controller_manager:
  use_sim_time
/ekf_localization_odom:
  use_sim_time
/gazebo:
  use_sim_time
/gazebo_ros2_control:
  use_sim_time
/velodyne_front/gazebo_ros_laser_controller:
  use_sim_time
/gps:
  use_sim_time
/imu:
  use_sim_time
/joint_state_publisher:
  use_sim_time
/robot_state_publisher:
  use_sim_time

Note, I've trimmed the other parameters so as not to go on too long, I have checked each and every one of these:

morten@agrirobot:~$ ros2 param get /ackermann_drive use_sim_time 
Boolean value is: True
morten@agrirobot:~$ ros2 param get /camera_controller_front use_sim_time 
Boolean value is: True ...
(more)
2022-09-13 07:33:10 -0500 received badge  Enlightened (source)
2022-09-13 07:33:10 -0500 received badge  Good Answer (source)
2022-08-29 03:53:57 -0500 received badge  Popular Question (source)
2022-08-28 05:03:21 -0500 commented answer Publishing multiple messages on same topic at same time

so each reading corresponds to a different viewpoint, this is to publish all clouds when the viewpoint transforms are up

2022-08-27 12:21:28 -0500 asked a question Publishing multiple messages on same topic at same time

Publishing multiple messages on same topic at same time I need to publish a several messages containing point clouds fro

2022-08-16 22:36:12 -0500 received badge  Famous Question (source)
2022-08-02 22:16:36 -0500 marked best answer ros2 foxy including header file from other package

I have two packages, temp_lib and temp_pkg. In temp_lib I have a file temp.hpp that I would like to include in other packages, but when I attempt to do so by writing in #include "temp_lib/temp.hpp" in a cpp file in temp_pkg then it says this header cannot be found.

The problem is i'm not really sure how to set up the CMakeLists file for the library.

How can I set these packages up for this to be possible?

LIBRARY CMAKE

cmake_minimum_required(VERSION 3.5)
project(temp_lib)

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)

install(TARGETS
  DESTINATION lib/${PROJECT_NAME}
  PUBLIC_HEADER DESTINATION include/${PROJECT_NAME}/
  )

install(DIRECTORY include/${PROJECT_NAME}/
  DESTINATION include/${PROJECT_NAME}
  FILES_MATCHING PATTERN "*.h"
  PATTERN ".git" EXCLUDE)

ament_package()

temp.hpp (from temp_lib)

#ifndef TEMP_LIB__TEMP_HPP_
#define TEMP_LIB__TEMP_HPP_

#include <iostream>

#endif // TEMP_LIB__TEMP_HPP_

PKG CMAKE

cmake_minimum_required(VERSION 3.5)
project(temp_pkg)

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(temp_lib REQUIRED)

include_directories(
  ${temp_lib_INCLUDE_DIRS}
)

add_executable(test src/temp.cpp)
ament_target_dependencies(test rclcpp temp_lib)

install(TARGETS
  test
  DESTINATION lib/${PROJECT_NAME}
)

ament_package()

temp.cpp (from temp_pkg)

#include "temp_lib/temp.hpp"
int main(int argc, char *argv[]) {
  std::cout << "it works" << std::endl;
  return 0;
}

Edit: for legibility I removed some repeated standard parts of the CMake files, these are

# Default to C99
if(NOT CMAKE_C_STANDARD)
  set(CMAKE_C_STANDARD 99)
endif()

# Default to C++14
if(NOT CMAKE_CXX_STANDARD)
  set(CMAKE_CXX_STANDARD 14)
endif()

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

and

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # uncomment the line when a copyright and license is not present in all source files
  #set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # uncomment the line when this package is not in a git repo
  #set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()
2022-07-13 07:00:09 -0500 received badge  Nice Answer (source)
2022-07-09 13:30:08 -0500 received badge  Notable Question (source)
2022-07-09 13:30:08 -0500 received badge  Famous Question (source)
2022-07-06 11:06:03 -0500 received badge  Popular Question (source)
2022-07-06 11:06:03 -0500 received badge  Notable Question (source)
2022-07-04 07:22:57 -0500 received badge  Famous Question (source)
2022-06-01 07:49:25 -0500 received badge  Famous Question (source)
2022-05-25 02:53:55 -0500 received badge  Notable Question (source)
2022-05-24 02:23:52 -0500 received badge  Famous Question (source)
2022-04-26 01:59:44 -0500 marked best answer Passing pcl::shared_ptr to subscriber (ROS2 Foxy)

I am trying to write a pointcloud filtering node in ROS2 foxy using pcl but I am running into some problems I think are resulting from the publishing.

The resulting error is

~/ros2_ws$ colcon build --symlink-install --packages-select pointcloud_filters
Starting >>> pointcloud_filters
--- stderr: pointcloud_filters                                
** WARNING ** io features related to pcap will be disabled
** WARNING ** io features related to png will be disabled
** WARNING ** io features related to libusb-1.0 will be disabled
/usr/bin/ld: CMakeFiles/pointcloud_filters_node.dir/src/pointcloud_filters_node.cpp.o: in function `rclcpp::Publisher<pcl::PointCloud<pcl::PointXYZI>, std::allocator<void> >::Publisher(rclcpp::node_interfaces::NodeBaseInterface*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rclcpp::QoS const&, rclcpp::PublisherOptionsWithAllocator<std::allocator<void> > const&)':
pointcloud_filters_node.cpp:(.text._ZN6rclcpp9PublisherIN3pcl10PointCloudINS1_9PointXYZIEEESaIvEEC2EPNS_15node_interfaces17NodeBaseInterfaceERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_3QoSERKNS_29PublisherOptionsWithAllocatorIS5_EE[_ZN6rclcpp9PublisherIN3pcl10PointCloudINS1_9PointXYZIEEESaIvEEC5EPNS_15node_interfaces17NodeBaseInterfaceERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS_3QoSERKNS_29PublisherOptionsWithAllocatorIS5_EE]+0x6e): undefined reference to `rosidl_message_type_support_t const* rosidl_typesupport_cpp::get_message_type_support_handle<pcl::PointCloud<pcl::PointXYZI> >()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/pointcloud_filters_node.dir/build.make:317: pointcloud_filters_node] Error 1
make[1]: *** [CMakeFiles/Makefile2:78: CMakeFiles/pointcloud_filters_node.dir/all] Error 2
make: *** [Makefile:141: all] Error 2
---
Failed   <<< pointcloud_filters [12.3s, exited with code 2]

Summary: 0 packages finished [12.4s]
  1 package failed: pointcloud_filters
  1 package had stderr output: pointcloud_filters

so its complaining about some undefined reference. I'm not entirely sure what the problem is but it seems like it could be similar to https://answers.ros.org/question/3117.... I looked at the interfaces for sensor_msgs/msg/PointCloud2 and sensor_msgs/msg./PointField and it looks identical to pcl::PointCloud so maybe I should manually transfer the attributes?

CPP file:

#include "rclcpp/rclcpp.hpp"
#include "sensor_msgs/msg/point_cloud2.hpp"

#include "pcl_conversions/pcl_conversions.h"

#include "pcl/filters/radius_outlier_removal.h"
#include "pcl/impl/point_types.hpp"
#include "pcl/point_cloud.h"

class PCFilter : public rclcpp::Node {
public:
  PCFilter() : Node("pointcloud_filters") {
    pub_ = this->create_publisher<pcl::PointCloud<pcl::PointXYZI>>(
        "filters_output", 1);
    sub_ = this->create_subscription<sensor_msgs::msg::PointCloud2>(
        "filters_input", 1,
        std::bind(&PCFilter::cloud_callback, this, std::placeholders::_1));

    this->declare_parameter("pointcloud_filters/neighbors", 1);
    this->declare_parameter("pointcloud_filters/radius", 0.2);
    this->declare_parameter("pointcloud_filters/distance", 5.0);
    this->declare_parameter("pointcloud_filters/intensity_threshold", 8);

    neighbors_ = this->get_parameter("pointcloud_filters/neighbors").as_int();
    radius_ = this->get_parameter("pointcloud_filters/radius").as_double();
    distance_ = this->get_parameter("pointcloud_filters/distance").as_double();
    intensity_threshold_ =
        this->get_parameter("pointcloud_filters/intensity_threshold").as_int();

    RCLCPP_INFO(this->get_logger(),
                "Filter "
                "pararms:\n\tneighbors:%d\t\nradius:%f\n\tdistance:%"
                "f\n\tintensity_threshold:%d",
                neighbors_, radius_, distance_, intensity_threshold_);
  }

private:
  void cloud_callback(const sensor_msgs::msg::PointCloud2::SharedPtr msg) {
    pcl::PointCloud<pcl::PointXYZI>::Ptr cloud(
        new pcl::PointCloud<pcl::PointXYZI>);
    pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_filtered(
        new pcl::PointCloud<pcl::PointXYZI>);
    pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_dust_filtered(
        new pcl::PointCloud<pcl::PointXYZI>);

    pcl::fromROSMsg(*msg, *cloud);

    if (cloud->size() > 0) {
      // Filter dust based on low intensity within a certain distance from the
      // lidar
      double dist = 0.0;
      for (std::size_t n = 0; n < cloud->size(); n++) {
        dist = std::sqrt(std::pow(cloud->points[n].x, 2) +
                         std::pow(cloud->points[n].y, 2) +
                         std::pow(cloud->points[n].z, 2));
        if (dist < distance_) {
          if (cloud->points[n].intensity > intensity_threshold_) {
            cloud_dust_filtered->push_back(cloud->points[n]);
          }
        } else {
          cloud_dust_filtered->push_back(cloud->points[n]);
        }
      }

      cloud_dust_filtered->header.frame_id = cloud->header.frame_id;
      cloud_dust_filtered->header.stamp = cloud->header.stamp;

      // Create radius outlier removal filter
      pcl::RadiusOutlierRemoval<pcl::PointXYZI> outrem;
      outrem.setInputCloud(cloud_dust_filtered);
      outrem.setRadiusSearch(radius_);
      outrem.setMinNeighborsInRadius(neighbors_);
      // Apply filter
      outrem.filter ...
(more)
2022-04-26 01:59:44 -0500 received badge  Self-Learner (source)
2022-04-23 15:09:00 -0500 received badge  Famous Question (source)
2022-04-14 16:59:33 -0500 received badge  Famous Question (source)
2022-04-07 03:32:17 -0500 received badge  Famous Question (source)
2022-04-04 15:48:39 -0500 received badge  Famous Question (source)
2022-03-14 10:42:55 -0500 received badge  Popular Question (source)
2022-03-14 10:42:55 -0500 received badge  Notable Question (source)
2022-03-11 14:07:07 -0500 received badge  Notable Question (source)
2022-03-08 15:18:28 -0500 received badge  Famous Question (source)
2022-03-08 15:18:28 -0500 received badge  Notable Question (source)
2022-03-04 03:56:11 -0500 asked a question Best practices for CMake with nested libraries

Best practices for CMake with nested libraries I have, at least what I think is, a slightly unique setup currently with

2022-03-01 15:23:48 -0500 received badge  Famous Question (source)
2022-03-01 15:23:48 -0500 received badge  Notable Question (source)
2022-03-01 15:23:48 -0500 received badge  Popular Question (source)
2022-02-23 06:24:08 -0500 received badge  Famous Question (source)
2022-02-22 15:49:24 -0500 received badge  Notable Question (source)
2022-02-22 11:56:00 -0500 received badge  Necromancer (source)
2022-02-22 11:56:00 -0500 received badge  Self-Learner (source)
2022-02-22 11:55:25 -0500 received badge  Popular Question (source)
2022-02-22 07:36:21 -0500 marked best answer Intra-Process Communication between Components in Container

Is it possible to take advantage of Intra Process Comms (IPC) when starting nodes in a container? I've made an example, trying to made a basic subscriber and publisher and looking at the pointer address, it seems as though it only works when "manually" composing.

This just seems surprising given the text in the composable nodes tutorial, which seems to indicate manually composing should somehow be "equivalent" to the container route. Especially given that manually composing using a multi-threaded executor also works fine.

Find the demo project here. The following example outputs are directly taken from this.

Example Outputs

Expected

With multi-threaded executor

$ ros2 run ipc_demo manual_composition 
[INFO] [1642518288.545003595] [ipc_talker]: Count: 0    Addr: 0x7f1dbc001300
[INFO] [1642518288.545393895] [ipc_listener]: Count: 0  Addr: 0x7f1dbc001300
[INFO] [1642518289.544906771] [ipc_talker]: Count: 1    Addr: 0x7f1dbc001400
[INFO] [1642518289.544989777] [ipc_listener]: Count: 1  Addr: 0x7f1dbc001400
[INFO] [1642518290.545010214] [ipc_talker]: Count: 2    Addr: 0x7f1dbc0032c0
[INFO] [1642518290.545243590] [ipc_listener]: Count: 2  Addr: 0x7f1dbc0032c0
[INFO] [1642518291.545039618] [ipc_talker]: Count: 3    Addr: 0x7f1dbc003f80
[INFO] [1642518291.545282153] [ipc_listener]: Count: 3  Addr: 0x7f1dbc003f80
[INFO] [1642518292.544973975] [ipc_talker]: Count: 4    Addr: 0x7f1db0001740
[INFO] [1642518292.545166314] [ipc_listener]: Count: 4  Addr: 0x7f1db0001740

Pointer addresses are the same, so should be working as expected.

Container

$ ros2 launch ipc_demo composition.launch.py 
[INFO] [launch]: All log files can be found below /home/morten/.ros/log/2022-01-18-16-04-58-690321-agrirobot-44101
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [component_container-1]: process started with pid [44117]
[component_container-1] [INFO] [1642518299.060037442] [two_nodes]: Load Library: /home/morten/temp_ws/install/ipc_demo/lib/libtalker_component.so
[component_container-1] [INFO] [1642518299.061590715] [two_nodes]: Found class: rclcpp_components::NodeFactoryTemplate<composition::Talker>
[component_container-1] [INFO] [1642518299.061656586] [two_nodes]: Instantiate class: rclcpp_components::NodeFactoryTemplate<composition::Talker>
[INFO] [launch_ros.actions.load_composable_nodes]: Loaded node '/talker' in container '/two_nodes'
[component_container-1] [INFO] [1642518299.068096064] [two_nodes]: Load Library: /home/morten/temp_ws/install/ipc_demo/lib/liblistener_component.so
[component_container-1] [INFO] [1642518299.068447676] [two_nodes]: Found class: rclcpp_components::NodeFactoryTemplate<composition::Listener>
[component_container-1] [INFO] [1642518299.068460910] [two_nodes]: Instantiate class: rclcpp_components::NodeFactoryTemplate<composition::Listener>
[INFO] [launch_ros.actions.load_composable_nodes]: Loaded node '/listener' in container '/two_nodes'
[component_container-1] [INFO] [1642518300.067406025] [talker]: Count: 0    Addr: 0x557f63f68960
[component_container-1] [INFO] [1642518300.067869433] [listener]: Count: 0  Addr: 0x557f63e42fd0
[component_container-1] [INFO] [1642518301.067393044] [talker]: Count: 1    Addr: 0x557f63e04720
[component_container-1] [INFO] [1642518301.067703912] [listener]: Count: 1  Addr: 0x557f64035980
[component_container-1] [INFO] [1642518302.067380956] [talker]: Count: 2    Addr: 0x557f64053c20
[component_container-1] [INFO] [1642518302.067666810] [listener]: Count: 2  Addr: 0x557f63e42fd0

Different pointer addresses between corresponding talker/listener message.

2022-02-22 07:36:18 -0500 edited answer Intra-Process Communication between Components in Container

Way down the road found a way to make it work, no one's responded so I'll post my own answer. See here, an example launc