Search code examples
c++arraysloopscallbackros

Put data from one topic into a dynamic array in the Callback function and do some calculation


I am reading my hand pose from a Leap Motion sensor and I want to calculate how fast the hand moves (by calculating derivativex = dx / dt) in X direction. My solution is to put 100 hand pose values in an array and keep updating this array with new values when new messages (msg->palmpos.x) arrive in the callback function through topic leapmotion/data.

My question is when I print the derivativex = dx / dt with ROS_ERROR("Hello %f", "derivativex") the output is always: 0

what I've been doing wrong? link for the topic that my callback is listening.

my call back function:

#include "geometry_msgs/TwistStamped.h"
#include "jog_msgs/JogJoint.h"
#include "jog_msgs/leapros.h"
#include "ros/ros.h"
#include <ros/console.h>
#include <iostream>
#include <iomanip>
#include <array>
using namespace std;

namespace to_twist
{
class spaceNavToTwist
{
public:
  spaceNavToTwist() : spinner_(1)


{
    joy_sub_ = n_.subscribe("leapmotion/data", 1, &spaceNavToTwist::joyCallback, this);
    // Changed "spacenav/joy" to topic "/leapmotion/data"
    twist_pub_ = n_.advertise<geometry_msgs::TwistStamped>("jog_arm_server/delta_jog_cmds", 1);
    joint_delta_pub_ = n_.advertise<jog_msgs::JogJoint>("jog_arm_server/joint_delta_jog_cmds", 1);

    spinner_.start();
    ros::waitForShutdown();
  };

  const int arraySize = 100;// constant variable can be used to specify array size
  double vectorx[ arraySize ] = {};// initialize elements of array n to 0
  int resolution = 10;
  double derivativex = 0;
  double dx = 0; 
  int dt = 0;

private:

  ros::NodeHandle n_;
  ros::Subscriber joy_sub_;
  ros::Publisher twist_pub_, joint_delta_pub_;
  ros::AsyncSpinner spinner_;
  // Convert incoming joy commands to TwistStamped commands for jogging.
  void joyCallback(const jog_msgs::leapros::ConstPtr& msg)
 { 
    for ( int count = 0; count < arraySize; ++count ) {// store the values of poses
       vectorx[ count ] = msg->palmpos.x;
       if (count>resolution) {
           dx = vectorx[ count-1 ] - vectorx[ count-(resolution-1) ];
           dt = resolution;
           derivativex = dx / dt;
           ROS_ERROR("Hello %f", derivativex);

       }    

       if (count == arraySize) {
           count=0;  
       }
    }

Solution

  • Issue 1: The log function ROS_ERROR is misused. You should pass a float instead of a string, otherwise, you will get an undefined behavior :

           ROS_ERROR("Hello %f", derivativex); // <-- there is no double quotes.
    

    Issue 2: derivative of X is always 0 because of the assignment at the beginning of the for loop:

    for ( int count = 0; count < arraySize; ++count ) {// store the values of poses
    
           //Could you please explain why the program needs this ???
           vectorx[ count ] = msg->palmpos.x; // <-- every element in vectorx is set to this values (const in each function call).
    
           if (count>resolution) {
               dx = vectorx[ count-1 ] - vectorx[ count-(resolution-1) ]; // is the same as (msg->palmpos.x - msg->palmpos.x) --> 0
    
               dt = resolution;
               derivativex = dx / dt;
    
               ROS_ERROR("Hello %f", derivativex);
           }    
    
           if (count == arraySize) {
               count = 0;  //<-- never get here because of count is always lesser than arraySize 
           }
    }
    

    I guess that you want to append msg->palmpos.x to the vectorx ? You should use std::vector for vectorx, it will be much easier.

    Here is the modified version of your program, using std::vector :

    //add this to your file
    #include <vector>
    
    //Your program body ...
    //...
    
    //As we are using C++, try to use C++ facilities if possible.
    //const int arraySize = 100;// constant variable can be used to specify array size
    //double vectorx[ arraySize ] = {};// initialize elements of array n to 0
    
    std::vector<double> vectorx;
    
    int resolution = 10;
    int max_vector_size = 100; //keep 100 elements in the vectorx.
    //...
    
    // Convert incoming joy commands to TwistStamped commands for jogging.
    void joyCallback(const jog_msgs::leapros::ConstPtr& msg)
    { 
         //store the x coordinate in the vectorx
         vectorx.push_back( msg->palmpos.x );
    
         if( vectorx.size() > resolution ){
             int id_back = vectorx.size() - 1;
             double dx = vectorx[id_back] - vectorx[ id_back - resolution ];
             double dt = resolution;
    
             derivativex = dx / dt;
             ROS_ERROR("Hello %f", derivativex);
         }
    
         while(vectorx.size() > max_vector_size ) {
             vectorx.erase( vectorx.begin() ); //remove the first element
         }
    
    }//eof joyCallback