Hi I am writing a ROS node where I am subscribing to a ROS topic and publishing the data using zeromq. I have declared a variable "var
" which is a float and is being utilized in the callback
function. When I am building this code I am getting the following error -
error: ‘var’ was not declared in this scope
robotData.sendMessage(&var);
Can someone help me figure out the correct way of parsing this variable?? Any help is appreciated.
This is the header file
#ifndef R_DATA
#define R_DATA
#include <nav_msgs/Odometry.h>
#include <ros/ros.h>
#include <iostream>
#include <zmq.hpp>
class RobotData {
public:
RobotData(ros::NodeHandle* nodehandle);
zmq::context_t context;
zmq::socket_t publisher;
void connect();
void sendMessage(float);
void disconnect();
private:
ros::NodeHandle nh;
ros::Subscriber odometry;
float var;
void initializeSubscribers();
void callback(const nav_msgs::Odometry::ConstPtr& msg);
};
#endif
This is the main node -
#include <ros/ros.h>
#include <zmq.hpp>
RobotData::RobotData(ros::NodeHandle* nodehandle)
: nh(*nodehandle), context(1), publisher(context, ZMQ_REQ) {
initializeSubscribers();
var = 0;
}
void RobotData::initializeSubscribers() {
odometry = nh.subscribe("/odometry", 10, &RobotData::callback, this);
}
void RobotData::callback(const nav_msgs::Odometry::ConstPtr& msg) {
float x = msg->twist.twist.linear.x;
float y = msg->twist.twist.linear.y;
var = x y;
}
void RobotData::connect() {
publisher.bind("tcp://*:6666");
}
void RobotData::sendMessage(float msg) {
std::stringstream msg_str_stream;
msg_str_stream << msg;
std::string msg_str = msg_str_stream.str();
zmq::message_t message(msg_str.length());
memcpy(message.data(), msg_str.c_str(), msg_str.length());
ROS_INFO_STREAM(msg_str);
publisher.send(message);
}
void RobotData::disconnect() {
publisher.close();
context.close();
}
int main(int argc, char** argv) {
ros::init(argc, argv, "pub_node", ros::init_options::AnonymousName);
ros::NodeHandle nh;
RobotData robotData(&nh);
robotData.connect();
robotData.sendMessage(&var);
robotData.disconnect();
ros::spin();
}
CodePudding user response:
Look at the method signature of Robot::sendMessage
:
void RobotData::sendMessage(float msg)
You want to pass the value and not the address of the var
. Also, var
is not declared in the main
function but as a private class field. To access it, define a getter method in the RobotData
class. For example:
public:
.
.
float getVar() const { return var; }
Then use it in the main
function. However, ensure that it has been correctly initialized before it comes into use to avoid unfortunate UBs.
CodePudding user response:
At very first: &var
would produce pointer, i.e. a float*
, not a float
, if there was a float var
somewhere in main
.
Within main
you'd need to write robotData.sendMessage(robotData.var)
to get access to the var
variable stored in robotData
– however, as mentioned in the comments already, this one is private, so you still cannot access it.
Moving it to public section would solve the issue but obviously is not a good idea for hurting the encapsulation principle. So you might want to provide another overload sending its own var
to the RobotData
type:
class RobotData
{
public:
// ...
void sendMessage(float);
void sendMessage()
{
sendMessage(var);
}
private:
var float;
};
I have some doubts if it is meaningful to allow to send arbitrary, possibly not meaningful data to the robot, so better alternative might be just dropping the parameter from the sole overload existing then (assuming you calculate its value internally anyway, or why is it private then?):
class RobotData
{
public:
// ...
void sendMessage(/*float*/);
private:
var float;
};
void RobotData::sendMessage()
{
// use var instead of original parameter name
}
Side note: Floating point types (float
, double
) can easily introduce trouble like rounding and comparison issues (see e.g. here) or incompatible bit pattern interpretations (not all hardware is guaranteed to use IEEE754 standard and even if it does different hardware might still show minor differences, e.g. in rounding modes). If the floating point is not given as fixed by the robot then I'd consider changing to integrals (if need be with fixed comma arithmetic, i.e. units in subprecision like e.g. cents instead of euro/dollar).