Dynamic_Reconfigure: Set Parameter Value from C++ Code
Hello - I am new to ROS. I am using Ros Noetic on Ubuntu 20.04.
I followed the dynamic_reconfigure tutorial and have dynamic_reconfigure parameters working. I have 1 parameter which is defined as a bool_t in the .cfg file, so in the rqt_reconfigure GUI it appears as a checkbox. In my C++ code, if the parameter value is true (i.e checkbox is checked) I will save data to a file. Once the data is saved, the C++ code should set the parameter value to false so the checkbox in the rqt_reconfigure GUI gets unchecked.
In order to change the value of a dynamic reconfigure parameter in C++ code, I followed these instructions and information in this FAQ. This is my code:
#include <dynamic_reconfigure/BoolParameter.h>
#include <dynamic_reconfigure/Reconfigure.h>
#include <dynamic_reconfigure/Config.h>
dynamic_reconfigure::ReconfigureRequest srv_req;
dynamic_reconfigure::ReconfigureResponse srv_resp;
dynamic_reconfigure::BoolParameter bool_param;
dynamic_reconfigure::Config conf;
bool_param.name = "save_data_to_file";
bool_param.value = false; // I also tried setting this to 0 instead of false with same results
conf.bools.push_back(bool_param);
srv_req.config = conf;
ros::service::call("/myNodeName/set_parameters", srv_req, srv_resp);
The ros::service::call line hangs. I have print statements before and after that line and never see the print that is after it.
From a command line, I can run this command and it works so I'm certain I'm using the correct node name, the correct parameter name etc:
rosrun dynamic_reconfigure dynparam set /myNodeName save_data_to_file false
Any suggestions as to why the ros::service::call in the C++ code hangs? Watching the values of the parameter from a command line, the ros::service::call does not change the value of the parameter.
Thanks in advance!
EDIT #1: This is my C++ code cut down to the basics. When I run it, I can see the "BEFORE" print statement, but not the "AFTER". The value of save_data_to_file never changes.
#include <unistd.h>
#include "ros/ros.h"
#include "dynamic_reconfigure/server.h"
#include "test/dynamicParamsConfig.h"
#include <dynamic_reconfigure/BoolParameter.h>
#include <dynamic_reconfigure/Reconfigure.h>
#include <dynamic_reconfigure/Config.h>
void callback(test::dynamicParamsConfig &config, uint32_t level) {
ROS_INFO("Reconfigure request : save:%i number: %i",
config.save_data_to_file,
config.num_to_save
);
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "publisher");
ros::NodeHandle nh;
dynamic_reconfigure::Server<test::dynamicParamsConfig> server;
dynamic_reconfigure::Server<test::dynamicParamsConfig>::CallbackType f;
f = boost::bind(&callback, _1, _2);
server.setCallback(f);
while (ros::ok())
{
for (int i=0; i < 15; ++i) {
ROS_INFO("Loop: %i", i);
if (i==9) {
dynamic_reconfigure::ReconfigureRequest srv_req;
dynamic_reconfigure::ReconfigureResponse srv_resp;
dynamic_reconfigure::BoolParameter bool_param;
dynamic_reconfigure::Config conf;
bool_param.name = "save_data_to_file";
//bool_param.value = 0;
bool_param.value = false;
conf.bools.push_back(bool_param);
srv_req.config = conf;
ROS_INFO("BEFORE"); // I see this print statement
ros::service::call("/publisher/set_parameters", srv_req, srv_resp);
ROS_INFO("AFTER"); // I never see this print statement
}
sleep(2);
ros::spinOnce();
}
}
return 0;
}
Hi Green01. Can you edit the question and include your entire code? The way you are building the
conf
object and your service calling seems both right. Maybe you are just missing the "ros::init" (ros::service::call documentation)I do have a ros::init. I will work on cutting down the cpp file to something I can paste into the question.
schulze18 - can you provide any further suggestions now that I have the entire code in the question?
Hi @Green01. I don`t know if those are the problems, but i have some recommendations for your code. I never saw someone calling a service in the same node of the service server. Maybe it is not even possible, due to some concurrency problem, I don't know. But it is at least weird since you could just have a method that directly updates the variables without ROS. Try to create a second node that only calls the dynamic reconfigure service. Also, to do "timer loops", try to use the ROS time sources (http://wiki.ros.org/roscpp/Overview/C...). You can use other time sources with ROS, but it is also tricky.
You nailed it, @schulze18! I created a separate node that calls the dynamic reconfigure service. Now when the C++ code sets the value of the parameter "save_data_to_file" to false, the checkbox in the rqt_reconfigure GUI gets unchecked. Thank you so much for all your help!
Great to hear that! You are welcome. Please, create an answer to your own question with a description of what you did. Therefore, if someone ends up with the same problem, they will easily see what they need to do.
I think the problem is a deadlock, since ros callbacks are executed consecutively you get a deadlock in a one-threaded spin. So you must call the service from another node or you can use a multithread spinner.