|
@@ -0,0 +1,398 @@
|
|
|
+#include "ros/ros.h"
|
|
|
+
|
|
|
+
|
|
|
+#include <QMutex>
|
|
|
+#include <QSerialPort>
|
|
|
+
|
|
|
+#include <nav_msgs/Odometry.h>
|
|
|
+#include <geometry_msgs/PointStamped.h>
|
|
|
+#include <geometry_msgs/TwistStamped.h>
|
|
|
+#include <geometry_msgs/PoseStamped.h>
|
|
|
+
|
|
|
+#include <thread>
|
|
|
+
|
|
|
+#include "gnss_coordinate_convert.h"
|
|
|
+
|
|
|
+static std::string _point_topic = "/points_raw";
|
|
|
+static std::string _point_msgname = "lidar_pc";
|
|
|
+
|
|
|
+static std::string _image_topic = "/image_raw";
|
|
|
+static std::string _image_msgname = "picfront";
|
|
|
+
|
|
|
+static std::string _odom_topic = "/odom";
|
|
|
+static std::string _odom_msgname = "odom";
|
|
|
+
|
|
|
+static std::string _waypoints_topic = "/final_waypoints";
|
|
|
+static std::string _waypoints_msgname = "waypoints";
|
|
|
+
|
|
|
+static std::string _pose_topic = "/current_pose";
|
|
|
+static std::string _twist_topic = "/current_velocity";
|
|
|
+
|
|
|
+static std::string gstrserialportname = "/dev/ttyUSB0";
|
|
|
+
|
|
|
+ros::Publisher pose_pub;
|
|
|
+ros::Publisher twist_pub;
|
|
|
+
|
|
|
+static double glon0 = 117;
|
|
|
+static double glat0 = 39;
|
|
|
+static double ghead0 = 0;
|
|
|
+
|
|
|
+static bool _use_rtk_odom = true; //if use rtk , use_rtk_odom is true;
|
|
|
+static bool _use_pilot_waypoints = true; //if use pilot to calculate waypoints, this is true
|
|
|
+
|
|
|
+QString mstrHCP2;
|
|
|
+
|
|
|
+void SerialGPSDecodeSen(QString strsen);
|
|
|
+
|
|
|
+
|
|
|
+#include <cmath>
|
|
|
+
|
|
|
+struct Quaternion {
|
|
|
+ double w, x, y, z;
|
|
|
+};
|
|
|
+
|
|
|
+struct EulerAngles {
|
|
|
+ double roll, pitch, yaw;
|
|
|
+};
|
|
|
+
|
|
|
+EulerAngles ToEulerAngles(Quaternion q) {
|
|
|
+ EulerAngles angles;
|
|
|
+
|
|
|
+ // roll (x-axis rotation)
|
|
|
+ double sinr_cosp = 2 * (q.w * q.x + q.y * q.z);
|
|
|
+ double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y);
|
|
|
+ angles.roll = std::atan2(sinr_cosp, cosr_cosp);
|
|
|
+
|
|
|
+ // pitch (y-axis rotation)
|
|
|
+ double sinp = 2 * (q.w * q.y - q.z * q.x);
|
|
|
+ if (std::abs(sinp) >= 1)
|
|
|
+ angles.pitch = std::copysign(M_PI / 2, sinp); // use 90 degrees if out of range
|
|
|
+ else
|
|
|
+ angles.pitch = std::asin(sinp);
|
|
|
+
|
|
|
+ // yaw (z-axis rotation)
|
|
|
+ double siny_cosp = 2 * (q.w * q.z + q.x * q.y);
|
|
|
+ double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z);
|
|
|
+ angles.yaw = std::atan2(siny_cosp, cosy_cosp);
|
|
|
+
|
|
|
+ return angles;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+Quaternion ToQuaternion(double yaw, double pitch, double roll) // yaw (Z), pitch (Y), roll (X)
|
|
|
+{
|
|
|
+ // Abbreviations for the various angular functions
|
|
|
+ double cy = cos(yaw * 0.5);
|
|
|
+ double sy = sin(yaw * 0.5);
|
|
|
+ double cp = cos(pitch * 0.5);
|
|
|
+ double sp = sin(pitch * 0.5);
|
|
|
+ double cr = cos(roll * 0.5);
|
|
|
+ double sr = sin(roll * 0.5);
|
|
|
+
|
|
|
+ Quaternion q;
|
|
|
+ q.w = cy * cp * cr + sy * sp * sr;
|
|
|
+ q.x = cy * cp * sr - sy * sp * cr;
|
|
|
+ q.y = sy * cp * sr + cy * sp * cr;
|
|
|
+ q.z = sy * cp * cr - cy * sp * sr;
|
|
|
+
|
|
|
+ return q;
|
|
|
+}
|
|
|
+
|
|
|
+//原文链接:https://blog.csdn.net/xiaoma_bk/article/details/79082629
|
|
|
+
|
|
|
+
|
|
|
+static void SerialGPSDecode()
|
|
|
+{
|
|
|
+ int xpos = mstrHCP2.indexOf('\n');
|
|
|
+ if(xpos>0)
|
|
|
+ {
|
|
|
+
|
|
|
+ QString xsen = mstrHCP2.left(xpos+1);
|
|
|
+ SerialGPSDecodeSen(xsen);
|
|
|
+ mstrHCP2.remove(0,xpos+1);
|
|
|
+ SerialGPSDecode();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static bool checknmeasen(const char * strsen,const unsigned int nlen)
|
|
|
+{
|
|
|
+ if(nlen< 4)return false;
|
|
|
+
|
|
|
+ int i;
|
|
|
+ char check;
|
|
|
+ int nstarpos = -1;
|
|
|
+ check = strsen[1]^strsen[2];
|
|
|
+ for(i=3;i<nlen;i++)
|
|
|
+ {
|
|
|
+ if(strsen[i] == '*')
|
|
|
+ {
|
|
|
+ nstarpos = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ check = check^strsen[i];
|
|
|
+ }
|
|
|
+ if(nstarpos < 0)return false;
|
|
|
+ if(nstarpos >(nlen -3))return false;
|
|
|
+ char strcheck[3];
|
|
|
+ int ncheck = check;
|
|
|
+ snprintf(strcheck,3,"%02X",ncheck);
|
|
|
+ char strsencheck[3];
|
|
|
+ strsencheck[2] = 0;
|
|
|
+ strsencheck[0] = strsen[nstarpos + 1];
|
|
|
+ strsencheck[1] = strsen[nstarpos + 2];
|
|
|
+ if(strncmp(strcheck,strsencheck,2) == 0)
|
|
|
+ {
|
|
|
+ // qDebug(" r sen is %s",strsen);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+// qDebug(" sen is %s",strsen);
|
|
|
+ return false;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void SerialGPSDecodeSen(QString strsen)
|
|
|
+{
|
|
|
+ QStringList strlistrmc;
|
|
|
+ strlistrmc = strsen.split(",");
|
|
|
+
|
|
|
+ if(strlistrmc.size() < 23)return;
|
|
|
+ if(strlistrmc.at(0) != "$GPCHC")return;
|
|
|
+
|
|
|
+ if(!checknmeasen(strsen.toLatin1().data(),strsen.length()))
|
|
|
+ {
|
|
|
+ int nPos = strsen.indexOf('$',10);
|
|
|
+ if(nPos > 0)
|
|
|
+ {
|
|
|
+ QString strnewsen = strsen.right(strsen.size()-nPos);
|
|
|
+// qDebug("new sen is %s",strnewsen.toLatin1().data());
|
|
|
+ SerialGPSDecodeSen(strnewsen);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ double fheading,fLat,fLon,fVel,fPitch,fRoll;
|
|
|
+ double fHgt,gyro_x,gyro_y,gyro_z,acc_x,acc_y,acc_z;
|
|
|
+ int nsv1,nsv2;
|
|
|
+ int gpsweek,gpstime;
|
|
|
+ int insstate,rtkstate;
|
|
|
+ QString strx = strlistrmc.at(3);
|
|
|
+ fheading = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(1);
|
|
|
+ gpsweek = strx.toInt();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(2);
|
|
|
+ gpstime = strx.toInt();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(12);
|
|
|
+ fLat = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(13);
|
|
|
+ fLon = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(14);
|
|
|
+ fHgt = strx.toDouble();
|
|
|
+
|
|
|
+ double ve,vn,vu;
|
|
|
+ strx = strlistrmc.at(15);
|
|
|
+ ve = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(16);
|
|
|
+ vn = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(17);
|
|
|
+ vu = strx.toDouble();
|
|
|
+
|
|
|
+// fVel = sqrt(ve*ve + vn*vn + vu*vu);
|
|
|
+ strx = strlistrmc.at(18);
|
|
|
+ fVel = strx.toDouble();
|
|
|
+
|
|
|
+
|
|
|
+ strx = strlistrmc.at(4);
|
|
|
+ fPitch = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(5);
|
|
|
+ fRoll = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(6);
|
|
|
+ gyro_x = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(7);
|
|
|
+ gyro_y = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(8);
|
|
|
+ gyro_z = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(9);
|
|
|
+ acc_x = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(10);
|
|
|
+ acc_y = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(11);
|
|
|
+ acc_z = strx.toDouble();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(19);
|
|
|
+ nsv1 = strx.toInt();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(20);
|
|
|
+ nsv2 = strx.toInt();
|
|
|
+
|
|
|
+ strx = strlistrmc.at(21);
|
|
|
+ char strstate[3];
|
|
|
+ strstate[2] = 0;
|
|
|
+ if(strx.size() >= 2)
|
|
|
+ {
|
|
|
+
|
|
|
+ memcpy(strstate,strx.data(),2);
|
|
|
+ // qDebug(strstate);
|
|
|
+ char xstate;
|
|
|
+ xstate = strstate[0];
|
|
|
+ rtkstate = 4;
|
|
|
+ int xs;
|
|
|
+ if(xstate == '0')xs = 0;
|
|
|
+ if(xstate == '1')xs = 3;
|
|
|
+ if(xstate == '2')xs = 4;
|
|
|
+ if(xstate == '3')xs = 8;
|
|
|
+ if(xstate == '4')xs = 6;
|
|
|
+ if(xstate == '5')xs = 5;
|
|
|
+ if(xstate == '6')xs = 3;
|
|
|
+ if(xstate == '7')xs = 4;
|
|
|
+ if(xstate == '8')xs = 5;
|
|
|
+ if(xstate == '9')xs = 5;
|
|
|
+
|
|
|
+ rtkstate = xs;
|
|
|
+// if(mstate == 0)minsstate = 0;
|
|
|
+// else minsstate = 4;
|
|
|
+
|
|
|
+ xstate = strstate[1];
|
|
|
+ if(xstate == '0')insstate = 3;
|
|
|
+ else insstate = 4;
|
|
|
+ if(rtkstate == 0)insstate = 3;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ double x_o,y_o;
|
|
|
+ double x_now,y_now;
|
|
|
+ GaussProjCal(glon0,glat0,&x_o,&y_o);
|
|
|
+ GaussProjCal(fLon,fLat,&x_now,&y_now);
|
|
|
+ double rel_x = x_now - x_o;
|
|
|
+ double rel_y = y_now - y_o;
|
|
|
+ double rel_z = fHgt;
|
|
|
+
|
|
|
+ double pitch,roll,yaw;
|
|
|
+ pitch = fPitch * M_PI/180.0;
|
|
|
+ roll = fRoll * M_PI/180.0;
|
|
|
+ double hdg_o = (90 - ghead0)*M_PI/180.0;
|
|
|
+ yaw = (90 - fheading)*M_PI/180.0;// - hdg_o;
|
|
|
+ while(yaw< 0)yaw = yaw +2.0*M_PI;
|
|
|
+ while(yaw>=(2.0*M_PI))yaw = yaw - 2.0*M_PI;
|
|
|
+ Quaternion quat = ToQuaternion(yaw,pitch,roll);
|
|
|
+
|
|
|
+ nav_msgs::Odometry msg;
|
|
|
+
|
|
|
+ msg.pose.pose.position.x = rel_x;
|
|
|
+ msg.pose.pose.position.y = rel_y;
|
|
|
+ msg.pose.pose.position.z = rel_z;
|
|
|
+
|
|
|
+ msg.pose.pose.orientation.x = quat.x;
|
|
|
+ msg.pose.pose.orientation.y = quat.y;
|
|
|
+ msg.pose.pose.orientation.z = quat.z;
|
|
|
+ msg.pose.pose.orientation.w = quat.w;
|
|
|
+
|
|
|
+ msg.twist.twist.linear.x = sqrt(pow(vn,2)+pow(ve,2));
|
|
|
+
|
|
|
+ geometry_msgs::PoseStamped xPose;
|
|
|
+ xPose.pose = msg.pose.pose;
|
|
|
+ geometry_msgs::TwistStamped xtwist;
|
|
|
+ xtwist.twist = msg.twist.twist;
|
|
|
+
|
|
|
+ pose_pub.publish(xPose);
|
|
|
+ twist_pub.publish(xtwist);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void ThreadRecvRTK()
|
|
|
+{
|
|
|
+ QSerialPort *m_serialPort_GPS;
|
|
|
+ m_serialPort_GPS->setPortName(gstrserialportname.data());
|
|
|
+ m_serialPort_GPS->setBaudRate(230400);
|
|
|
+ m_serialPort_GPS->setParity(QSerialPort::NoParity);
|
|
|
+ m_serialPort_GPS->setDataBits(QSerialPort::Data8);
|
|
|
+ m_serialPort_GPS->setStopBits(QSerialPort::OneStop);
|
|
|
+ m_serialPort_GPS->setFlowControl(QSerialPort::NoFlowControl);
|
|
|
+ m_serialPort_GPS->setReadBufferSize(0);
|
|
|
+
|
|
|
+ bool bSerialPortOpen = false;
|
|
|
+ if(m_serialPort_GPS->open(QSerialPort::ReadWrite))
|
|
|
+ {
|
|
|
+ bSerialPortOpen = true;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ std::cout<<" Open Port "<<gstrserialportname<<" Fail."<<std::endl;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ while(bSerialPortOpen)
|
|
|
+ {
|
|
|
+ QByteArray ba = m_serialPort_GPS->readAll();
|
|
|
+
|
|
|
+ if(ba.length() > 0)
|
|
|
+ {
|
|
|
+ mstrHCP2.append(ba);
|
|
|
+ SerialGPSDecode();
|
|
|
+ // mnNotRecvCount = 0;
|
|
|
+ //Decode
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+int main(int argc, char *argv[])
|
|
|
+{
|
|
|
+ ros::init(argc, argv, "pilottoros");
|
|
|
+// ros::NodeHandle n;
|
|
|
+ ros::NodeHandle private_nh("~");
|
|
|
+ ros::Rate loop_rate(1);
|
|
|
+
|
|
|
+
|
|
|
+ private_nh.getParam("points_node",_point_topic);
|
|
|
+ private_nh.getParam("points_msgname",_point_msgname);
|
|
|
+ std::cout<<"_point_topic is "<<_point_topic<<std::endl;
|
|
|
+ std::cout<<"_point_msgname : "<<_point_msgname<<std::endl;
|
|
|
+
|
|
|
+ private_nh.getParam("image_node",_image_topic);
|
|
|
+ private_nh.getParam("image_msgname",_image_msgname);
|
|
|
+ std::cout<<"_image_topic is "<<_image_topic<<std::endl;
|
|
|
+ std::cout<<"_image_msgname : "<<_image_msgname<<std::endl;
|
|
|
+
|
|
|
+ private_nh.getParam("waypoints_node",_waypoints_topic);
|
|
|
+ private_nh.getParam("waypoints_msgname",_waypoints_msgname);
|
|
|
+ std::cout<<"_waypoints_topic is "<<_waypoints_topic<<std::endl;
|
|
|
+ std::cout<<"_waypoints_msgname : "<<_waypoints_msgname<<std::endl;
|
|
|
+
|
|
|
+ private_nh.getParam("use_rtk_odom",_use_rtk_odom);
|
|
|
+ private_nh.getParam("use_pilot_waypoints",_use_pilot_waypoints);
|
|
|
+
|
|
|
+
|
|
|
+ pose_pub = private_nh.advertise<geometry_msgs::PoseStamped>(_pose_topic,10);
|
|
|
+ twist_pub = private_nh.advertise<geometry_msgs::TwistStamped>(_twist_topic,10);
|
|
|
+
|
|
|
+
|
|
|
+std::thread * pthread = new std::thread(ThreadRecvRTK);
|
|
|
+
|
|
|
+
|
|
|
+ros::spin();
|
|
|
+
|
|
|
+}
|