纯跟踪算法可借鉴开发

					```cpp

#include “pathcontrol.h”

using namespace std;

enum StateMachSts_st
{
SM_OFF,
SM_STANDBY,
SM_HANDSHAKE,
SM_ACTIVE,
SM_BRAKE,
SM_COMPLETE,
} sm_state;

int TargetInd;
float Car_current_velicity;
bool active;
int mini_index;
float Lp = 2.7;
float pursuit_K = 0.1;
float pursuit_Lfc = 2;

PathController::PathController() : ImuGpsSize_(3)
{
}

PathController::~PathController()
{
}

// vector ref_path_points;
// vector clean_path_points;
// vector cartesian_path_points;
// queue car_current_XY;
// vector Indx;

void PathController::ReadRefpathGPS_lon_lat_alat()
{
int index;
ifstream inFile(FILE_PATH, ios::in);
if (!inFile)
{
cout << “打开文件失败” << endl;
exit(1);
}

string line;

while (getline(inFile, line)) //getline(inFile, line)表示按行读取CSV文件中的数据
{
    string field;
    istringstream sin(line); //将整行字符串line读入到字符串流sin中
    ImuGpsData tmp = {0};

    getline(sin, field, ','); //将字符串流sin中的字符读入到field字符串中,以逗号为分隔符
    tmp.ImuGpsLat = atof(field.c_str());
    // refpath_Gps_latitude[index] = temp1; //纬度
    // refpath_lat.push_back(temp1);

    getline(sin, field, ','); //将字符串流sin中的字符读入到field字符串中,以逗号为分隔符
    tmp.ImuGpsLon = atof(field.c_str());
    // refpath_Gps_longitude[index] = temp2; //经度
    // refpath_lon.push_back(temp2);

    getline(sin, field, ','); //将字符串流sin中的字符读入到field字符串中,以逗号为分隔符
    tmp.ImuGpsAlat = atof(field.c_str());
    // refpath_Gps_altitude[index] = temp3; //高度
    // refpath_alat.push_back(temp3);
    ref_path_points.push_back(tmp);

    index++;
}

inFile.close();

}

void PathController::CleanrefpathGpsPoint_lon_lat_alat()
{
ImuGpsData clean_temp;
bool flag(false);
Indx.push_back(0);
for (int i = 0; i < ref_path_points.size() && !flag;)
{
for (int j = i + 1; j < ref_path_points.size(); ++j)
{
if (j == ref_path_points.size() - 1)
flag = true;
float dist = abs(sqrt(pow(10000000 * ref_path_points[i].ImuGpsLon - 10000000 * ref_path_points[j].ImuGpsLon, 2) + pow(10000000 * ref_path_points[i].ImuGpsLat - 10000000 * ref_path_points[j].ImuGpsLat, 2)));
if (dist >= 0.000000000001)
{
i = j;
Indx.push_back(i);
}
}
}

for (int k = 0; k < Indx.size() - 1; ++k)
{
    clean_temp.ImuGpsLon = (ref_path_points[Indx[k]].ImuGpsLon);
    clean_temp.ImuGpsLat = (ref_path_points[Indx[k]].ImuGpsLat);
    clean_temp.ImuGpsAlat = (ref_path_points[Indx[k]].ImuGpsAlat);
    clean_path_points.push_back(clean_temp);
}

}

std::vector PathController::RefpathGps2Cal_RefpathXY()
{
CartesianXYPoint cal_tempxy;
float wgs84a = 6378.137;
float wgs84f = 1.0 / 298.257223563;
float wgs84b = wgs84a * (1.0 - wgs84f);
float eccsq = 1 - (wgs84b * wgs84b) / (wgs84a * wgs84a);
float dtr = M_PI / 180.0;
for (int IND = 0; IND < clean_path_points.size() - 1; ++IND)
{
float clat = cos(dtr * clean_path_points[IND].ImuGpsLat);
float clon = cos(dtr * clean_path_points[IND].ImuGpsLon);
float slat = sin(dtr * clean_path_points[IND].ImuGpsLat);
float slon = sin(dtr * clean_path_points[IND].ImuGpsLon);
float dsq = 1.0 - eccsq * slat * slat;
float d = sqrt(dsq);
float rn = wgs84a / d;
float Cal_RefpathX = (rn + clean_path_points[IND].ImuGpsAlat) * clat * clon;
float Cal_RefpathY = (rn + clean_path_points[IND].ImuGpsAlat) * clat * slon;
cal_tempxy.cartesian_X = (Cal_RefpathX);
cal_tempxy.cartesian_Y = (Cal_RefpathY);
cartesian_path_points.push_back(cal_tempxy);
}
return cartesian_path_points;
}

CartesianXYPoint PathController::getCarCurPt()
{
float wgs84a = 6378.137;
float wgs84f = 1.0 / 298.257223563;
float wgs84b = wgs84a * (1.0 - wgs84f);
float eccsq = 1 - (wgs84b * wgs84b) / (wgs84a * wgs84a);
float dtr = M_PI / 180.0;

float clat1 = cos(dtr * car_current_imu_gps_data.ImuGpsLat);
float clon1 = cos(dtr * car_current_imu_gps_data.ImuGpsLon);
float slat1 = sin(dtr * car_current_imu_gps_data.ImuGpsLat);
float slon1 = sin(dtr * car_current_imu_gps_data.ImuGpsLon);
float dsq1 = 1.0 - eccsq * slat1 * slat1;
float d1 = sqrt(dsq1);
float rn1 = wgs84a / d1;
float Car_X1 = (rn1 + car_current_imu_gps_data.ImuGpsAlat) * clat1 * clon1;
float Car_Y1 = (rn1 + car_current_imu_gps_data.ImuGpsAlat) * clat1 * slon1;
return CartesianXYPoint(Car_X1, Car_Y1);

}

std::vector PathController::CarGps2Cal_CarXY()
{
if (car_current_XY.size() == ImuGpsSize_)
{
car_current_XY.pop();
}

while (car_current_XY.size() < ImuGpsSize_) // ImuGpsSize_ == 2
{
    CartesianXYPoint car_current_point = getCarCurPt();
    car_current_XY.push(car_current_point);
}

std::vector<CartesianXYPoint> pts = {car_current_XY.front(), car_current_XY.back()};
//pts[0].cartesian_X;
return pts;
cout << "pts[0].cartesian_X" << pts[0].cartesian_X << "---"
     << "pts[0].cartesian_X" << pts[0].cartesian_Y << endl;
cout << "pts[1].cartesian_X" << pts[1].cartesian_X << "---"
     << "pts[1].cartesian_X" << pts[1].cartesian_Y << endl;

}

int PathController::calc_pursuit_index(CartesianXYPoint car_current_cartisian_point, std::vector &cartesian_path_points) //计算最短路径。
{

int pursuit_index;
float min = abs(sqrt(pow(car_current_cartisian_point.cartesian_X - cartesian_path_points[0].cartesian_X, 2) + pow(car_current_cartisian_point.cartesian_Y - cartesian_path_points[0].cartesian_Y, 2)));
for (int j = 0; j < cartesian_path_points.size(); j++)
{
    float d = abs(sqrt(pow(car_current_cartisian_point.cartesian_X - cartesian_path_points[j].cartesian_X, 2) + pow(car_current_cartisian_point.cartesian_Y - cartesian_path_points[j].cartesian_Y, 2)));
    if (d < min)
    {
        min = d;
        pursuit_index = j;
    }
}
float L = 0.0;
float Lf = pursuit_K * Car_current_velicity + 1.0;
while (Lf > L && (pursuit_index + 1) < cartesian_path_points.size())
{
    float dx = cartesian_path_points[pursuit_index + 1].cartesian_X - cartesian_path_points[pursuit_index].cartesian_X;
    float dy = cartesian_path_points[pursuit_index + 1].cartesian_Y - cartesian_path_points[pursuit_index].cartesian_Y;
    L += sqrt(pow(dx, 2) + pow(dy, 2));
    pursuit_index += 1;
}
return pursuit_index;
cout << "pursuit_index" << pursuit_index << endl;

}

Result PathController::pure_pursuit_control(std::vector &pts, std::vector &cartesian_path_points, int pind)
{
Result ret;
float tx;
float ty;

if (pind < cartesian_path_points.size())
{
    tx = cartesian_path_points[pind].cartesian_X;
    ty = cartesian_path_points[pind].cartesian_Y;
}
else
{
    tx = cartesian_path_points[cartesian_path_points.size() - 1].cartesian_X; //倒数第一个点
    ty = cartesian_path_points[cartesian_path_points.size() - 1].cartesian_Y;
    pind = cartesian_path_points.size() - 1; //最后一个点的索引
}
float pi = 3.14;

float refx_car0x = (cartesian_path_points[pind].cartesian_X-pts[0].cartesian_X );
float refy_car0y = (cartesian_path_points[pind].cartesian_Y-pts[0].cartesian_Y);
float car1x_car0x = (pts[1].cartesian_X - pts[0].cartesian_X) + 0.01;
float car1y_car0y = (pts[1].cartesian_Y - pts[0].cartesian_Y) + 0.1;
//float alpha1 = abs(refx_car0x * car1y_car0y) + abs(refy_car0y * car1x_car0x);
float alpha1 = (refx_car0x * car1x_car0x) + (refy_car0y * car1y_car0y);

float alpha2 = sqrt(pow(refx_car0x, 2) + pow(refy_car0y, 2)) * sqrt(pow(car1x_car0x, 2) + pow(car1y_car0y, 2));
float salpha = alpha1 / alpha2;
if (salpha < -1 && salpha > -2)
{
    salpha = -1;
}
else if (salpha > 1 && salpha < 2)
{
    salpha = 1;
}
float angle = acos(salpha) * 180 / M_PI;

cout << "refx_car0x" << refx_car0x << "refy_car0y" << refy_car0y << "car1x_car0x " << car1x_car0x << "car1y_car0y" << car1y_car0y << endl;
cout << "pts[0].cartesian_X" << pts[0].cartesian_X << "pts[0].cartesian_Y" << pts[0].cartesian_Y << "pts[1].cartesian_X" << pts[1].cartesian_X << "pts[1].cartesian_Y" << pts[1].cartesian_Y << endl;
cout << "cartesian_path_points[pind].cartesian_X" << cartesian_path_points[pind].cartesian_X << "cartesian_path_points[pind].cartesian_Y" << cartesian_path_points[pind].cartesian_Y << endl;
float Lf = pursuit_K * Car_current_velicity + pursuit_Lfc;
//float pursuit_alpha = atan2(cartesian_path_points[pursuit_ind].cartesian_Y - car_current_cartisian_point.cartesian_Y, cartesian_path_points[pursuit_ind].cartesian_X - car_current_cartisian_point.cartesian_X) - CarCurrentSteerAngle - 90;
//float pursuit_delta = atan2(2.0 * Lp * sin(pursuit_alpha) / Lf, 1.0);
float delta = atan(2.0 * Lp * sin(angle) / Lf)* 180 / M_PI;

// float delta = (atan2(2.0 * Lp * sin(alpha) / Lf, 1.0)) * 16;

ret.delta = delta;
ret.ind = pind;
return ret; //返回角度和最近点的索引。
cout << "ret" << ret.delta << "###" << ret.ind << endl;

}

float PathController::Velicity_control()
{

if (Car_current_velicity < 2)
{
    target_acc = 0.25;
}
else if (Car_current_velicity > 5)
{
    target_acc = -0.25;
}
else
{
    target_acc = 0;
}

return target_acc;

}

//激活条件
// bool PathController::Automobile_Active()
// {
// int active;

// int pursuit_MinDistance_ind = 0;
// float min = abs(sqrt(pow(car_current_cartisian_point.cartesian_X - cartesian_path_points[0].cartesian_X, 2) + pow(car_current_cartisian_point.cartesian_Y - cartesian_path_points[0].cartesian_Y, 2)));
// for (int j = 0; j < cartesian_path_points.size(); j++)
// {
// float d = abs(sqrt(pow(car_current_cartisian_point.cartesian_X - cartesian_path_points[j].cartesian_X, 2) + pow(car_current_cartisian_point.cartesian_Y - cartesian_path_points[j].cartesian_Y, 2)));
// if (d < min)
// {
// min = d;
// pursuit_MinDistance_ind = j;
// }
// }

// float Min_X_Distance = (cartesian_path_points[pursuit_MinDistance_ind].cartesian_X - car_current_cartisian_point.cartesian_X); //x方向的距离 - 车辆x方向的距离
// float Min_Y_Distance = (cartesian_path_points[pursuit_MinDistance_ind].cartesian_Y - car_current_cartisian_point.cartesian_Y);
// float Min_D_Distance = abs(sqrt(Min_X_Distance * Min_X_Distance + Min_Y_Distance * Min_Y_Distance));
// //
// float pursuit_Lf = (pursuit_K * Car_current_velicity + pursuit_Lfc);

// if (pursuit_Lf > Min_D_Distance)
// {
// active = 1;
// }
// else
// {
// active = 0;
// }
// return active;
// }

void PathController::statemachine_task()
{
// TODO: convert current car gps latitude longitude to S-L points.
// CartesianXYPoint car_current_cartisian_point;
// vector pts;

car_current_cartisian_point = PathController::getCarCurPt();

pts = PathController::CarGps2Cal_CarXY();

switch (sm_state)
{
case SM_OFF:
    PathController::ReadRefpathGPS_lon_lat_alat();
    PathController::CleanrefpathGpsPoint_lon_lat_alat();
    cartesian_path_points = PathController::RefpathGps2Cal_RefpathXY();

    if (cartesian_path_points.size() != 0) // TODO: 1. read reference path and convert to s-l , return finishend.
    {
        sm_state = SM_STANDBY;
    }
    chassis_ctr_handshake_req = false;
    break;

case SM_STANDBY:

    // TODO: 2 . if funtion on condition is reached.

    // active = Automobile_Active();
    active = 1;

    if (active == true && current_gear == GEAR_P)
    {
        sm_state = SM_HANDSHAKE;
    }

    chassis_ctr_handshake_req = false;
    break;
case SM_HANDSHAKE:
    // TODO: 3. if eps controlled is OK
    if (chassis_be_controlled == true)
    {
        sm_state = SM_ACTIVE;
    }
    chassis_ctr_handshake_req = true;
    break;
case SM_ACTIVE:
    TargetInd = PathController::calc_pursuit_index(car_current_cartisian_point, cartesian_path_points);
    // TODO:  4 mini obstacle length < 10 meter
    if (dist_mini_obstacle < 4)
    {
        sm_state = SM_BRAKE;
    }

    else if (TargetInd == cartesian_path_points.size() - 1) // TODO 5 reach the reference path end
    {
        sm_state = SM_COMPLETE;
    }
    else
    {
        //TODO : SM active actions: calculate the output parameters
        Result ret;
        ret = PathController::pure_pursuit_control(pts, cartesian_path_points, TargetInd);
        target_steer_ang = ret.delta;
        int p_ind = ret.ind;
        target_acc = PathController::Velicity_control();
        // then output
        chassis_ctr_handshake_req = true;
        target_gear = GEAR_D;
        cout << " p_ind" << p_ind << endl;
    }
    break;
case SM_BRAKE:
    if (dist_mini_obstacle > 6)
    {
        sm_state = SM_ACTIVE;
    }
    else
    {
        chassis_ctr_handshake_req = true;
        target_acc = -0.5;
    }
    break;
case SM_COMPLETE:
    if (current_gear == GEAR_P)
    {
        // jump to off, wait for next function on .
        sm_state = SM_OFF;
    }
    else
    {
        chassis_ctr_handshake_req = true;
        target_acc = -0.5;
        if (Car_current_velicity <= 0.2)
        {
            target_gear = GEAR_P;
        }
    }
    break;
default:
    break;
}
//printf("SM state: %d, steer angle: %f \n", sm_state, target_steer_ang);
printf("SM state: %d, arget_steer_ang: %f, cam_distance: %f \n", sm_state, target_steer_ang, dist_mini_obstacle);

}


```cpp
#ifndef PLANING_CONTROL_H
#define PLANING_CONTROL_H

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <queue>

#define FILE_PATH "/home/titan/Bo.csv"

struct CartesianXYPoint
{
    float cartesian_X;
    float cartesian_Y;
    CartesianXYPoint() : cartesian_X(0.0f), cartesian_Y(0.0f)
    {
    }

    CartesianXYPoint(const float _x, const float _y)
        : cartesian_X(_x), cartesian_Y(_y)
    {
    }

    CartesianXYPoint &operator=(const CartesianXYPoint &obj)
    {
        this->cartesian_X = obj.cartesian_X;
        this->cartesian_Y = obj.cartesian_Y;
        return *this;
    }
};

struct ImuGpsData
{
    float ImuGpsLon;
    float ImuGpsLat;
    float ImuGpsAlat;
};

enum Gear
{
    GEAR_NONE = 0,
    GEAR_P = 1,
    GEAR_R = 2,
    GEAR_N = 3,
    GEAR_D = 4,

};

struct Result
{
    double delta;
    int ind;
};

class PathController
{

public:
    PathController();
    ~PathController();

public:
    void statemachine_task();

public:
    // input parameters:--------------------------------------------------如何给直接给
    float Car_current_velicity; // uinit: m/s^2
    float dist_mini_obstacle;   // uinit: m
    ImuGpsData car_current_imu_gps_data;
    float CarCurrentSteerAngle;
    bool chassis_be_controlled;
    enum Gear current_gear;

    // output
    enum Gear target_gear;
    float target_acc;       //uinit: m/s^2
    float target_steer_ang; // unit: degree -540 ~ +540
    bool chassis_ctr_handshake_req;

private:
    void ReadRefpathGPS_lon_lat_alat();
    void CleanrefpathGpsPoint_lon_lat_alat();
    std::vector<CartesianXYPoint> RefpathGps2Cal_RefpathXY();
    std::vector<CartesianXYPoint> CarGps2Cal_CarXY();
    CartesianXYPoint getCarCurPt();
    int calc_pursuit_index(CartesianXYPoint car_current_cartisian_point, std::vector<CartesianXYPoint> &cartesian_path_points); //计算最短路径。
    Result pure_pursuit_control(std::vector<CartesianXYPoint> &pts, std::vector<CartesianXYPoint> &cartesian_path_points, int pind);
    // bool Automobile_Active();
    float Velicity_control();

private:
    int ImuGpsSize_;
    std::vector<ImuGpsData> ref_path_points;
    std::vector<ImuGpsData> clean_path_points;
    std::vector<int> Indx;
    std::vector<CartesianXYPoint> cartesian_path_points;
    std::queue<CartesianXYPoint> car_current_XY;
    std::vector<CartesianXYPoint> pts;

    CartesianXYPoint car_current_cartisian_point;
    CartesianXYPoint last_car_current_cartisian_point;
};

#endif
#include "pathcontrol.h"

using namespace std;

int TargetInd;
float Car_current_velicity;
bool active;
int mini_index;

PathController::PathController() : ImuGpsSize_(2)
{
    // CartesianXYPoint p0(0.1, 0.2);
    // CartesianXYPoint p1(0.19, 0.29);
    // p0 = p1;
    // CartesianXYPoint p2 = p0 - p1;

    // ImuGpsData imu1 = {0.1, 0.2, 0.3};
    // ImuGpsData imu2 = imu1;
    // imu1.ImuGpsAlat = 0;
    // ImuGpsData imu3 = imu2 - imu1;

    read_ref_path_gps();
    cleanRefPathGpsData();
    refPathGps2XY();
}

PathController::~PathController()
{
}

void PathController::read_ref_path_gps()
{
    ifstream inFile(FILE_PATH, ios::in);
    if (!inFile)
    {
        cout << "打开文件失败" << endl;
        exit(1);
    }

    string line;
    ref_path_points.clear();
    while (getline(inFile, line)) //getline(inFile, line)表示按行读取CSV文件中的数据
    {
        string field;
        istringstream sin(line); //将整行字符串line读入到字符串流sin中
        ImuGpsData tmp = {0};

        getline(sin, field, ','); //将字符串流sin中的字符读入到field字符串中,以逗号为分隔符
        tmp.ImuGpsLat = atof(field.c_str());

        getline(sin, field, ','); //将字符串流sin中的字符读入到field字符串中,以逗号为分隔符
        tmp.ImuGpsLon = atof(field.c_str());

        getline(sin, field, ','); //将字符串流sin中的字符读入到field字符串中,以逗号为分隔符
        tmp.ImuGpsAlat = atof(field.c_str());

        ref_path_points.push_back(tmp);
    }

    inFile.close();
}

void PathController::cleanRefPathGpsData()
{
    bool flag(false);
    Index.clear();
    Index.push_back(0);
    for (int i = 0; i < ref_path_points.size() && !flag;)
    {
        for (int j = i + 1; j < ref_path_points.size(); ++j)
        {
            if (j == ref_path_points.size() - 1)
                flag = true;
            float dist = abs(sqrt(pow(10000000 * ref_path_points[i].ImuGpsLon - 10000000 * ref_path_points[j].ImuGpsLon, 2) + pow(10000000 * ref_path_points[i].ImuGpsLat - 10000000 * ref_path_points[j].ImuGpsLat, 2)));
            if (dist > 0)
            {
                i = j;
                Index.push_back(i);
            }
        }
    }

    clean_path_points.clear();
    for (int k = 0; k < Index.size(); ++k)
    {
        ImuGpsData clean_temp;
        clean_temp = ref_path_points[Index[k]];
        clean_path_points.push_back(clean_temp);
    }
}

// void PathController::refPathGps2XY()
// {
//     cartesian_path_points.clear();
//     CartesianXYPoint cal_tempxy;
//     double wgs84a = 6378.137;
//     double wgs84f = 1.0 / 298.257223563;
//     double wgs84b = wgs84a * (1.0 - wgs84f);
//     double eccsq = 1 - (wgs84b * wgs84b) / (wgs84a * wgs84a);
//     double dtr = M_PI / 180.0;
//     for (int IND = 0; IND < clean_path_points.size(); ++IND)
//     {
//         double clat = cos(dtr * clean_path_points[IND].ImuGpsLat);
//         double clon = cos(dtr * clean_path_points[IND].ImuGpsLon);
//         double slat = sin(dtr * clean_path_points[IND].ImuGpsLat);
//         double slon = sin(dtr * clean_path_points[IND].ImuGpsLon);
//         double dsq = 1.0 - eccsq * slat * slat;
//         double d = sqrt(dsq);
//         double rn = wgs84a / d;
//         double Cal_RefpathX = (rn + 7.5) * clat * clon;
//         double Cal_RefpathY = (rn + 7.5) * clat * slon;
//         cal_tempxy.cartesian_X = (Cal_RefpathX);
//         cal_tempxy.cartesian_Y = (Cal_RefpathY);
//         cartesian_path_points.push_back(cal_tempxy);
//     }
// }

void PathController::refPathGps2XY()
{
    cartesian_path_points.clear();
    CartesianXYPoint cal_tempxy;

    for (int IND = 0; IND < clean_path_points.size(); ++IND)
    {
        cal_tempxy = ConvertGPS2XY(clean_path_points[IND]);

        cartesian_path_points.push_back(cal_tempxy);
    }
}

void PathController::CalculateCarCurrentCartesianXYPt()
{
    double wgs84a = 6378.137;
    double wgs84f = 1.0 / 298.257223563;
    double wgs84b = wgs84a * (1.0 - wgs84f);
    double eccsq = 1 - (wgs84b * wgs84b) / (wgs84a * wgs84a);
    double dtr = M_PI / 180.0;

    double clat1 = cos(dtr * car_current_imu_gps_data.ImuGpsLat);
    double clon1 = cos(dtr * car_current_imu_gps_data.ImuGpsLon);
    double slat1 = sin(dtr * car_current_imu_gps_data.ImuGpsLat);
    double slon1 = sin(dtr * car_current_imu_gps_data.ImuGpsLon);
    double dsq1 = 1.0 - eccsq * slat1 * slat1;
    double d1 = sqrt(dsq1);
    double rn1 = wgs84a / d1;
    double Car_X1 = (rn1 + 7.5) * clat1 * clon1;
    double Car_Y1 = (rn1 + 7.5) * clat1 * slon1;
    car_current_cartisian_point.cartesian_X = Car_X1;
    car_current_cartisian_point.cartesian_Y = Car_Y1;
}

CartesianXYPoint PathController::ConvertGPS2XY(ImuGpsData gps_data)
{
    CartesianXYPoint res;

    double wgs84a = 6378.137;
    double wgs84f = 1.0 / 298.257223563;
    double wgs84b = wgs84a * (1.0 - wgs84f);
    double eccsq = 1 - (wgs84b * wgs84b) / (wgs84a * wgs84a);
    double dtr = M_PI / 180.0;

    double clat = cos(dtr * gps_data.ImuGpsLat);
    double clon = cos(dtr * gps_data.ImuGpsLon);
    double slat = sin(dtr * gps_data.ImuGpsLat);
    double slon = sin(dtr * gps_data.ImuGpsLon);
    double dsq = 1.0 - eccsq * slat * slat;
    double d = sqrt(dsq);
    double rn = wgs84a / d;
    double Car_X = (rn + 7.5) * clat * clon;
    double Car_Y = (rn + 7.5) * clat * slon;

    // convert the calculated result unit:1km to 1m
    res.cartesian_X = Car_X * 1000;
    res.cartesian_Y = Car_Y * 1000;

    return res;
}

void PathController::CarGps2Cal_CarXY()
{
    if (car_history_XY.size() == 0)
    {
        car_history_XY.push(car_current_cartisian_point);
    }
    else
    {
        float dx = car_current_cartisian_point.cartesian_X - car_history_XY.back().cartesian_X;
        float dy = car_current_cartisian_point.cartesian_Y - car_history_XY.back().cartesian_Y;
        float diff_len = sqrt(pow(dx, 2) + pow(dy, 2));
        if (diff_len > 0.2) // if move more than 20cm
        {
            if (car_history_XY.size() < ImuGpsSize_)
            {
                car_history_XY.push(car_current_cartisian_point);
            }
            else
            {
                car_history_XY.pop();
                car_history_XY.push(car_current_cartisian_point);
            }
        }
    }
}

int PathController::calc_pursuit_index() //计算最短路径。
{

    int pursuit_index = 0;
    float min = abs(sqrt(pow(car_current_cartisian_point.cartesian_X - cartesian_path_points[0].cartesian_X, 2) + pow(car_current_cartisian_point.cartesian_Y - cartesian_path_points[0].cartesian_Y, 2)));
    for (int j = 0; j < cartesian_path_points.size(); j++)
    {
        float d = abs(sqrt(pow(car_current_cartisian_point.cartesian_X - cartesian_path_points[j].cartesian_X, 2) + pow(car_current_cartisian_point.cartesian_Y - cartesian_path_points[j].cartesian_Y, 2)));
        if (d < min)
        {
            min = d;
            pursuit_index = j;
        }
    }

    float L = 0.0;
    float Lf = PURSUIT_K * Car_current_velicity + PURSUIT_LFC;
    while (Lf > L && (pursuit_index + 1) < cartesian_path_points.size())
    {
        float dx = cartesian_path_points[pursuit_index + 1].cartesian_X - cartesian_path_points[pursuit_index].cartesian_X;
        float dy = cartesian_path_points[pursuit_index + 1].cartesian_Y - cartesian_path_points[pursuit_index].cartesian_Y;
        L += sqrt(pow(dx, 2) + pow(dy, 2));
        pursuit_index += 1;
    }

    cout << "pursuit_index " << pursuit_index << endl;
    return pursuit_index;
}

Result PathController::pure_pursuit_control(const int pind)
{
    float tx;
    float ty;
    int _pind = pind;
    if (_pind < cartesian_path_points.size())
    {
        tx = cartesian_path_points[_pind].cartesian_X;
        ty = cartesian_path_points[_pind].cartesian_Y;
    }
    else
    {
        tx = cartesian_path_points[cartesian_path_points.size() - 1].cartesian_X; //倒数第一个点
        ty = cartesian_path_points[cartesian_path_points.size() - 1].cartesian_Y;
        _pind = cartesian_path_points.size() - 1; //最后一个点的索引
    }
    float delta = 0;

    // if(car_history_XY.size() == ImuGpsSize_)
    // {
    //     float refx_car0x = (tx - car_history_XY.front().cartesian_X);
    //     float refy_car0y = (ty - car_history_XY.front().cartesian_Y);
    //     float car1x_car0x = (car_history_XY.back().cartesian_X - car_history_XY.front().cartesian_X);
    //     float car1y_car0y = (car_history_XY.back().cartesian_Y - car_history_XY.front().cartesian_Y);
    //     float alpha1 = (refx_car0x * car1x_car0x) + (refy_car0y * car1y_car0y);
    //     float alpha2 = sqrt(pow(refx_car0x, 2) + pow(refy_car0y, 2)) * sqrt(pow(car1x_car0x, 2) + pow(car1y_car0y, 2));
    //     float salpha = alpha1 / alpha2;

    //     if (salpha < -1)
    //     {
    //         salpha = -1;
    //     }
    //     else if (salpha > 1)
    //     {
    //         salpha = 1;
    //     }

    // double sinQ = sqrt(1-salpha*salpha);

    int delta1 = (360 - CarCurrentSteerAngle);
    int YAW = delta1 % 360;

    float H = (90.0f - YAW)float Lf = PURSUIT_K * Car_current_velicity + PURSUIT_LFC;
    float refx_car0x = (tx - car_current_cartisian_point.cartesian_X);
    float refy_car0y = (ty - car_current_cartisian_point.cartesian_Y);
    float slope = atan2(refy_car0y, refx_car0x)*180.0f/M_PI;
    float alpha = slope - H;
    delta = alpha * 180.0f / M_PI * 16.25f;
    // float Dir = alpha * 180 / M_PI * 16.25;

    //delta = atan((2.0 * VEHICLE_LENGTH * sin(alpha)) / Lf) * 180 / M_PI;

    //     if(delta > 30)
    //     {
    //         delta = 30;
    //     }
    //     else if (delta < -30)
    //     {
    //         delta = -30;
    //     }
    //     else
    //     {

    //     }

    //     delta *= 16;
    // }
    // else
    // {
    //     delta = CarCurrentSteerAngle;
    // }

    Result ret;
    ret.delta = delta;
    ret.ind = _pind;
    cout << "cartesian_path_points[_pind].cartesian_X" << cartesian_path_points[_pind].cartesian_X << " cartesian_path_points[_pind].cartesian_Y" << cartesian_path_points[_pind].cartesian_Y << endl;
    cout << "car_current_cartisian_point.cartesian_X" << car_current_cartisian_point.cartesian_X << " car_current_cartisian_point.cartesian_Y" << car_current_cartisian_point.cartesian_Y << endl;
    cout << "ret:" << ret.delta << " ret.ind" << ret.ind << endl;
    return ret; //返回角度和最近点的索引。
}

void PathController::Velocity_control()
{

    if (Car_current_velicity < 5)
    {
        target_acc = 0.25;
    }
    else if (Car_current_velicity > 7)
    {
        target_acc = -0.25;
    }
    else
    {
        target_acc = 0;
    }
}

void PathController::statemachine_task()
{
    car_current_cartisian_point = ConvertGPS2XY(car_current_imu_gps_data);
    CarGps2Cal_CarXY();
    switch (sm_state)
    {
    case SM_OFF:
        if (cartesian_path_points.size() != 0) // TODO: 1. read reference path and convert to s-l , return finishend.
        {
            sm_state = SM_STANDBY;
        }

        chassis_ctr_handshake_req = false;
        break;

    case SM_STANDBY:
        // TODO: 2 . if funtion on condition is reached.
        // active = Automobile_Active();
        active = true;
        if (active && current_gear == GEAR_P)
        {
            sm_state = SM_HANDSHAKE;
        }

        chassis_ctr_handshake_req = false;
        break;
    case SM_HANDSHAKE:
        // TODO: 3. if eps controlled is OK
        if (chassis_be_controlled == true)
        {
            sm_state = SM_ACTIVE;
        }
        chassis_ctr_handshake_req = true;
        break;
    case SM_ACTIVE:
        TargetInd = calc_pursuit_index();
        // TODO:  4 mini obstacle length < 10 meter
        if (dist_mini_obstacle < 4)
        {
            sm_state = SM_BRAKE;
        }

        else if (TargetInd == cartesian_path_points.size() - 1) // TODO 5 reach the reference path end
        {
            sm_state = SM_COMPLETE;
        }
        else
        {
            //TODO : SM active actions: calculate the output parameters
            Result ret;
            ret = pure_pursuit_control(TargetInd);
            target_steer_ang = ret.delta;
            Velocity_control();
            // then output
            chassis_ctr_handshake_req = true;
            target_gear = GEAR_D;
        }
        break;
    case SM_BRAKE:
        if (dist_mini_obstacle > 6)
        {
            sm_state = SM_ACTIVE;
        }
        else
        {
            chassis_ctr_handshake_req = true;
            target_acc = -0.5;
        }
        break;
    case SM_COMPLETE:
        if (current_gear == GEAR_P)
        {
            // jump to off, wait for next function on .
            sm_state = SM_OFF;
        }
        else
        {
            chassis_ctr_handshake_req = true;
            target_acc = -0.5;
            if (Car_current_velicity <= 0.2)
            {
                target_gear = GEAR_P;
            }
        }
        break;
    default:
        break;
    }
    //printf("SM state: %d, steer angle: %f \n", sm_state, target_steer_ang);
    // printf("SM state: %d, arget_steer_ang: %f, cam_distance: %f \n", sm_state, target_steer_ang, dist_mini_obstacle);
}
#ifndef PLANING_CONTROL_H
#define PLANING_CONTROL_H

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <queue>


#define  FILE_PATH  "/home/titan/Bo.csv"
const float VEHICLE_LENGTH = 2.7f;
const float PURSUIT_K   = 0.1f;
const float PURSUIT_LFC = 2;
 

struct CartesianXYPoint
{
    float cartesian_X;
    float cartesian_Y;
    CartesianXYPoint() : cartesian_X(0.0f), cartesian_Y(0.0f)
    {
    }

    CartesianXYPoint(const float _x, const float _y)
        : cartesian_X(_x), cartesian_Y(_y)
    {
    }

    CartesianXYPoint &operator=(const CartesianXYPoint &obj)
    {
        this->cartesian_X = obj.cartesian_X;
        this->cartesian_Y = obj.cartesian_Y;
        return *this;
    }
};

struct ImuGpsData
{
    double ImuGpsLon;
    double ImuGpsLat;
    double ImuGpsAlat;
};



enum Gear
{
    GEAR_NONE = 0,
    GEAR_P = 1,
    GEAR_R = 2,
    GEAR_N = 3,
    GEAR_D = 4,
};

struct Result
{
    double delta;
    int ind;
};

enum StateMachSts_st
{
    SM_OFF,
    SM_STANDBY,
    SM_HANDSHAKE,
    SM_ACTIVE,
    SM_BRAKE,
    SM_COMPLETE,
};



/**
 * @brief, As following steps: 
 *         1. Get reference GPS path, by csv files;
 *         2. Clean data;
 *         3. Transform reference path GPS data to XY coordinate;
 *         4. Vehicle GPS pose to XY;
 *         5. Get pursiut index;
 *         6. Get pursuit angle;    
 */
class PathController
{

public:
    PathController();
    ~PathController();

public:

    void statemachine_task();

public:
    // input parameters:--------------------------------------------------如何给直接给
    float Car_current_velicity; // uinit: m/s^2
    float dist_mini_obstacle;   // uinit: m
    ImuGpsData car_current_imu_gps_data;
    float CarCurrentSteerAngle;
    bool chassis_be_controlled;
    enum Gear current_gear;
    StateMachSts_st sm_state;
    // output
    enum Gear target_gear;
    float target_acc;       //uinit: m/s^2
    float target_steer_ang; // unit: degree -540 ~ +540
    bool chassis_ctr_handshake_req;

private:

    void ReadRefpathGPS_lon_lat_alat();

    void cleanRefPathGpsData();

    void refPathGps2XY();
    void CarGps2Cal_CarXY();

    void CalculateCarCurrentCartesianXYPt();
    int calc_pursuit_index(); //计算最短路径。
    Result pure_pursuit_control(int pind);
    // bool Automobile_Active();
    void Velocity_control();
    void read_ref_path_gps();
    CartesianXYPoint ConvertGPS2XY(ImuGpsData gps_data);

private:
    uint8_t ImuGpsSize_;
    std::vector<ImuGpsData> ref_path_points;
    std::vector<ImuGpsData> clean_path_points;
    std::vector<int> Index;

    std::vector<CartesianXYPoint> cartesian_path_points;
    std::queue<CartesianXYPoint> car_history_XY;
    std::vector<CartesianXYPoint> pts;
    CartesianXYPoint car_current_cartisian_point;
    CartesianXYPoint last_car_current_cartisian_point;
};

#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

14-于猛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值