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

How to set std::vector<bool> as ros parameter ?

asked 2022-09-29 04:51:18 -0600

ros_user_ak gravatar image

updated 2022-09-30 02:54:02 -0600

I'm trying to set parameter in two different ways. In both case I'm getting error.

Here is the code example:

Method 1:

std::vector<bool> odomConfig;
nh.param<std::vector<bool>>(odom0_config", odomConfig,
          {false, false, false, false, false, false, true, true, true, false, false, false, false, false, false});

Method 2:

std::vector<bool> odomConfig;
ros::param::param<std::vector<bool>>(odom0_config", odomConfig,
          {false, false, false, false, false, false, true, true, true, false, false, false, false, false, false});

The error i get in both case is as follows:

[FATAL] [1664453231.205964254]: ASSERTION FAILED
    file = /home/user111/git_repos/catkin_ws/src/robot_localization/src/ros_filter.cpp
    line = 2280
    cond = topicConfig.getType() == XmlRpc::XmlRpcValue::TypeArray

The error is thrown by this line of code link.

Where am I doing wrong in setting parameters ?

Edit 1:

With the answers given, there is no solution to my problem addressed although.

Just a simple problem. A ros parameter need to be set for ekf_localization_node of robot_localization package.

I now set the parameter as follows: (Changed vector template argument type to int )

But, there is an error (pls see above for the error.)

ros::param::set("odom0", "/husky_velocity_controller/odom");
std::vector<int> odomConfig;
ros::param::param<std::vector<int>>("odom0_config", odomConfig,
              {false, false, false, false, false, false, true, true, true, false, false, false, false, false, false});

When I run my project, the below function is called:

template<typename T>
  std::vector<int> RosFilter<T>::loadUpdateConfig(const std::string &topicName)
  {
    XmlRpc::XmlRpcValue topicConfig;
    std::vector<int> updateVector(STATE_SIZE, 0);
    std::string topicConfigName = topicName + "_config";

    try
    {
      nhLocal_.getParam(topicConfigName, topicConfig);
      ROS_ASSERT(topicConfig.getType() == XmlRpc::XmlRpcValue::TypeArray);
    }
    catch (XmlRpc::XmlRpcException &e)
    {
      ROS_FATAL_STREAM("Could not read sensor update configuration for topic " << topicName );
    }

Here,

std::string topicConfigName = topicName + "_config"; outputs "odom0_config"

The program fails at the line ROS_ASSERT()

Note: The below function is called inside nh.setParam() function:

 template <class T>
   void setImpl(const std::string& key, const std::vector<T>& vec)
 {
   // Note: the XmlRpcValue starts off as "invalid" and assertArray turns it
   // into an array type with the given size
   XmlRpc::XmlRpcValue xml_vec;
   xml_vec.setSize(vec.size());

   // Copy the contents into the XmlRpcValue
   for(size_t i=0; i < vec.size(); i++) {
     xml_vec[i] = vec.at(i);
   }

   ros::param::set(key, xml_vec);
 }
edit retag flag offensive close merge delete

Comments

1

Just a notice, std::vector<bool> is not recommended to use - avoid std::vector<bool> and use boost::vector<bool>. And if you really need to save bits then use boost::dynamic_bitset.

ljaniec gravatar image ljaniec  ( 2022-09-29 08:01:25 -0600 )edit

Thank you for the suggestions. However, my team doesn't use boost library for the projects. Also, it would be really helpful when you give actual reasons for your suggestions / recommendations. Then it might be easy to make further considerations.

ros_user_ak gravatar image ros_user_ak  ( 2022-09-29 09:06:16 -0600 )edit

By the second source in the comment above:

`std::vector<bool>` is great example of a premature optimization that wasn’t well-thought-out. 
Problem is that `vector<bool>` behaves slightly differently than other vectors :

- It isn’t an array of bools internally.
- `&v[i] + n` will not point to `&v[i+n]`
- `v[i]` returns a proxy object that may die surprisingly fast.
- It doesn’t have `data()` method.

This is a problem, when you are writing a template code with vectors of something unknown.
ljaniec gravatar image ljaniec  ( 2022-09-29 09:24:56 -0600 )edit

In the new edit - what is the failing result on the LHS. with topicConfig.getType()?

I think it's a typo only in the question, but in your Method (both 1 & 2) you don't have odom0_config within " ... "

ljaniec gravatar image ljaniec  ( 2022-09-29 09:53:13 -0600 )edit

topicConfig.getType() should match the RHS. The ros::param::set() will set the value to typeXmlRpc::XmlRpcValue::TypeArray.

Sorry, its a typo here in the question I posted. In my program, I have set

ros::param::set("odom0_config", std::vector<int>{false, false, false, false, false, false, true, true, true, false, false, false, false, false, false});
ros_user_ak gravatar image ros_user_ak  ( 2022-09-30 03:09:17 -0600 )edit

1 Answer

Sort by » oldest newest most voted
1

answered 2022-09-29 08:41:10 -0600

ravijoshi gravatar image

updated 2022-09-29 08:49:08 -0600

I suspect about the error you reported, as it is shown that the error is coming from the robot_localization package. However, ros::param is a part of the ROS core thus should be unrelated to the robot_localization package.

Nevertheless, below is what I tried and found working:

#include <ros/ros.h>

int main(int argc, char** argv)
{
  ros::init(argc, argv, "my_ros_param");
  ros::NodeHandle nh;

  // define a shorthand notation
  using BoolVector = std::vector<bool>;

  BoolVector odomConfig;

  // define a handy lambda funciton
  const auto printConfig = [&odomConfig]() {
    std::string configStr = "";
    for (const auto& item : odomConfig)
      configStr += item ? "true " : "false ";
    ROS_INFO("odom_config[%zu] items:[%s]", odomConfig.size(), configStr.c_str());
  };

  // no default
  nh.getParam("odom_config", odomConfig);
  printConfig();

  // with default
  nh.param("odom_config", odomConfig,
           { false, false, false, false, false, false, true, true, true, false, false, false, false, false, false });
  printConfig();

  ros::param::param("odom_config", odomConfig,
                    { false, false, false, false, false, false, true, true, true, false, false, false, false, false });
  printConfig();

  ros::param::param<BoolVector>("odom_config", odomConfig, { false, true, true, true, false, false });
  printConfig();

  // set as ros param
  nh.setParam("odom_config", odomConfig);

  // no default but this time, we should be getting it from parameter server
  nh.getParam("odom_config", odomConfig);
  printConfig();

  return 0;
}

This is what I saw while running it:

$ rosrun beginner_tutorials talker_rosparam 
[ INFO] [1664457912.188430402]: odom_config[0] items:[]
[ INFO] [1664457912.189091735]: odom_config[15] items:[false false false false false false true true true false false false false false false ]
[ INFO] [1664457912.189296018]: odom_config[14] items:[false false false false false false true true true false false false false false ]
[ INFO] [1664457912.189495235]: odom_config[6] items:[false true true true false false ]
[ INFO] [1664459025.189954825]: odom_config[6] items:[false true true true false false ]

I can also get it from the parameter server as shown below:

$ rosparam get /odom_config
- false
- true
- true
- true
- false
- false

Last but not least, please avoid using std::vector<bool> and redefine BoolVector based on the alternatives mentioned by @ljaniec

edit flag offensive delete link more

Comments

I'm working on robot_localization package in ROS. I need to set "odom0_config" as a ros parameter, and its value is a list of boolean. The ekf_localization_node uses it while executing the node.

ros_user_ak gravatar image ros_user_ak  ( 2022-09-29 09:12:04 -0600 )edit

Does the above information help you? Just pick one style from above and use it in your code. If the error persist, persists elaborate.

ravijoshi gravatar image ravijoshi  ( 2022-09-29 09:32:41 -0600 )edit

No.

For my project, I set a ros paramter as follows:

std::vector<bool> odomConfig;
ros::param::param<std::vector<bool>>("odom0_config", odomConfig, {false, false, false, false, false, false, true, true, true, false, false, false, false, false, false});

When I run the ekf_localization_node, I get error at this line of code.

template<typename T>
  std::vector<int> RosFilter<T>::loadUpdateConfig(const std::string &topicName)
  {
    XmlRpc::XmlRpcValue topicConfig;
    std::vector<int> updateVector(STATE_SIZE, 0);
    std::string topicConfigName = topicName + "_config";

    try
    {
      nhLocal_.getParam(topicConfigName, topicConfig);

      ROS_ASSERT(topicConfig.getType() == XmlRpc::XmlRpcValue::TypeArray);

The above function parameter receives const std::string& topicName = "odom0"

ros_user_ak gravatar image ros_user_ak  ( 2022-09-30 03:02:18 -0600 )edit
1

I encourage to create a "Minimal reproducible example".

ravijoshi gravatar image ravijoshi  ( 2022-09-30 06:01:32 -0600 )edit
1

The issue is solved. Prefix node name that's all I had to do.

std::vector<bool> odomConfig;
ros::param::param<std::vector<bool>>("ekf_node/odom0_config", odomConfig, {false, false, false, false, false, false, true, true, true, false, false, false, false, false, false});
ros_user_ak gravatar image ros_user_ak  ( 2022-09-30 06:25:34 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2022-09-29 04:51:18 -0600

Seen: 304 times

Last updated: Sep 30 '22