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

I want to use differentials in ros

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

renanmb gravatar image

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

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 -0500

jayess gravatar image

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

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 image renanmb  ( 2017-08-11 17:27:16 -0500 )edit

Can you update your question with that output?

jayess gravatar image jayess  ( 2017-08-11 18:33:16 -0500 )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 image renanmb  ( 2017-08-11 19:12:39 -0500 )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 image jayess  ( 2017-08-11 19:46:42 -0500 )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 image renanmb  ( 2017-08-13 22:01:15 -0500 )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 image jayess  ( 2017-08-13 22:05:02 -0500 )edit
1

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

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
1

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

lucasw gravatar image

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

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 image renanmb  ( 2017-08-11 18:07:20 -0500 )edit

Question Tools

1 follower

Stats

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

Seen: 1,602 times

Last updated: Aug 11 '17