Rosanswers logo

Hi to all,

I have a ROS node which publish data coming from encoders and current sensors (the node outputs velocity data, raw encoders ticks and currents). Currently, my ROS node publish all these data as std_msgs/String, but this gives me lot of problems when I need to handle data.

I would like to publish a structured ROS message which reports the robot status; what should I use for encoders ticks, velocity values and currents?

How should I re-write the code in order to implement a correct structured message? I think the best thing to do is to publish a topic for the velocity, another one for the motor current and another for the encoder ticks.

This is my current code, as you can see I declare everything like std_msgs::String.

Thank you for your help.

while (ros::ok())
    std_msgs::String msg_sys, msg_enc, msg_io, msg_vel;
    std:string temp="", volt="", amotor="", enco="", aio="", dio=""; 
    std::stringstream ss, ss2, ss3, ssvel;          
    if (sys == 1){
      device.GetValue(_T, 0, temp);
      device.GetValue(_V, 0, volt);
      device.GetValue(_A, amotor);

      if (temp != "" && volt != "" && amotor != ""){

        std::replace(temp.begin(), temp.end(), ':', ',');
        std::replace(volt.begin(), volt.end(), ':', ',');
        std::replace(amotor.begin(), amotor.end(), ':', ',');

        ros::Time time = ros::Time::now();
        ss << time << "," << temp << "," << volt << "," << amotor << "," << count;
        msg_sys.data = ss.str();

    //Encoder Topic
    if (enc == 1){
      current_time =ros::Time::now().toSec();
      device.GetValue(_C, 0, enco);
       //enco ="15000:16000";

      if (enco != ""){

        if (velocity == 1){
        std::string vel_enco=enco;
        std::replace(vel_enco.begin(), vel_enco.end(), ':', ' ');

        const char * c_enco = vel_enco.c_str();
        char* pEnd;
        double Encoder_sx, Encoder_dx;
        double Distance_sx, Distance_dx, Distance_prev_sx, Distance_prev_dx, Vel_sx, Vel_dx;
        float Vel_linear, w;

        Encoder_sx = std::strtod (c_enco,&pEnd);
        Encoder_dx = std::strtod (pEnd,&pEnd);
        Distance_sx = (Encoder_sx)*sprocket;
        Distance_dx = (Encoder_dx)*sprocket;

        last_time =ros::Time::now().toSec();
        Vel_sx = ((Distance_prev_sx - Distance_sx) / (last_time - current_time))/1000; // m / sec 
        Vel_dx = ((Distance_prev_dx - Distance_dx) / (last_time - current_time))/1000;  

        Distance_prev_sx = Distance_sx;
        Distance_prev_dx = Distance_dx;

        Vel_linear = (Vel_dx + Vel_sx)/2;
        w = (Vel_dx - Vel_sx)/track;

        ros::Time time2 = ros::Time::now();

        //Publish velocity topic
        ssvel << time2 << "," << Distance_sx << "," << Distance_dx << "," << Vel_sx << "," << Vel_dx << "," << Vel_linear << "," << w;
        msg_vel.data = ssvel.str();

        ros::Time time3 = ros::Time::now();

        std::replace(enco.begin(), enco.end(), ':', ',');
        //Publish enco topic
        ss2 << time3 << "," << enco << "," << count;
        msg_enc.data = ss2.str();

Originally posted by Marcus Barnet on ROS Answers with karma: 287 on 2018-03-22

Post score: 1

Original comments

Comment by gvdhoorn on 2018-03-22:
To take this question a bit broader: do you want to stay at the abstraction level of "ticks" and "encoders", or would it make sense to have your node(s) publish more semantically meaningful messages with fields in SI units?

That could be done by the 'next' node btw, but is something to consider.

Comment by Marcus Barnet on 2018-03-22:
This would be even better, but also the absolute values are OK for me. For example, having something like:

left_ticks: 1234
right_ticks: 2345

works fine for me; what I would like to obtain is to output the values as integers and floats so I can plot them in rqt_plot or use them for other purposes.

Comment by Marcus Barnet on 2018-03-22:
At the moment, the std_msgs::String format is giving me lots of problems when I have to handle the node output.


1 Answer 1


Rosanswers logo

Just create your own message file (as detailed in the Wiki).

In your case, something like

time timestamp
int32 left_ticks
int32 right_ticks
float32 left_rotation_radian
float32 right_rotation_radian

should do the trick (I assumed rotations, change for linear motion). The linked wiki page tells you everything you need to know to create, build and use such custom messages.

I agree with @gvdhoorn that a result in SI units is a better idea. If you change something to the hardware, you should only change the driver (or a configuration parameter used by the driver), not all nodes relying on the driver. If you really want to use ticks, add a radian_per_tick (or m_per_tick) field and use that for calculations in other nodes.

Originally posted by Maarten with karma: 206 on 2018-03-22

This answer was ACCEPTED on the original site

Post score: 0


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.