553 lines
17 KiB
C
553 lines
17 KiB
C
#include <math.h>
|
||
#include <stdint.h>
|
||
#include <string.h>
|
||
|
||
#include "cJSON.h"
|
||
#include "coordtrans.h"
|
||
#include "rtk_gps.h"
|
||
|
||
#include "ql_log.h"
|
||
#define LOGD(msg, ...) QL_LOG(QL_LOG_LEVEL_DEBUG, "rtk", msg, ##__VA_ARGS__)
|
||
#define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "rtk", msg, ##__VA_ARGS__)
|
||
#define LOGW(msg, ...) QL_LOG(QL_LOG_LEVEL_WARN, "rtk", msg, ##__VA_ARGS__)
|
||
#define LOGE(msg, ...) QL_LOG(QL_LOG_LEVEL_ERROR, "rtk", msg, ##__VA_ARGS__)
|
||
|
||
extern uint16_t gWordVar[];
|
||
|
||
/**
|
||
* @brief 计算参数
|
||
*
|
||
*/
|
||
struct gps_coord_calc
|
||
{
|
||
double angle_offset; // GPS1(左侧Gps)旋转角度
|
||
double x_offset; // x偏移距离m
|
||
double y_offset; // y偏移距离m
|
||
};
|
||
/**
|
||
struct ConfigParam cfp = {
|
||
.dx = 0, // x坐标平移量(米)
|
||
.dy = 0, // y坐标平移量(米)
|
||
.dz = 0, // z坐标平移量(米)
|
||
.wx = 0, // x坐标旋转角度(秒)
|
||
.wy = 0, // y坐标旋转角度(秒)
|
||
.wz = 0, // z坐标旋转角度(秒)
|
||
.k = 0, // 尺度因子(ppm),这里其实应该用变量m表示
|
||
.height = 0, // 投影面高程
|
||
.gcsSrc = WGS84, // 原始坐标系
|
||
.gcsDst = WGS84, // 结果坐标系
|
||
};
|
||
! 大地坐标系类型
|
||
enum GEODETIC_COORD_SYSTEM { BJ54 = 0, XA80, WGS84, WGS2000 };
|
||
{
|
||
"dx": 0,
|
||
"dy": 0,
|
||
"dz": 0,
|
||
"wx": 0,
|
||
"wy": 0,
|
||
"wz": 0,
|
||
"k": 0,
|
||
"height": 0,
|
||
"gcsSrc": "WGS84",
|
||
"gcsDst": "WGS84",
|
||
}
|
||
*/
|
||
#define COORD_CFG_FILE_PATH "/coord_cfg.json"
|
||
static struct ConfigParam gps_coord_cfg; // 转换配置参数
|
||
/**
|
||
{
|
||
"y_offset": 0, // 单位m
|
||
"x_offset": 0, // 单位m
|
||
"angle_offset": 0, // 角度 度
|
||
}
|
||
*/
|
||
#define CALC_CFG_FILE_PATH "/calc_cfg.json"
|
||
static struct gps_coord_calc gps_coord_calc_cfg; // 计算配置参数
|
||
|
||
/**
|
||
* @brief 保存json配置文件
|
||
*
|
||
* @param json
|
||
* @param name
|
||
*/
|
||
static void save_json_cfg_file(cJSON *json, const char *name)
|
||
{
|
||
if (name == NULL || json == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
int8_t *buff_p = NULL;
|
||
int32_t buf_len = 0;
|
||
int32_t fileFd = -1;
|
||
int ret = 0;
|
||
fileFd = LSAPI_FS_Open(name, LSAPI_FS_O_RDONLY, 0x0);
|
||
if (fileFd < 0)
|
||
{
|
||
LOGE("LSAPI_FS_Open failed, file:%s\n", name);
|
||
return;
|
||
}
|
||
buff_p = cJSON_Print(json);
|
||
if (buff_p == NULL)
|
||
{
|
||
LOGE("cJSON_Print failed, buff_p is null\n");
|
||
goto exit0;
|
||
}
|
||
buf_len = strlen(buff_p);
|
||
ret = LSAPI_FS_Write(fileFd, (void *)buff_p, buf_len);
|
||
if (ret <= 0)
|
||
{
|
||
LOGE("LSAPI_FS_Write failed. ret:%d\n", ret);
|
||
goto exit1;
|
||
}
|
||
exit1:
|
||
LSAPI_OSI_Free(buff_p);
|
||
exit0:
|
||
LSAPI_FS_Close(fileFd);
|
||
return;
|
||
}
|
||
/**
|
||
* @brief 加载json配置文件
|
||
*
|
||
* @param name
|
||
* @return cJSON*
|
||
*/
|
||
static cJSON *load_json_cfg_file(const char *name)
|
||
{
|
||
if (name == NULL)
|
||
{
|
||
return NULL;
|
||
}
|
||
cJSON *json = NULL;
|
||
int8_t *buff_p = NULL;
|
||
int32_t fileFd = -1;
|
||
int32_t ret = 0;
|
||
fileFd = LSAPI_FS_Open(name, LSAPI_FS_O_RDONLY, 0x0);
|
||
if (fileFd < 0)
|
||
{
|
||
LOGE("LSAPI_FS_Open failed, file:%s\n", name);
|
||
return NULL;
|
||
}
|
||
LSAPI_FS_Stat_info_t fileStat = {0};
|
||
ret = LSAPI_FS_Fstat(fileFd, &fileStat);
|
||
if (fileStat.st_size > 4096)
|
||
{
|
||
fileStat.st_size = 4096;
|
||
}
|
||
buff_p = (int8_t *)LSAPI_OSI_Malloc(fileStat.st_size + 1); // byte
|
||
if (buff_p == NULL)
|
||
{
|
||
LOGE("LSAPI_OSI_Malloc failed, size:%d\n", fileStat.st_size + 1);
|
||
goto exit0;
|
||
}
|
||
memset(buff_p, 0x00, fileStat.st_size + 1);
|
||
ret = LSAPI_FS_Read(fileFd, (void *)buff_p, fileStat.st_size);
|
||
if (ret <= 0)
|
||
{
|
||
LOGE("LSAPI_FS_Read failed. ret:%d\n", ret);
|
||
goto exit1;
|
||
}
|
||
buff_p[fileStat.st_size] = '\0';
|
||
LSAPI_FS_Close(fileFd);
|
||
json = cJSON_Parse((const char *)buff_p);
|
||
LSAPI_OSI_Free(buff_p);
|
||
buff_p = NULL;
|
||
if (json == NULL)
|
||
{
|
||
LOGE("JSON_Parse Err ret%s", cJSON_GetErrorPtr());
|
||
}
|
||
return json;
|
||
exit1:
|
||
LSAPI_OSI_Free(buff_p);
|
||
buff_p = NULL;
|
||
exit0:
|
||
LSAPI_FS_Close(fileFd);
|
||
return NULL;
|
||
}
|
||
|
||
/**
|
||
* @brief 加载转换参数配置
|
||
*
|
||
* @param coord_cfg
|
||
*/
|
||
void load_coord_cfg(struct ConfigParam *coord_cfg, const char *filePath)
|
||
{
|
||
cJSON *node, *child;
|
||
cJSON *cfg_json = load_json_cfg_file(filePath);
|
||
if (cfg_json != NULL)
|
||
{
|
||
node = cJSON_GetObjectItem(cfg_json, "dx");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->dx = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "dy");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->dy = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "dz");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->dz = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "wx");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->wx = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "wy");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->wy = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "wz");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->wz = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "k");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->k = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "height");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->height = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "gcsSrc");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->gcsSrc = node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "gcsDst");
|
||
if (node != NULL)
|
||
{
|
||
coord_cfg->gcsDst = node->valueint;
|
||
}
|
||
LOGE("load_coord_cfg success, filePath:%s\n", filePath);
|
||
cJSON_Delete(cfg_json);
|
||
}
|
||
else
|
||
{
|
||
LOGE("cfg_json is null, filePath:%s\n", filePath);
|
||
}
|
||
}
|
||
/**
|
||
* @brief 保存转换参数配置
|
||
*
|
||
* @param coord_cfg
|
||
*/
|
||
void save_coord_cfg(struct ConfigParam *coord_cfg, const char *filePath)
|
||
{
|
||
cJSON *cfg_json = cJSON_CreateObject();
|
||
if (cfg_json != NULL)
|
||
{
|
||
cJSON_AddNumberToObject(cfg_json, "dx", coord_cfg->dx);
|
||
cJSON_AddNumberToObject(cfg_json, "dy", coord_cfg->dy);
|
||
cJSON_AddNumberToObject(cfg_json, "dz", coord_cfg->dz);
|
||
cJSON_AddNumberToObject(cfg_json, "wx", coord_cfg->wx);
|
||
cJSON_AddNumberToObject(cfg_json, "wy", coord_cfg->wy);
|
||
cJSON_AddNumberToObject(cfg_json, "wz", coord_cfg->wz);
|
||
cJSON_AddNumberToObject(cfg_json, "k", coord_cfg->k);
|
||
cJSON_AddNumberToObject(cfg_json, "height", coord_cfg->height);
|
||
cJSON_AddNumberToObject(cfg_json, "gcsSrc", coord_cfg->gcsSrc);
|
||
cJSON_AddNumberToObject(cfg_json, "gcsDst", coord_cfg->gcsDst);
|
||
save_cfg_file(cfg_json, filePath);
|
||
cJSON_Delete(cfg_json);
|
||
}
|
||
}
|
||
/**
|
||
* @brief 加载计算参数配置
|
||
*
|
||
* @param coord_cfg
|
||
*/
|
||
void load_calc_cfg(struct gps_coord_calc *calc_cfg, const char *filePath)
|
||
{
|
||
cJSON *node, *child;
|
||
cJSON *cfg_json = load_json_cfg_file(filePath);
|
||
if (cfg_json != NULL)
|
||
{
|
||
node = cJSON_GetObjectItem(cfg_json, "y_offset");
|
||
if (node != NULL)
|
||
{
|
||
calc_cfg->y_offset = (double)node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "x_offset");
|
||
if (node != NULL)
|
||
{
|
||
calc_cfg->x_offset = (double)node->valueint;
|
||
}
|
||
node = cJSON_GetObjectItem(cfg_json, "angle_offset");
|
||
if (node != NULL)
|
||
{
|
||
calc_cfg->angle_offset = (double)node->valueint;
|
||
}
|
||
LOGT("load_calc_cfg success, filePath:%s, y_offset:%lf, x_offset:%lf, angle_offset:%lf\n",
|
||
filePath, calc_cfg->y_offset, calc_cfg->x_offset, calc_cfg->angle_offset);
|
||
cJSON_Delete(cfg_json);
|
||
}
|
||
else
|
||
{
|
||
LOGE("cfg_json is null, filePath:%s\n", filePath);
|
||
}
|
||
}
|
||
|
||
void gps_coord_init(const char *filePath)
|
||
{
|
||
memset(&gps_coord_cfg, 0x00, sizeof(gps_coord_cfg));
|
||
/**
|
||
* @brief 加载配置 若无配置需要在远程传输后自动加载配置 可指定配置文件路径
|
||
*
|
||
*/
|
||
if (filePath == NULL)
|
||
{
|
||
load_coord_cfg(&gps_coord_cfg, COORD_CFG_FILE_PATH);
|
||
}
|
||
else
|
||
{
|
||
load_coord_cfg(&gps_coord_cfg, filePath);
|
||
}
|
||
// 初始化常用椭球参数信息
|
||
DatumEllipsoidal(0, 0, NULL); // 初始化中央子午线118
|
||
}
|
||
|
||
void gps_coord_calc_init(const char *filePath)
|
||
{
|
||
memset(&gps_coord_calc_cfg, 0x00, sizeof(gps_coord_calc_cfg));
|
||
if (filePath == NULL)
|
||
{
|
||
load_calc_cfg(&gps_coord_calc_cfg, CALC_CFG_FILE_PATH);
|
||
}
|
||
else
|
||
{
|
||
load_calc_cfg(&gps_coord_calc_cfg, filePath);
|
||
}
|
||
}
|
||
|
||
#define PI (3.1415926)
|
||
#define ANGLE_TO_RADIAN(a) ((a) * (PI) / 180) // 角度转弧度
|
||
#define ANGLE_TO_DEGREES(a) ((a)*180 / (PI)) // 角度转度
|
||
/**
|
||
* @brief 点旋转
|
||
*
|
||
* @param point 指定点
|
||
* @param angle 旋转角度
|
||
* @param origin 原始点
|
||
* @param res 结果点
|
||
* @return int
|
||
*/
|
||
static int pointRotate(struct Point *point, double angle, struct Point *origin, struct Point *res)
|
||
{
|
||
if (point == NULL || res == NULL)
|
||
{
|
||
return 1;
|
||
}
|
||
double r = ANGLE_TO_RADIAN(angle); // 角度转弧度??
|
||
if (origin == NULL || (origin->x == 0 && origin->y == 0))
|
||
{
|
||
// See: https://en.wikipedia.org/wiki/Cartesian_coordinate_system#Rotation
|
||
res->x = point->x * cos(r) - point->y * sin(r);
|
||
res->y = point->x * sin(r) + point->y * cos(r);
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
// See: https://math.stackexchange.com/questions/1964905/rotation-around-non-zero-point
|
||
struct Point p0 = {point->x - origin->x, point->y - origin->y};
|
||
struct Point rotated;
|
||
rotated.x = p0.x * cos(r) - p0.y * sin(r);
|
||
rotated.y = p0.x * sin(r) + p0.y * cos(r);
|
||
res->x = rotated.x + origin->x;
|
||
res->y = rotated.y + origin->y;
|
||
return 0;
|
||
}
|
||
}
|
||
/**
|
||
* @brief 以度数和距离为单位按角度平移点
|
||
*
|
||
* @param point 需要平移的原始点
|
||
* @param angle 角度
|
||
* @param distance 距离
|
||
* @param res_point 结果点
|
||
*/
|
||
static void pointTranslate(struct Point *point, double angle, double distance,
|
||
struct Point *res_point)
|
||
{
|
||
if (point == NULL || res_point == NULL)
|
||
{
|
||
return;
|
||
}
|
||
double r = ANGLE_TO_RADIAN(angle);
|
||
res_point->x = point->x + distance * cos(r);
|
||
res_point->y = point->y + distance * sin(r);
|
||
return;
|
||
}
|
||
static double lineAngle(struct Point *line_s, struct Point *line_e)
|
||
{
|
||
if (line_s == NULL || line_e == NULL)
|
||
{
|
||
return 0;
|
||
}
|
||
return ANGLE_TO_DEGREES(atan2(line_e->y - line_s->y, line_e->x - line_s->x));
|
||
}
|
||
/**
|
||
* @brief 计算出从指定线起始点为x_offset距离的点的坐标
|
||
*
|
||
* @param line_s 线起始点
|
||
* @param line_e 线终点
|
||
* @param x_offset 偏移距离
|
||
* @param res_point 结果点
|
||
* @return int
|
||
*/
|
||
static int lineInterpolate(struct Point *line_s, struct Point *line_e, double x_offset,
|
||
struct Point *res_point)
|
||
{ // line_s + line_e构成一条直线
|
||
if (line_e == NULL || line_s == NULL)
|
||
{
|
||
return 1;
|
||
}
|
||
/**
|
||
* @brief 以起始点line_s作为原点进行旋转
|
||
* 旋转角度为起始点和终点的连线并且得出与水平线的夹角lineAngle(line_s, line_e)顺时针旋转
|
||
* 最终根据偏移x_offset计算出结果点
|
||
*/
|
||
pointTranslate(line_s, lineAngle(line_s, line_e), x_offset, res_point);
|
||
return 0;
|
||
}
|
||
|
||
// 七参数modbus参数地址集合
|
||
#define MODBUS_GPS_COORD_DX_ADDR 1024
|
||
#define MODBUS_GPS_COORD_DY_ADDR 1026
|
||
#define MODBUS_GPS_COORD_DZ_ADDR 1028
|
||
#define MODBUS_GPS_COORD_WX_ADDR 1030
|
||
#define MODBUS_GPS_COORD_WY_ADDR 1032
|
||
#define MODBUS_GPS_COORD_WZ_ADDR 1034
|
||
#define MODBUS_GPS_COORD_K_ADDR 1036
|
||
#define MODBUS_GPS_COORD_HEIGHT_ADDR 1038
|
||
#define MODBUS_GPS_COORD_GCSSRC_ADDR 1040
|
||
#define MODBUS_GPS_COORD_GCSDST_ADDR 1041
|
||
// 计算参数modbus参数地址集合
|
||
#define MODBUS_GPS_CALC_X_ADDR 1042
|
||
#define MODBUS_GPS_CALC_Y_ADDR 1044
|
||
#define MODBUS_GPS_CALC_ANGLE_ADDR 1046
|
||
|
||
static inline void get_gps_coord_param_bymodbus(struct ConfigParam *gps_coord_cfg)
|
||
{
|
||
if (gps_coord_cfg == NULL)
|
||
{
|
||
return;
|
||
}
|
||
gps_coord_cfg->dx =
|
||
(double)((gWordVar[MODBUS_GPS_COORD_DX_ADDR] | gWordVar[MODBUS_GPS_COORD_DX_ADDR + 1] << 16) /
|
||
1000000.0); // 六位小数
|
||
gps_coord_cfg->dy =
|
||
(double)((gWordVar[MODBUS_GPS_COORD_DY_ADDR] | gWordVar[MODBUS_GPS_COORD_DY_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
gps_coord_cfg->dz =
|
||
(double)((gWordVar[MODBUS_GPS_COORD_DZ_ADDR] | gWordVar[MODBUS_GPS_COORD_DZ_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
gps_coord_cfg->wx =
|
||
(double)((gWordVar[MODBUS_GPS_COORD_WX_ADDR] | gWordVar[MODBUS_GPS_COORD_WX_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
gps_coord_cfg->wy =
|
||
(double)((gWordVar[MODBUS_GPS_COORD_WY_ADDR] | gWordVar[MODBUS_GPS_COORD_WY_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
gps_coord_cfg->wz =
|
||
(double)((gWordVar[MODBUS_GPS_COORD_WZ_ADDR] | gWordVar[MODBUS_GPS_COORD_WZ_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
gps_coord_cfg->k =
|
||
(double)((gWordVar[MODBUS_GPS_COORD_K_ADDR] | gWordVar[MODBUS_GPS_COORD_K_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
gps_coord_cfg->height = (double)((gWordVar[MODBUS_GPS_COORD_HEIGHT_ADDR] |
|
||
gWordVar[MODBUS_GPS_COORD_HEIGHT_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
gps_coord_cfg->gcsSrc = (gWordVar[MODBUS_GPS_COORD_GCSSRC_ADDR]);
|
||
gps_coord_cfg->gcsDst = (gWordVar[MODBUS_GPS_COORD_GCSDST_ADDR]);
|
||
}
|
||
|
||
static inline void get_gps_calc_param_bymodbus(struct gps_coord_calc *gps_calc_cfg)
|
||
{
|
||
if (gps_calc_cfg == NULL)
|
||
{
|
||
return;
|
||
}
|
||
gps_calc_cfg->x_offset =
|
||
(double)((gWordVar[MODBUS_GPS_CALC_X_ADDR] | gWordVar[MODBUS_GPS_CALC_X_ADDR + 1] << 16) /
|
||
1000000.0); // 六位小数
|
||
gps_calc_cfg->y_offset =
|
||
(double)((gWordVar[MODBUS_GPS_CALC_Y_ADDR] | gWordVar[MODBUS_GPS_CALC_Y_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
gps_calc_cfg->angle_offset =
|
||
(double)((gWordVar[MODBUS_GPS_CALC_ANGLE_ADDR] | gWordVar[MODBUS_GPS_CALC_ANGLE_ADDR + 1] << 16) /
|
||
1000000.0);
|
||
}
|
||
/**
|
||
* @brief 坐标转换+计算中心坐标点任务
|
||
* 1、获取Gps1/2的原始经纬度坐标
|
||
* 2、将经纬度坐标转换成平面坐标
|
||
* 3、根据计算参数计算目标节点坐标
|
||
*/
|
||
/**
|
||
* @brief
|
||
*
|
||
* @param gps1
|
||
* @param gps2
|
||
*/
|
||
void gps_calc_target_point(gps_t *gps1, gps_t *gps2, struct car_param_data *cpd)
|
||
{
|
||
if (gps1 == NULL || gps2 == NULL || cpd == NULL)
|
||
{
|
||
return;
|
||
}
|
||
if (!(gps1->LAT != 0 && gps1->LNG != 0 && gps2->LAT != 0 && gps2->LNG != 0))
|
||
{
|
||
return;
|
||
}
|
||
// get_gps_coord_param_bymodbus(&gps_coord_cfg); // 从modbus更新七参数
|
||
// get_gps_calc_param_bymodbus(&gps_coord_calc_cfg); // 从modbus更新计算参数
|
||
LOGD("angle_offset:%lf, x_offset:%lf, y_offset:%lf\n",
|
||
gps_coord_calc_cfg.angle_offset, gps_coord_calc_cfg.x_offset,
|
||
gps_coord_calc_cfg.y_offset);
|
||
struct Point gps1_d2p_i = {(double)(gps1->LAT / 10000000.00), (double)(gps1->LNG / 10000000.00),
|
||
0.000000000000};
|
||
struct Point gps1_d2p_res = d2p(&gps1_d2p_i, &gps_coord_cfg); // 大地坐标转平面坐标
|
||
|
||
struct Point gps2_d2p_i = {(double)(gps2->LAT / 10000000.00), (double)(gps2->LNG / 10000000.00),
|
||
0.000000000000};
|
||
struct Point gps2_d2p_res = d2p(&gps2_d2p_i, &gps_coord_cfg);
|
||
|
||
LOGD("gps1: src_x:%lf, src_y:%lf, res_x:%lf, res_y:%lf\n", gps1_d2p_i.x,
|
||
gps1_d2p_i.y, gps1_d2p_res.x, gps1_d2p_res.y);
|
||
LOGD("gps2: src_x:%lf, src_y:%lf, res_x:%lf, res_y:%lf\n", gps2_d2p_i.x,
|
||
gps2_d2p_i.y, gps2_d2p_res.x, gps2_d2p_res.y);
|
||
// ## 1 旋转Gps2点
|
||
struct Point gps2ResPoint; // 旋转后Gps2的坐标
|
||
// pointRotate(&gps2_d2p_res, gps_coord_calc_cfg.angle_offset, &gps1_d2p_res, &gps2ResPoint);
|
||
// cpd->angle = lineAngle(&gps1_d2p_res, &gps2ResPoint) - 90; // 保留当前车体角度
|
||
// ## 2 平移Gps1点(x_offset)
|
||
struct Point gps1ResPoint; // 平移后Gps1的坐标
|
||
lineInterpolate(&gps1_d2p_res, &gps2ResPoint, gps_coord_calc_cfg.x_offset, &gps1ResPoint);
|
||
// ## 3 平移Gps1点(y_offset) // 旋转+平移
|
||
struct Point gps2_ResPoint; // 旋转后Gps2`的坐标
|
||
double angle_offset_tmp = 0;
|
||
if (gps_coord_calc_cfg.y_offset >= 0)
|
||
{
|
||
angle_offset_tmp = -90; // 目标点在gps1_d2p_res与gps2ResPoint之间的直线右侧
|
||
}
|
||
else
|
||
{
|
||
angle_offset_tmp = 90; // 目标点在gps1_d2p_res与gps2ResPoint之间的直线左侧
|
||
}
|
||
pointRotate(&gps2ResPoint, angle_offset_tmp, &gps1ResPoint,
|
||
&gps2_ResPoint); // 以gps1ResPoint为起点
|
||
struct Point flat_res_point;
|
||
lineInterpolate(&gps1ResPoint, &gps2_ResPoint, gps_coord_calc_cfg.y_offset,
|
||
&flat_res_point); // 以gps1ResPoint为起点
|
||
// ## end 将平面坐标转换成大地坐标(上面的结果为平面坐标)
|
||
// cpd->target = p2d(&flat_res_point, &gps_coord_cfg); // 大地坐标转平面坐标
|
||
// log_printf(LDEBUG, LOG_TAG "res_point: x:%lf, y:%lf, angle:%lf\n", cpd->target.x, cpd->target.y,
|
||
// cpd->angle);
|
||
return;
|
||
}
|