ROS类方法回调错误

时间:2017-12-14 14:17:48

标签: c++ class static ros member-function-pointers

我正在敲打这个错误。我创建了3个文件,其中1个是main.cpp,第2个是.cpp文件,第3个是.hpp代码文件。 由于某种原因,当我尝试从类方法调用它时,订阅者回调函数给我一个错误。代码如下:

文件1:main.cpp

#include "ControlTurtlebot.hpp"

int main(int argc, char **argv){

//initialize the ROS node
ros::init(argc, argv, "free_space_navigation_node");
ros::NodeHandle n;

ControlTurtlebot obj;

//subscribe to the odometry topic to get the position of the robot
obj.pose_subscriber = n.subscribe("/odom", 10, &ControlTurtlebot::poseCallback, &obj);
//register the velocity publisher
obj.pub =n.advertise<geometry_msgs::Twist>("mobile_base/commands/velocity", 1000);

ros::spinOnce();
ros::Rate loop(1);
loop.sleep();loop.sleep();loop.sleep();//loop.sleep();loop.sleep();
ros::spinOnce();

while (ros::ok()){
    ros::spinOnce();loop.sleep();
    printf("robot initial pose: (%.2f, %.2f, %.2f)\n", obj.turtlebot_odom_pose.pose.pose.position.x, obj.turtlebot_odom_pose.pose.pose.position.y, obj.radian2degree(tf::getYaw(obj.turtlebot_odom_pose.pose.pose.orientation)));

    double velocity = 0.3;

    obj.moveShape(1.0, 3, 120, velocity);

    //exercise: try to remove the ros::SpinOnce() and observe and comment the result
    ros::spinOnce();loop.sleep();ros::spinOnce();
    printf("robot final pose: (%.2f, %.2f, %.2f)\n", obj.turtlebot_odom_pose.pose.pose.position.x, obj.turtlebot_odom_pose.pose.pose.position.y, obj.radian2degree(tf::getYaw(obj.turtlebot_odom_pose.pose.pose.orientation)));
    return 0;
}

return 0;

}

另一个文件是:

文件2:ControlTurtlebot.hpp

#pragma once

#ifndef INCLUDE_CONTROLTURTLEBOT_HPP_
#define INCLUDE_CONTROLTURTLEBOT_HPP_

#include "ros/ros.h"
#include "geometry_msgs/Twist.h"
#include "sensor_msgs/LaserScan.h"
#include "nav_msgs/Odometry.h"
#include "tf/tf.h"
#include <tf/transform_listener.h>
#include <fstream>

class ControlTurtlebot {


  public:

  #define ANGULAR_VELOCITY_MINIMUM_THRESHOLD 0.4
  #define pi 22/7

  //declare publishers
  ros::Publisher pub;
  //declare subscribers
  ros::Subscriber pose_subscriber;
  //global variable to update the position of the robot
  nav_msgs::Odometry turtlebot_odom_pose;

  ros::NodeHandle n;


  //callback function for the /odom topic to update the pose
  void poseCallback(const nav_msgs::Odometry::ConstPtr& pose_message);



  //the function that makes the robot moves forward and backward
  void move_linear(double speed, double distance, bool isForward);

  //the function that makes the robot rotates left and right
  double rotate(double ang_vel, double angle_radian, bool isClockwise);

  double degree2radian(double degreeAngle);
  double radian2degree(double radianAngle);

  void moveShape(double sideLength, double totalSides, double angle, double velocity);

};

#endif

` 最后一个文件是:

文件3:ControlTurtlebot.cpp

#include "ControlTurtlebot.hpp"



void ControlTurtlebot::poseCallback(const nav_msgs::Odometry::ConstPtr& pose_message){

turtlebot_odom_pose.pose.pose.position.x=pose_message->pose.pose.position.x;
turtlebot_odom_pose.pose.pose.position.y=pose_message->pose.pose.position.y;
turtlebot_odom_pose.pose.pose.position.z=pose_message->pose.pose.position.z;

turtlebot_odom_pose.pose.pose.orientation.w=pose_message->pose.pose.orientation.w;
turtlebot_odom_pose.pose.pose.orientation.x=pose_message->pose.pose.orientation.x;
turtlebot_odom_pose.pose.pose.orientation.y=pose_message->pose.pose.orientation.y;
turtlebot_odom_pose.pose.pose.orientation.z=pose_message->pose.pose.orientation.z;

}



void ControlTurtlebot::moveShape(double sideLength, double totalSides, double angle, double velocity){
    for (int i=0;i<totalSides;i++){
        move_linear(velocity, sideLength, true);
        rotate (velocity, degree2radian(angle), true);
    }   
}


void ControlTurtlebot::move_linear(double speed, double distance, bool isForward){
    //delcare a Twist message to send velocity commands
    geometry_msgs::Twist VelocityMessage;
    //initial pose of the turtlebot before start moving
    nav_msgs::Odometry initial_turtlebot_odom_pose;

    //set the linear velocity to a positive value if isFoward is true
    if (isForward)
        VelocityMessage.linear.x =abs(speed);
    //all velocities of other axes must be zero.
    VelocityMessage.linear.y = VelocityMessage.linear.z =VelocityMessage.angular.x =VelocityMessage.angular.y =VelocityMessage.angular.z =0;

    double distance_moved = 0.0;
    ros::Rate loop_rate(10); // we publish the velocity at 10 Hz (10 times a second)

    //we update the initial_turtlebot_odom_pose using the turtlebot_odom_pose global variable updated in the callback function poseCallback
    initial_turtlebot_odom_pose = turtlebot_odom_pose;

    do{
        pub.publish(VelocityMessage);
        ros::spinOnce();
        loop_rate.sleep();
        distance_moved = sqrt(pow((turtlebot_odom_pose.pose.pose.position.x-initial_turtlebot_odom_pose.pose.pose.position.x), 2) +
            pow((turtlebot_odom_pose.pose.pose.position.y-initial_turtlebot_odom_pose.pose.pose.position.y), 2));

    }while((distance_moved<distance)&&(ros::ok()));
//finally, stop the robot when the distance is moved
    VelocityMessage.linear.x =0;
    pub.publish(VelocityMessage);
}



double ControlTurtlebot::rotate(double angular_velocity, double radians,  bool clockwise)
{

//delcare a Twist message to send velocity commands
geometry_msgs::Twist VelocityMessage;
//declare tf transform listener: this transform listener will be used to listen and capture the transformation between
// the odom frame (that represent the reference frame) and the base_footprint frame the represent moving frame
tf::TransformListener TFListener;
//declare tf transform
//init_transform: is the transformation before starting the motion
tf::StampedTransform init_transform;
//current_transformation: is the transformation while the robot is moving
tf::StampedTransform current_transform;
//initial coordinates (for method 3)
nav_msgs::Odometry initial_turtlebot_odom_pose;

double angle_turned =0.0;

//validate angular velocity; ANGULAR_VELOCITY_MINIMUM_THRESHOLD is the minimum allowed
angular_velocity=((angular_velocity>ANGULAR_VELOCITY_MINIMUM_THRESHOLD)?angular_velocity:ANGULAR_VELOCITY_MINIMUM_THRESHOLD);

while(radians < 0) radians += 2*pi;
while(radians > 2*pi) radians -= 2*pi;

//wait for the listener to get the first message
TFListener.waitForTransform("base_footprint", "odom", ros::Time(0), ros::Duration(1.0));

//record the starting transform from the odometry to the base frame
TFListener.lookupTransform("base_footprint", "odom", ros::Time(0), init_transform);

//the command will be to turn at 0.75 rad/s
VelocityMessage.linear.x = VelocityMessage.linear.y = 0.0;
VelocityMessage.angular.z = angular_velocity;
if (clockwise) VelocityMessage.angular.z = -VelocityMessage.angular.z;

//the axis we want to be rotating by
tf::Vector3 desired_turn_axis(0,0,1);
if (!clockwise) desired_turn_axis = -desired_turn_axis;

ros::Rate rate(10.0);
bool done = false;
while (!done )
{
    //send the drive command
    pub.publish(VelocityMessage);
    rate.sleep();
    //get the current transform
    try
    {
        TFListener.waitForTransform("base_footprint", "odom", ros::Time(0), ros::Duration(1.0));
        TFListener.lookupTransform("base_footprint", "odom", ros::Time(0), current_transform);
    }
    catch (tf::TransformException ex)
    {
        ROS_ERROR("%s",ex.what());
        break;
    }
    tf::Transform relative_transform = init_transform.inverse() * current_transform;
    tf::Vector3 actual_turn_axis = relative_transform.getRotation().getAxis();
    angle_turned = relative_transform.getRotation().getAngle();

    if (fabs(angle_turned) < 1.0e-2) continue;
    if (actual_turn_axis.dot(desired_turn_axis ) < 0 )
        angle_turned = 2 * pi - angle_turned;

    if (!clockwise)
        VelocityMessage.angular.z = (angular_velocity-ANGULAR_VELOCITY_MINIMUM_THRESHOLD) * (fabs(radian2degree(radians-angle_turned)/radian2degree(radians)))+ANGULAR_VELOCITY_MINIMUM_THRESHOLD;
    else
        if (clockwise)
            VelocityMessage.angular.z = (-angular_velocity+ANGULAR_VELOCITY_MINIMUM_THRESHOLD) * (fabs(radian2degree(radians-angle_turned)/radian2degree(radians)))-ANGULAR_VELOCITY_MINIMUM_THRESHOLD;

    if (angle_turned > radians) {
        done = true;
        VelocityMessage.linear.x = VelocityMessage.linear.y = VelocityMessage.angular.z = 0;
        pub.publish(VelocityMessage);
    }

}
if (done) return angle_turned;
return angle_turned;
}

/* makes conversion from radian to degree */
double ControlTurtlebot::radian2degree(double radianAngle){
return (radianAngle*57.2957795);
}


/* makes conversion from degree to radian */
double ControlTurtlebot::degree2radian(double degreeAngle){
    return (degreeAngle/57.2957795);
}

我在main.cpp文件中使用上述订阅者回调的错误是:

  

CMakeFiles / free_space_navigation_node.dir / src / main.cpp.o:在功能中   main': main.cpp:(.text+0x400): undefined reference to ControlTurtlebot :: poseCallback(升压:: shared_ptr的

     
    

常量&GT;常量&安培;)&#39; main.cpp :(。text + 0x5f0):未定义引用ControlTurtlebot::radian2degree(double)' main.cpp:(.text+0x674): undefined reference to ControlTurtlebot :: moveShape(double,double,     双,双)&#39; main.cpp :(。text + 0x6b1):未定义的引用     `ControlTurtlebot :: radian2degree(双)&#39; collect2:错误:ld返回     1退出状态     toy_robot / CMakeFiles / free_space_navigation_node.dir / build.make:118:     目标食谱     &#39; /家/ VIKI / catkin_ws / devel的/ lib目录/ toy_robot / free_space_navigation_node&#39;     失败了[2]: *     [/家庭/ VIKI / catkin_ws / devel的/ lib目录/ toy_robot / free_space_navigation_node]     错误1 CMakeFiles / Makefile2:2938:目标的配方     &#39; toy_robot / CMakeFiles / free_space_navigation_node.dir /所有&#39;失败     make [1]:* [toy_robot / CMakeFiles / free_space_navigation_node.dir / all]     错误2 Makefile:138:目标配方&#39;全部&#39;失败了:*** [全部]     错误2

  

如果我改变了main.cpp中的订阅回调行:

    obj.pose_subscriber = n.subscribe("/odom", 10, &ControlTurtlebot::poseCallback, &obj);

    obj.pose_subscriber = n.subscribe("/odom", 10, ControlTurtlebot::poseCallback);

所以我收到如下错误:

  

错误:无效使用非静态成员函数'void   ControlTurtlebot :: poseCallback(const ConstPtr&amp;)'       obj.pose_subscriber = n.subscribe(&#34; / odom&#34;,10,ControlTurtlebot :: poseCallbac                                                                        ^ toy_robot / CMakeFiles / free_space_navigation_node.dir / build.make:62:   目标食谱   &#39; toy_robot / CMakeFiles / free_space_navigation_node.dir / SRC / main.cpp.o&#39;   失败了[2]: *   [toy_robot / CMakeFiles / free_space_navigation_node.dir / SRC / main.cpp.o]   错误1 CMakeFiles / Makefile2:2938:目标的配方   &#39; toy_robot / CMakeFiles / free_space_navigation_node.dir /所有&#39;失败   make [1]:* [toy_robot / CMakeFiles / free_space_navigation_node.dir / all]   错误2 Makefile:138:目标配方&#39;全部&#39;失败了:*** [全部]   错误2

我不明白这是什么问题。我也尝试将callfunction定义从void更改为static void callback(),但它再次恢复为第一个错误,类似于我使用上述订阅者方法时。

任何帮助都会非常感激!

谢谢!

0 个答案:

没有答案