Auto Ware 代码解析系列-can_info_translator节点

节点订阅vehicle_receiver发布过来的/can_info话题,主节点如下:

// ROS includes
#include .h>

#include "can_info_translator_core.h"

int main(int argc, char **argv)
{
  ros::init(argc, argv, "can_info_translator");
  autoware_connector::VelPoseConnectNode n;
  n.run();

  return 0;
}

代码中autoware_connector::VelPoseConnectNode n生命了autoware_connector::VelPoseConnectNode对象,并调用了类的成员函数 n.run(),下面对autoware_connector::VelPoseConnectNode类进行解析:
在can_info_translator_core.h中声明如下:

class VelPoseConnectNode
{
public:

  VelPoseConnectNode();
  ~VelPoseConnectNode();

  void run();

private:

/////声明handle
  ros::NodeHandle nh_;
  ros::NodeHandle private_nh_;

  // publisher
  ros::Publisher pub1_, pub2_, pub3_;

  // subscriber
  ros::Subscriber sub1_,sub2_;

  // variables
  VehicleInfo v_info_;
  Odometry odom_;
  // tf::TransformBroadcaster odom_broadcaster_;

  // callbacks
  void callbackFromCanInfo(const vehicle_socket::CanInfoConstPtr &msg);

  // initializer
  void initForROS();

  // functions
  void publishVelocity(const vehicle_socket::CanInfoConstPtr &msg);//发布速度
  void publishVelocityViz(const vehicle_socket::CanInfoConstPtr &msg);//发布用于rviz显示的速度
  void publishOdometry(const vehicle_socket::CanInfoConstPtr &msg);//发布odom信息
};

代码initForROS()在类的构造函数中实现了调用:

VelPoseConnectNode::VelPoseConnectNode() : private_nh_("~"), v_info_(), odom_(ros::Time::now())
{
  initForROS();
}

在回调函数中发布上述三个发布消息

void VelPoseConnectNode::callbackFromCanInfo(const vehicle_socket::CanInfoConstPtr &msg)
{
  publishVelocity(msg);
  publishVelocityViz(msg);
  publishOdometry(msg);

}

下面重点对第三个发布函数进行说明,代码如下

void VelPoseConnectNode::publishOdometry(const vehicle_socket::CanInfoConstPtr &msg)
{
  double vx = kmph2mps(msg->speed);
  double vth = v_info_.convertSteeringAngleToAngularVelocity(kmph2mps(msg->speed), msg->angle);
  odom_.updateOdometry(vx, vth, msg->header.stamp);

  geometry_msgs::Quaternion odom_quat = tf::createQuaternionMsgFromYaw(odom_.th);

  // first, we'll publish the transform over tf
  /*geometry_msgs::TransformStamped odom_trans;
  odom_trans.header.stamp = msg->header.stamp;
  odom_trans.header.frame_id = "odom";
  odom_trans.child_frame_id = "base_link";

  odom_trans.transform.translation.x = odom_.x;
  odom_trans.transform.translation.y = odom_.y;
  odom_trans.transform.translation.z = 0.0;
  odom_trans.transform.rotation = odom_quat;

  // send the transform
  odom_broadcaster_.sendTransform(odom_trans);
  */

  // next, we'll publish the odometry message over ROS
  nav_msgs::Odometry odom;
  odom.header.stamp = msg->header.stamp;
  odom.header.frame_id = "odom";

  // set the position
  odom.pose.pose.position.x = odom_.x;
  odom.pose.pose.position.y = odom_.y;
  odom.pose.pose.position.z = 0.0;
  odom.pose.pose.orientation = odom_quat;

  // set the velocity
  odom.child_frame_id = "base_link";
  odom.twist.twist.linear.x = vx;
  odom.twist.twist.angular.z = vth;

  // publish the message
  pub3_.publish(odom);
}

代码定义处有

double vth = v_info_.convertSteeringAngleToAngularVelocity(kmph2mps(msg->speed), msg->angle);
  odom_.updateOdometry(vx, vth, msg->header.stamp);

其中convertSteeringAngleToAngularVelocity主要是将控制器输出的转向角度转化成车的角速度,该部分的函数定义在VehicleInfo结构体中

namespace autoware_connector
{
struct VehicleInfo {
  bool is_stored;
  double wheel_base;
  double minimum_turning_radius;
  double maximum_steering_angle;

  VehicleInfo()
  {
    is_stored = false;
    wheel_base = 0;
    minimum_turning_radius = 0;
    maximum_steering_angle = 0;
  }
  double convertSteeringAngleToAngularVelocity(const double cur_vel_mps, const double cur_angle_deg) // rad/s
  {
    return is_stored ? tan(deg2rad(getCurrentTireAngle(cur_angle_deg))) * cur_vel_mps / wheel_base : 0;
  }
  double getCurrentTireAngle(const double angle_deg) // steering [degree] -> tire [degree]
  {
    return is_stored ? angle_deg * getMaximumTireAngle() / maximum_steering_angle: 0;
  }
  double getMaximumTireAngle() // degree
  {
    return is_stored ? rad2deg(asin(wheel_base / minimum_turning_radius)) : 0;
  }
  double rad2deg(double rad)
  {
    return rad * 180 / M_PI;
  }
  // convert degree to radian
  inline double deg2rad(double deg)
  {
    return deg * M_PI / 180;
  }
};

上述函数中TireAngle和SteeringAngle分别为车轮的转向角和方向盘的转向角度,因为两者之间存在减速比,故定义上述函数,rad2deg(asin(wheel_base / minimum_turning_radius))中可能和有些资料中定义不太一样,该处主要取决与用户如何定义:
Auto Ware 代码解析系列-can_info_translator节点_第1张图片
Auto Ware 代码解析系列-can_info_translator节点_第2张图片

函数中tan(deg2rad(getCurrentTireAngle(cur_angle_deg))) * cur_vel_mps / wheel_base 为汽车的基本运动方程,参考如下:
Auto Ware 代码解析系列-can_info_translator节点_第3张图片

整车的里程计定义结构体如下,为基本的运动方程,不错详细阐述:

    struct Odometry {
  double x;
  double y;
  double th;
  ros::Time stamp;

  Odometry(const ros::Time &time)
  {
    x = 0;
    y = 0;
    th = 0;
    stamp = time;
  }

  void updateOdometry(const double vx, const double vth, const ros::Time &cur_time)
  {

    double dt = (cur_time - stamp).toSec();
    double delta_x = (vx * cos(th)) * dt;
    double delta_y = (vx * sin(th)) * dt;
    double delta_th = vth * dt;
    std::cout << "dt : " << dt << "delta (x y th) : (" << delta_x << " " << delta_y << " " << delta_th << ")" << std::endl;


    x += delta_x;
    y += delta_y;
    th += delta_th;
    stamp = cur_time;
  }

};

你可能感兴趣的:(代码大全)