Ask Your Question
0

I want to use differentials in ros

asked 2017-08-11 15:58:31 -0600

renanmb gravatar image

updated 2017-08-11 18:41:47 -0600

My goal was to create TimeStamps to make a simple differentiation. I don't know yet how to use ros::Time.

This my pd_controller node:

    #include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <std_msgs/Float32.h>
#include <std_msgs/Float64.h>
#include <std_msgs/Int32.h>
#include "pd_controller/Int32Stamped.h"
#include <math.h>

pd_controller::Int32Stamped encoder;

ros::Subscriber encoder_sub;
ros::Publisher vel_pub;
geometry_msgs::Twist vel;       

// subscriber from comm encoder
void encoderCallback(const pd_controller::Int32Stamped::ConstPtr& tk){

//Modify this equation to be the Controller Function
    // double timelapse[10] = {0};
   double timelapse = encoder.header.stamp.toSec() -encoder.header.stamp.toSec();
   double kd = (double(encoder.data) - double(encoder.data))/timelapse;
   vel.linear.x = float(((encoder.data*234)*5886) + kd);
   encoder.data = tk->data;
   encoder.header = tk->header; 
   vel_pub.publish(vel);
}


//make publisher for cmd_vel

//create a rotary encoder to send cmd_vel

int main(int argc, char** argv){
   ros::init(argc, argv, "pd_controller");
   ros::NodeHandle nh;
   vel_pub = nh.advertise<geometry_msgs::Twist>("cmd_vel", 1);
   encoder_sub = nh.subscribe<pd_controller::Int32Stamped> ("comm_encoder", 10, &encoderCallback); 


   ros::spin();

   return 0;
}

When I run the code I get as output in cmd_vel the value: nan

How do I properly set a differential equation in ROS???? I just want after_topic - before_topic divided by the time difference between these topics.

edit retag flag offensive close merge delete

3 Answers

Sort by » oldest newest most voted
1

answered 2017-08-11 16:35:32 -0600

jayess gravatar image

updated 2017-08-11 18:44:55 -0600

If I recall correctly, from your previous question you defined surp::Int32Stamped to be

Header header
int32 data

The header portion of your message has a stamp attribute which carries the time, as you know. According to the wiki, the way that you convert from ros::Duration to floating point is by using the toSec() method, not by casting. For example:

double secs =ros::Time::now().toSec();

ros::Duration d(0.5);
secs = d.toSec();

Therefore, you should change

double timelapse = double(encoder.header.stamp) - double(encoder.header.stamp);

to

double timelapse = encoder.header.stamp.toSec() - encoder.header.stamp.toSec();

But, this raises another issue. Isn't this just going to be zero...


Edit:

If I'm understanding you correctly, should either use a global (easiest, not necessarily the best way) to keep track of the previous time that the callback was called or use a class and have an attribute that does that.

I've used the ... for brevity, but here's an example (using a global):

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>

...

double previous_time;

// subscriber from comm encoder
void encoderCallback(const surp::Int32Stamped::ConstPtr& tk){

  //Modify this equation to be the Controller Function
  double timelapse = encoder.header.stamp.toSec() - previous_time;
  previous_time = encoder.header.stamp.toSec();

...

int main(int argc, char** argv){
   ros::init(argc, argv, "pd_controller");
   ros::NodeHandle nh;
   vel_pub = nh.advertise<geometry_msgs::Twist>("cmd_vel", 1);
   encoder_sub = nh.subscribe<std_msgs::Int32> ("comm_encoder", 10, &encoderCallback); 

   previous_time = ros::Time::now().toSec();

   ros::spin();

   return 0;
}
edit flag offensive delete link more

Comments

I finally understood how Header works. I corrected it few minnutes after I posted here. The main issue is how to do a differential in ROS. If I uderstand it everything else that follows will be easy, like integrals, sensor fusion, ...etc. Yes, it is 0, and gives me nan how do I do it right?

renanmb gravatar imagerenanmb ( 2017-08-11 17:27:16 -0600 )edit

Can you update your question with that output?

jayess gravatar imagejayess ( 2017-08-11 18:33:16 -0600 )edit

Ok, it worked. Now I need to explore how to tweek it, because it is not generating the right output. Probably topic for another questions. Someone need to write a tutorial on how to create controllers following the Ogata book. Teach from PID to LQR and LQG.

renanmb gravatar imagerenanmb ( 2017-08-11 19:12:39 -0600 )edit

I believe that questions regarding how to write controllers would be out of the scope of this site (as it's not ROS specific). It would be better asked on a site like Stack Overlfow

jayess gravatar imagejayess ( 2017-08-11 19:46:42 -0600 )edit

I strongly disagree to you jayess, people who apply ROS has intention in building robots. Controllers are ultimately what enables you go from simple robots to real cool ones. Controllers are extremely important and is very sad the fact there is no tutorial on ROS wiki.

renanmb gravatar imagerenanmb ( 2017-08-13 22:01:15 -0600 )edit

I agree that controllers are important to robotics and engineering in general. However, this site is for ROS-related questions. There are other sites dedicated to questions about robotics in general such as Robotics Stack Exchange.

jayess gravatar imagejayess ( 2017-08-13 22:05:02 -0600 )edit
1

answered 2017-08-11 16:28:01 -0600

lucasw gravatar image

updated 2017-08-11 16:29:26 -0600

http://wiki.ros.org/roscpp/Overview/Time

Subtracting a stamp (ros::Time) from a stamp produces a ros::Duration, which has to be converted to a double:

ros::Duration d(0.5);
double secs = d.toSec()

I don't understand how there isn't a different error message for the code you posted though, either double(timestamp) should produce an error, or timelapse is a double and there would be no error for it.

It looks like you want to subtract encoder.data from tk.data and similar for the timestamps, otherwise you are going to get a divide by zero, and zero in the numerator besides.

Hopefully the error here is obvious:

encoder.header.stamp = tk->header;
edit flag offensive delete link more

Comments

but how do I do the differentiation?? It is giving me nan How do I do after_topic - before_topic and divide by the time difference ?

renanmb gravatar imagerenanmb ( 2017-08-11 18:07:20 -0600 )edit
1

answered 2017-08-11 16:35:41 -0600

ahendrix gravatar image

It looks like you're trying to copy the header from one message into the timestamp in another message, and the compiler is trying to tell you that these types aren't compatible.

The relevant error message is:

home/rmb/gopigo_ws/src/pd_controller/src/pd_controller.cpp:24:25: error: no match for ‘operator=’ (operand types are ‘std_msgs::Header_<std::allocator<void> >::_stamp_type {aka ros::Time}’ and ‘const _header_type {aka const std_msgs::Header_<std::allocator<void> >}’)
encoder.header.stamp = tk->header;

It looks like you should update that line so that it's just copying the timestamp:

encoder.header.stamp = tk->header.stamp;
edit flag offensive delete link more

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

1 follower

Stats

Asked: 2017-08-11 15:58:31 -0600

Seen: 640 times

Last updated: Aug 11 '17