ROS连接ky9250(mpu9250)角度姿态传感器

1、和usb头的接线方式

usb头            ky9250模块

3.3v    ------    vcc

Rx      ------   Tx

Tx      ------    Rx

Gnd   ------    Gnd

2、安装ch340-64串口驱动(文章后下载包中有)

3、ROS中拷贝入下面代码:(文章后下载包中有完整的ROS代码)

serial_port.cpp



#include "ky_imu/serial_port.h"

SerialPort::SerialPort(void) : end_of_line_char_('\n')
{

}

SerialPort::~SerialPort(void)
{
	stop();
}

char SerialPort::end_of_line_char() const
{
	return this->end_of_line_char_;
}

void SerialPort::end_of_line_char(const char &c)
{
	this->end_of_line_char_ = c;
}
std::vector<std::string> SerialPort::get_port_names()
{
	std::vector<std::string> names;
	return names;
}

int SerialPort::get_port_number()
{
	std::vector<std::string> names = get_port_names();
	return names.size();
}

std::string SerialPort::get_port_name(const unsigned int &idx)
{
	std::vector<std::string> names = get_port_names();
	if (idx >= names.size()) return std::string();
	return names[idx];
}

void SerialPort::print_devices()
{
	std::cout << "SerialPort::print_devices()" << std::endl;
	int n = SerialPort::get_port_number();
	for (int i = 0; i < n; ++i) {
		std::string name = SerialPort::get_port_name(i);
		std::cout << "\t" << name.c_str() << std::endl;
	}
}

bool SerialPort::start(const char *com_port_name, int baud_rate)
{
    port_name_=com_port_name;
	boost::system::error_code ec;

	if (port_) {
		std::cout << "error : port is already opened..." << std::endl;
		return false;
	}

	port_ = serial_port_ptr(new boost::asio::serial_port(io_service_));
	port_->open(com_port_name, ec);
	if (ec) {
		std::cout << "error : port_->open() failed...com_port_name="
			<< com_port_name << ", e=" << ec.message().c_str() << std::endl; 
		return false;
	}

	// option settings...
	port_->set_option(boost::asio::serial_port_base::baud_rate(baud_rate));
	port_->set_option(boost::asio::serial_port_base::character_size(8));
	port_->set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
	port_->set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
	port_->set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));

//	boost::thread t(boost::bind(&boost::asio::io_service::run, &io_service_));



    boost::thread t(boost::bind(&SerialPort::run, this));
      async_read_some_();
      return true;
    }





void SerialPort::run()
{
    while(ros::ok())
    {
        io_service_.run();
        io_service_.reset();
    }
}

void SerialPort::stop()
{
	boost::mutex::scoped_lock look(mutex_);

	if (port_) {
		port_->cancel();
		port_->close();
		port_.reset();
	}
	io_service_.stop();
	io_service_.reset();
}

int SerialPort::write_some(const std::string &buf)
{
	return write_some(buf.c_str(), buf.size());
}

int SerialPort::write_some(const char *buf, const int &size)
{
	boost::system::error_code ec;

	if (!port_) return -1;
	if (size == 0) return 0;

	return port_->write_some(boost::asio::buffer(buf, size), ec);
}

void SerialPort::async_read_some_()
{
	if (port_.get() == NULL || !port_->is_open()) return;
    //读满才返回
    async_read(*port_,boost::asio::buffer(read_buf_raw_, SERIAL_PORT_READ_BUF_SIZE),
               boost::bind(
                   &SerialPort::on_receive_,
                   this, boost::asio::placeholders::error,
                   boost::asio::placeholders::bytes_transferred));
      //有数据就返回
//    port_->async_read_some(
//        boost::asio::buffer(read_buf_raw_, SERIAL_PORT_READ_BUF_SIZE),
//        boost::bind(
//            &SerialPort::on_receive_,
//            this, boost::asio::placeholders::error,
//            boost::asio::placeholders::bytes_transferred));

//    boost::asio::async_read_until(*port_,sbuf_, '3a',
//                                  boost::bind(&SerialPort::on_receive_,this, boost::asio::placeholders::error,
//                                  boost::asio::placeholders::bytes_transferred));

}

void SerialPort::on_receive_(const boost::system::error_code& ec, size_t bytes_transferred)
{
	boost::mutex::scoped_lock look(mutex_);
    if (port_.get() == NULL || !port_->is_open()) return;
    if (ec) {
        async_read_some_();
        return;
    }
    for (unsigned int i = 0; i < bytes_transferred; ++i) {
    buffer_.push_back(read_buf_raw_[i]);
//    printf("i=%d,%02x\r\n",i,read_buf_raw_[i]);

    }
	async_read_some_();
}


bool SerialPort::get_data(std::vector<u_char>*data)
{
    boost::mutex::scoped_lock look(mutex_);
    if(buffer_.size()>=SERIAL_PORT_READ_BUF_SIZE*2)
    {
        data->assign(buffer_.begin(),buffer_.end());
        buffer_.erase(buffer_.begin(),buffer_.begin()+SERIAL_PORT_READ_BUF_SIZE);//删除上一个数据
        return true;
    }
    else {
        return false;
    }
//    if(buffer_.size()>=SERIAL_PORT_READ_BUF_SIZE)
//    {
//        data.assign(buffer_.begin(),buffer_.end());
//        buffer_.erase(buffer_.begin(),buffer_.end());//删除上一个数据
//        return true;
//    }
//    else {
//        return false;
//    }


}

 ky_imu.cpp

#include <ros/ros.h>
#include <sensor_msgs/Imu.h>
#include <std_msgs/String.h>
#include <std_msgs/Float32.h>
#include <string>
#include <boost/asio.hpp>                 
#include <boost/bind.hpp>
#include <tf/transform_broadcaster.h>
#include <cmath>
#include<ky_imu/serial_port.h>
#include<tf2_ros/static_transform_broadcaster.h>
#include<geometry_msgs/TransformStamped.h>

using namespace std;
using namespace boost::asio;           //定义一个命名空间,用于后面的读写操作
                     //定义字符串长度,IMU返回的数据是53个字节一组,可用串口调试助手获得


typedef float float32_t;
struct _sensorData
{

  float32_t gX;
  float32_t gY;
  float32_t gZ;

  float32_t accX;
  float32_t accY;
  float32_t accZ;

  float32_t mX;
  float32_t mY;
  float32_t mZ;

  float32_t roll;
  float32_t pitch;
  float32_t yaw;

  float32_t q1;
  float32_t q2;
  float32_t q3;
  float32_t q4;
} sensorData;

bool parse_data(std::vector<u_char>& dataBuffer)
{
// Check header byte
  if(dataBuffer.size() == 0){
    // Error
    ROS_ERROR("data is None");
    return false;
  }
  if (dataBuffer.at(0) != 0x50)
  {
// Error
    ROS_ERROR("Head is not 0x50");
    return false;
  }

  if ((dataBuffer.at(49) *256 *256 + dataBuffer.at(50) *256 +dataBuffer.at(51) -1000000) *0.001 != 128)
  {
// Error
    ROS_ERROR("jy is not 128");
    return false;
  }

//Scale and store data
  sensorData.gX = (dataBuffer.at(1) *256 *256 + dataBuffer.at(2) *256 +dataBuffer.at(3) -1000000) *0.001;
  sensorData.gY = (dataBuffer.at(4) *256 *256 + dataBuffer.at(5) *256 +dataBuffer.at(6) -1000000) *0.001;
  sensorData.gZ = (dataBuffer.at(7) *256 *256 + dataBuffer.at(8) *256 +dataBuffer.at(9) -1000000) *0.001;

  sensorData.accX = (dataBuffer.at(10) *256 *256 + dataBuffer.at(11) *256 +dataBuffer.at(12) -1000000) *0.001 * 9.8;
  sensorData.accY = (dataBuffer.at(13) *256 *256 + dataBuffer.at(14) *256 +dataBuffer.at(15) -1000000) *0.001 * 9.8;
  sensorData.accZ = (dataBuffer.at(16) *256 *256 + dataBuffer.at(17) *256 +dataBuffer.at(18) -1000000) *0.001 * 9.8;

  sensorData.mX = (dataBuffer.at(19) *256 *256 + dataBuffer.at(20) *256 +dataBuffer.at(21) -1000000) *0.001;
  sensorData.mY = (dataBuffer.at(22) *256 *256 + dataBuffer.at(23) *256 +dataBuffer.at(24) -1000000) *0.001;
  sensorData.mZ = (dataBuffer.at(25) *256 *256 + dataBuffer.at(26) *256 +dataBuffer.at(27) -1000000) *0.001;

  sensorData.roll = -(dataBuffer.at(28) *256 *256 + dataBuffer.at(29) *256 +dataBuffer.at(30) -1000000) *0.001;
  sensorData.pitch = -(dataBuffer.at(31) *256 *256 + dataBuffer.at(32) *256 +dataBuffer.at(33) -1000000) *0.001;
  sensorData.yaw = -(dataBuffer.at(34) *256 *256 + dataBuffer.at(35) *256 +dataBuffer.at(36) -1000000) *0.001;

  sensorData.q1 = (dataBuffer.at(37) *256 *256 + dataBuffer.at(38) *256 +dataBuffer.at(39) -1000000) *0.001;
  sensorData.q2 = (dataBuffer.at(40) *256 *256 + dataBuffer.at(41) *256 +dataBuffer.at(42) -1000000) *0.001;
  sensorData.q3 = (dataBuffer.at(43) *256 *256 + dataBuffer.at(44) *256 +dataBuffer.at(45) -1000000) *0.001;
  sensorData.q4 = (dataBuffer.at(46) *256 *256 + dataBuffer.at(47) *256 +dataBuffer.at(48) -1000000) *0.001;
  // printf("555\n");

  return true;
}

//deg to rad
 double deg2rad(double deg)
{
    return deg * M_PI / 180.;
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "ky_imu");
  ros::NodeHandle nh;
  ros::NodeHandle private_nh("~");
  std::string imu_port="";
  int imu_port_baud=0;
  std::string imu_frame_id="";
  int imu_rate=0;

  private_nh.param<std::string>("imu_port",imu_port,"/dev/imu");
  private_nh.param<int>("imu_rate",imu_rate,100.);
  private_nh.param<int>("imu_port_baud",imu_port_baud,115200.);
  private_nh.param<std::string>("imu_frame_id",imu_frame_id,"imu");


//  double pre_yaw;
//  ros::Time pre_time;

  std::vector<double> imu_transform;
  try
  {
//    XmlRpc::XmlRpcValue v;
    std::vector<double> pos;
    if(private_nh.param("imu_transform", pos, pos))
    {
      for(uint8_t i=0;i<pos.size();++i)
      {
        imu_transform.push_back(pos.at(i));
      }
    }
  }
  catch (const std::out_of_range& e) {
      ROS_ERROR("%s",e.what());
    }
  ROS_INFO("open :%s succeed,imu rate:%d,imu_frame_id:%s",imu_port.c_str(),imu_rate,imu_frame_id.c_str());
  ros::Publisher imu_pub = nh.advertise<sensor_msgs::Imu>("imu", 50);
  tf2_ros::StaticTransformBroadcaster static_transform_broadcaster;
  ros::Rate r(imu_rate); // 100 hz

  SerialPort sp;
  sp.start(imu_port.c_str(),imu_port_baud);
  
  while(ros::ok())
  {

      std::vector<u_char> data;
      std::vector<u_char> buf;
      if(sp.get_data(&data))
      {
          
          if(data.at(0)==0x50&&data.at(52)==0x0d)//如果头是50 尾是0d,直接取53个数据
          {
            buf.assign(data.end()-53,data.end());//取第2帧数据
          }
          else {
              for(uint8_t i=1;i<106-53;++i)//第一个确定不是0x50
              {
                if(data.at(i)==0x50&&data.at(i+52)==0x0d)//:
                {
                    buf.assign(data.begin()+i,data.begin()+i+52);
                    break;//找到数据头,跳出循环
                }
              }
          }

          // 
          if(parse_data(buf))
          {
            geometry_msgs::TransformStamped trf;

            ros::Time stamp=ros::Time::now();
            trf.header.stamp=stamp;
            trf.header.frame_id="base_link";
            trf.child_frame_id=imu_frame_id;

            trf.transform.translation.x=imu_transform[0];
            trf.transform.translation.y=imu_transform[1];
            trf.transform.translation.z=imu_transform[2];

            tf2::Quaternion tf_q;
            tf_q.setRPY(imu_transform[3],imu_transform[4],imu_transform[5]);
            // tf_q.setRPY(deg2rad(sensorData.roll), deg2rad(sensorData.pitch), deg2rad(sensorData.yaw));
            // tf::Quaternion q= tf::createQuaternionFromRPY(0.0,0.0,yaw);//roll pitch yaw 转四元素
            // std::cout<<"roll: "<<sensorData.roll <<std::endl;
            // std::cout<<"pitch: "<<sensorData.pitch <<std::endl;
            // std::cout<<"yaw: "<<sensorData.yaw <<std::endl<<std::endl;
            trf.transform.rotation.x=tf_q.x();
            trf.transform.rotation.y=tf_q.y();
            trf.transform.rotation.z=tf_q.z();
            trf.transform.rotation.w=tf_q.w();
            static_transform_broadcaster.sendTransform(trf);//发布tf


            sensor_msgs::Imu imu;
            tf2::Quaternion imu_q;
            imu_q.setRPY(deg2rad(sensorData.roll), deg2rad(sensorData.pitch), deg2rad(sensorData.yaw));
            imu.orientation.x=imu_q.x();
            imu.orientation.y=imu_q.y();
            imu.orientation.z=imu_q.z();
            imu.orientation.w=imu_q.w();
            imu.header.stamp=stamp;
            imu.header.frame_id=imu_frame_id;
            imu.linear_acceleration.x=sensorData.accX;
            imu.linear_acceleration.y=sensorData.accY;
            imu.linear_acceleration.z=sensorData.accZ;
            imu.angular_velocity.x=sensorData.gX;
            imu.angular_velocity.y=sensorData.gY;
            imu.angular_velocity.z=sensorData.gZ;

//              imu.angular_velocity_covariance[0] = 0.02;
//              imu.angular_velocity_covariance[1] = 0;
//              imu.angular_velocity_covariance[2] = 0;
//              imu.angular_velocity_covariance[3] = 0;
//              imu.angular_velocity_covariance[4] = 0.02;
//              imu.angular_velocity_covariance[5] = 0;
//              imu.angular_velocity_covariance[6] = 0;
//              imu.angular_velocity_covariance[7] = 0;
//              imu.angular_velocity_covariance[8] = 0.02;


//              imu.linear_acceleration_covariance[0] = 0.04;
//              imu.linear_acceleration_covariance[1] = 0;
//              imu.linear_acceleration_covariance[2] = 0;
//              imu.linear_acceleration_covariance[3] = 0;
//              imu.linear_acceleration_covariance[4] = 0.04;
//              imu.linear_acceleration_covariance[5] = 0;
//              imu.linear_acceleration_covariance[6] = 0;
//              imu.linear_acceleration_covariance[7] = 0;
//              imu.linear_acceleration_covariance[8] = 0.04;


//              imu.orientation_covariance[0] = 0.025;
//              imu.orientation_covariance[1] = 0;
//              imu.orientation_covariance[2] = 0;
//              imu.orientation_covariance[3] = 0;
//              imu.orientation_covariance[4] = 0.025;
//              imu.orientation_covariance[5] = 0;
//              imu.orientation_covariance[6] = 0;
//              imu.orientation_covariance[7] = 0;
//              imu.orientation_covariance[8] = 0.025;

              imu_pub.publish(imu);
          }
          else
          {
//              sp.stop();
//              ROS_WARN("restart open serial port !!!");
//              ros::Duration(0.5).sleep();
//              sp.start(imu_port.c_str(),imu_port_baud);
          }

      }
    r.sleep();
    }
  sp.stop();
  return 0;
 
}

17位ky9250软件包(内有stm32\arduino\C#\Matlab\树莓\Unity3d\python\ROS\英飞凌\Nvidia jetson linux  访问例程)

2024年3月3日驱动和上位机
链接:https://pan.baidu.com/s/16zoUz5U4WCZIcFwD02ytgA 
提取码:abcd 
--来自百度网盘超级会员V5的分享

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值