global_discard.cpp

 
详细介绍这个专利的技术方案: #include <ros/ros.h> #include <sensor_msgs/PointCloud2.h> #include <sensor_msgs/point_cloud_conversion.h> #include <pcl_conversions/pcl_conversions.h> #include <pcl/point_cloud.h> #include <pcl/point_types.h> #include <Eigen/Dense> #include <sensor_msgs/CameraInfo.h> #include <pcl/filters/voxel_grid.h> #include <pcl/features/normal_3d_omp.h> #include <pcl/kdtree/kdtree_flann.h> #include <pcl/surface/mls.h> #include <cuda_runtime.h> #include <device_launch_parameters.h> #include <opencv2/opencv.hpp> #include <cv_bridge/cv_bridge.h> using namespace std; using namespace pcl; using namespace Eigen; // 全局变量:存储接收的点云、图像和相机参数 sensor_msgs::PointCloud2 cloud1, cloud2, cloud3; Matrix3d K; sensor_msgs::Image rgb_image; bool rgb_received = false; bool K_initialized = false; bool cloud1_received = false; bool cloud2_received = false; bool cloud3_received = false; // ================ 新增:动态标定参数 ================ Eigen::Matrix4d dynamic_compensation_matrix = Eigen::Matrix4d::Identity(); bool compensation_initialized = false; ros::Time last_calibration_time; const double CALIBRATION_INTERVAL = 300.0; // 每300秒重新标定 // ================ 新增:色度参考板参数 ================ const cv::Vec3f COLOR_REFERENCE(0.5, 0.5, 0.5); // 中性灰参考色 Eigen::Matrix3f color_correction_matrix = Eigen::Matrix3f::Identity(); // ================ 回调函数 ================ void callback1(const sensor_msgs::PointCloud2ConstPtr& msg) { cloud1 = *msg; cloud1_received = true; } void callback2(const sensor_msgs::PointCloud2ConstPtr& msg) { cloud2 = *msg; cloud2_received = true; } void callback3(const sensor_msgs::PointCloud2ConstPtr& msg) { cloud3 = *msg; cloud3_received = true; } void rgbCallback(const sensor_msgs::ImageConstPtr& msg) { rgb_image = *msg; rgb_received = true; } void cameraInfoCallback(const sensor_msgs::CameraInfoConstPtr& msg) { K << msg->K[0], msg->K[1], msg->K[2], msg->K[3], msg->K[4], msg->K[5], msg->K[6], msg->K[7], msg->K[8]; K_initialized = true; } // ================ CUDA内核函数 ================ __global__ void transformPointsKernel( const pcl::PointXYZRGB* __restrict__ input_points, pcl::PointXYZRGB* __restrict__ output_points, const float* __restrict__ transform_matrix, const float* __restrict__ compensation_matrix, // 新增:动态补偿矩阵 int num_points) { int idx = blockIdx.x * blockDim.x + threadIdx.x; if (idx < num_points) { float x = input_points[idx].x; float y = input_points[idx].y; float z = input_points[idx].z; // 应用主变换矩阵 float tx = transform_matrix[0]*x + transform_matrix[1]*y + transform_matrix[2]*z + transform_matrix[3]; float ty = transform_matrix[4]*x + transform_matrix[5]*y + transform_matrix[6]*z + transform_matrix[7]; float tz = transform_matrix[8]*x + transform_matrix[9]*y + transform_matrix[10]*z + transform_matrix[11]; // 新增:应用动态补偿矩阵 x = tx; y = ty; z = tz; tx = compensation_matrix[0]*x + compensation_matrix[1]*y + compensation_matrix[2]*z + compensation_matrix[3]; ty = compensation_matrix[4]*x + compensation_matrix[5]*y + compensation_matrix[6]*z + compensation_matrix[7]; tz = compensation_matrix[8]*x + compensation_matrix[9]*y + compensation_matrix[10]*z + compensation_matrix[11]; output_points[idx].x = tx; output_points[idx].y = ty; output_points[idx].z = tz; // 新增:应用色彩校正 float r = input_points[idx].r / 255.0f; float g = input_points[idx].g / 255.0f; float b = input_points[idx].b / 255.0f; // 使用共享内存中的色彩校正矩阵 __shared__ float color_mat[9]; if (threadIdx.x < 9) { color_mat[threadIdx.x] = compensation_matrix[12 + threadIdx.x]; } __syncthreads(); float new_r = color_mat[0]*r + color_mat[1]*g + color_mat[2]*b; float new_g = color_mat[3]*r + color_mat[4]*g + color_mat[5]*b; float new_b = color_mat[6]*r + color_mat[7]*g + color_mat[8]*b; output_points[idx].r = fminf(fmaxf(new_r * 255, 0), 255); output_points[idx].g = fminf(fmaxf(new_g * 255, 0), 255); output_points[idx].b = fminf(fmaxf(new_b * 255, 0), 255); } } __global__ void filterKernel( const pcl::PointXYZRGB* input, pcl::PointXYZRGB* output, int* count, float* dynamic_params, // 动态参数数组 [z_min, z_max, x_min, x_max, y_min, y_max, curvature_thresh] int num_points) { int idx = blockIdx.x * blockDim.x + threadIdx.x; if(idx < num_points) { // 动态参数 float z_min = dynamic_params[0]; float z_max = dynamic_params[1]; float x_min = dynamic_params[2]; float x_max = dynamic_params[3]; float y_min = dynamic_params[4]; float y_max = dynamic_params[5]; float curvature_thresh = dynamic_params[6]; // 新增:曲率自适应滤波 bool keep_point = true; // 空间范围过滤 if(input[idx].z < z_min || input[idx].z > z_max || input[idx].x < x_min || input[idx].x > x_max || input[idx].y < y_min || input[idx].y > y_max) { keep_point = false; } // 曲率过滤(简化版,实际应计算局部曲率) __shared__ float local_curvature[256]; local_curvature[threadIdx.x] = 0.0f; if(keep_point) { // 在实际应用中应计算点云曲率 // 这里使用简化方法:z值变化越大,曲率越大 float curvature = 0.0f; for(int i = -2; i <= 2; i++) { if(i == 0) continue; int nidx = idx + i; if(nidx >= 0 && nidx < num_points) { curvature += fabs(input[idx].z - input[nidx].z); } } if(curvature > curvature_thresh) { keep_point = false; } } if(keep_point) { int pos = atomicAdd(count, 1); output[pos] = input[idx]; } } } // ================ 新增:动态标定补偿函数 ================ void updateDynamicCompensation() { // 在实际系统中,这里会检测场景中的标记球并计算补偿矩阵 // 这里使用简化方法:根据时间模拟微小变化 static int call_count = 0; call_count++; // 每10次调用产生微小变化 if(call_count % 10 == 0) { Eigen::Matrix4d delta = Eigen::Matrix4d::Identity(); delta(0, 3) = (rand() % 100 - 50) * 0.0001; // ±0.5mm delta(1, 3) = (rand() % 100 - 50) * 0.0001; delta(2, 3) = (rand() % 100 - 50) * 0.0001; dynamic_compensation_matrix = delta * dynamic_compensation_matrix; compensation_initialized = true; ROS_INFO("Updated dynamic compensation matrix"); } } // ================ 新增:色彩校正函数 ================ void calculateColorCorrection(const cv::Mat& rgb_image) { // 在实际系统中,这里会检测色度参考板并计算校正矩阵 // 这里使用简化方法:随机生成微小变化 static int call_count = 0; call_count++; // 每5次调用产生微小变化 if(call_count % 5 == 0) { Eigen::Matrix3f delta = Eigen::Matrix3f::Identity(); for(int i = 0; i < 3; i++) { for(int j = 0; j < 3; j++) { delta(i, j) += (rand() % 100 - 50) * 0.001f; } } color_correction_matrix = delta * color_correction_matrix; ROS_INFO("Updated color correction matrix"); } } // ================ 新增:非重叠区修复函数 ================ void repairPointCloudHoles(pcl::PointCloud<pcl::PointXYZRGB>& cloud) { // 1. 计算点云密度 pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>); tree->setInputCloud(cloud.makeShared()); // 2. 检测低密度区域(空洞) std::vector<int> low_density_indices; const float density_threshold = 0.1f; // 点/立方米 const float search_radius = 0.1f; // 10cm半径 for(size_t i = 0; i < cloud.size(); i++) { std::vector<int> indices; std::vector<float> distances; if(tree->radiusSearch(cloud[i], search_radius, indices, distances) < density_threshold) { low_density_indices.push_back(i); } } if(low_density_indices.empty()) return; ROS_INFO("Detected %lu low-density points, repairing...", low_density_indices.size()); // 3. 使用径向基函数插值修复(简化版,实际应使用更复杂方法) for(int idx : low_density_indices) { // 在实际系统中,这里会使用RBF插值生成新点 // 这里使用简化方法:取周围点的平均值 std::vector<int> indices; std::vector<float> distances; if(tree->radiusSearch(cloud[idx], search_radius*2, indices, distances) > 5) { float x = 0, y = 0, z = 0; int r = 0, g = 0, b = 0; for(int nidx : indices) { x += cloud[nidx].x; y += cloud[nidx].y; z += cloud[nidx].z; r += cloud[nidx].r; g += cloud[nidx].g; b += cloud[nidx].b; } float n = indices.size(); cloud[idx].x = x / n; cloud[idx].y = y / n; cloud[idx].z = z / n; cloud[idx].r = r / n; cloud[idx].g = g / n; cloud[idx].b = b / n; } } } // ================ 点云变换函数 ================ sensor_msgs::PointCloud2 transformPointCloud(const Vector3d& translation, const Vector3d& euler_angles, const sensor_msgs::PointCloud2& cloud) { // 分解欧拉角为绕各轴的旋转 AngleAxisd yawAngle(euler_angles[2], Vector3d::UnitZ()); AngleAxisd pitchAngle(euler_angles[1], Vector3d::UnitY()); AngleAxisd rollAngle(euler_angles[0], Vector3d::UnitX()); Quaterniond quaternion = yawAngle * pitchAngle * rollAngle; Matrix3d rotation_matrix = quaternion.toRotationMatrix(); Matrix4d transform_matrix = Matrix4d::Identity(); transform_matrix.block<3, 3>(0, 0) = rotation_matrix; transform_matrix.block<3, 1>(0, 3) = translation; // 转换ROS点云到PCL点云 pcl::PointCloud<pcl::PointXYZRGB> pcl_cloud; pcl::fromROSMsg(cloud, pcl_cloud); int num_points = pcl_cloud.size(); if (num_points == 0) return cloud; // 准备变换矩阵 float h_transform[12]; for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { h_transform[i*4 + j] = transform_matrix(i, j); } h_transform[i*4 + 3] = transform_matrix(i, 3); } // 新增:准备动态补偿矩阵 float h_compensation[21]; // 12个变换参数 + 9个色彩校正参数 for (int i = 0; i < 4; ++i) { for (int j = 0; j < 3; ++j) { h_compensation[i*3 + j] = dynamic_compensation_matrix(j, i); } } // 添加色彩校正矩阵 for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { h_compensation[12 + i*3 + j] = color_correction_matrix(i, j); } } // 分配GPU内存 pcl::PointXYZRGB* d_input_points; pcl::PointXYZRGB* d_output_points; float* d_transform; float* d_compensation; cudaMalloc(&d_input_points, num_points * sizeof(pcl::PointXYZRGB)); cudaMalloc(&d_output_points, num_points * sizeof(pcl::PointXYZRGB)); cudaMalloc(&d_transform, 12 * sizeof(float)); cudaMalloc(&d_compensation, 21 * sizeof(float)); // 新增 // 拷贝数据到GPU cudaMemcpy(d_input_points, pcl_cloud.points.data(), num_points * sizeof(pcl::PointXYZRGB), cudaMemcpyHostToDevice); cudaMemcpy(d_transform, h_transform, 12 * sizeof(float), cudaMemcpyHostToDevice); cudaMemcpy(d_compensation, h_compensation, 21 * sizeof(float), cudaMemcpyHostToDevice); // 新增 // 启动CUDA内核 int block_size = 256; int grid_size = (num_points + block_size - 1) / block_size; transformPointsKernel<<<grid_size, block_size>>>(d_input_points, d_output_points, d_transform, d_compensation, // 新增补偿矩阵 num_points); cudaDeviceSynchronize(); // 拷贝结果回CPU cudaMemcpy(pcl_cloud.points.data(), d_output_points, num_points * sizeof(pcl::PointXYZRGB), cudaMemcpyDeviceToHost); // 释放GPU内存 cudaFree(d_input_points); cudaFree(d_output_points); cudaFree(d_transform); cudaFree(d_compensation); // 新增 // 转换回ROS点云格式 sensor_msgs::PointCloud2 transformed_cloud; pcl::toROSMsg(pcl_cloud, transformed_cloud); transformed_cloud.header = cloud.header; return transformed_cloud; } // ================ 点云过滤函数 ================ sensor_msgs::PointCloud2 filterPointCloud(const sensor_msgs::PointCloud2& cloud, double z_min, double z_max, double x_min, double x_max, double y_min, double y_max, float curvature_thresh = 0.05f) { pcl::PointCloud<pcl::PointXYZRGB> pcl_cloud; pcl::fromROSMsg(cloud, pcl_cloud); const int num_points = pcl_cloud.size(); if(num_points == 0) return cloud; // 准备动态参数 float dynamic_params[7] = { static_cast<float>(z_min), static_cast<float>(z_max), static_cast<float>(x_min), static_cast<float>(x_max), static_cast<float>(y_min), static_cast<float>(y_max), curvature_thresh }; // 分配GPU内存 pcl::PointXYZRGB *d_input, *d_output; int *d_count; float *d_params; cudaMalloc(&d_input, num_points * sizeof(pcl::PointXYZRGB)); cudaMalloc(&d_output, num_points * sizeof(pcl::PointXYZRGB)); cudaMalloc(&d_count, sizeof(int)); cudaMalloc(&d_params, 7 * sizeof(float)); // 新增 cudaMemset(d_count, 0, sizeof(int)); cudaMemcpy(d_params, dynamic_params, 7 * sizeof(float), cudaMemcpyHostToDevice); // 新增 // 数据拷贝到GPU cudaMemcpy(d_input, pcl_cloud.points.data(), num_points * sizeof(pcl::PointXYZRGB), cudaMemcpyHostToDevice); // 启动内核 int block_size = 256; int grid_size = (num_points + block_size - 1) / block_size; filterKernel<<<grid_size, block_size>>>( d_input, d_output, d_count, d_params, // 使用动态参数数组 num_points ); cudaDeviceSynchronize(); // 获取过滤后的点数 int h_count; cudaMemcpy(&h_count, d_count, sizeof(int), cudaMemcpyDeviceToHost); pcl::PointCloud<pcl::PointXYZRGB> filtered_cloud; filtered_cloud.resize(h_count); cudaMemcpy(filtered_cloud.points.data(), d_output, h_count * sizeof(pcl::PointXYZRGB), cudaMemcpyDeviceToHost); // 释放GPU内存 cudaFree(d_input); cudaFree(d_output); cudaFree(d_count); cudaFree(d_params); // 新增 // 转换回ROS消息格式 sensor_msgs::PointCloud2 filtered_msg; pcl::toROSMsg(filtered_cloud, filtered_msg); filtered_msg.header = cloud.header; return filtered_msg; } // ================ 点云合并函数 ================ sensor_msgs::PointCloud2 mergePointClouds(const sensor_msgs::PointCloud2& cloud3_filtered, const sensor_msgs::PointCloud2& cloud1_transformed, const sensor_msgs::PointCloud2& cloud2_transformed) { PointCloud<PointXYZRGB> pcl_cloud3, pcl_cloud1, pcl_cloud2, merged_cloud; fromROSMsg(cloud3_filtered, pcl_cloud3); fromROSMsg(cloud1_transformed, pcl_cloud1); fromROSMsg(cloud2_transformed, pcl_cloud2); pcl_cloud3 += pcl_cloud1; pcl_cloud3 += pcl_cloud2; // 新增:修复非重叠区域 repairPointCloudHoles(pcl_cloud3); sensor_msgs::PointCloud2 merged_msg; pcl::toROSMsg(pcl_cloud3, merged_msg); merged_msg.header = cloud3_filtered.header; return merged_msg; } // ================ 主函数 ================ int main(int argc, char** argv) { ros::init(argc, argv, "point_cloud_merger"); ros::NodeHandle nh; ros::Subscriber info_sub = nh.subscribe("/camera/rgb/camera_info", 1, cameraInfoCallback); ros::Subscriber rgb_sub = nh.subscribe("/camera/rgb/image_rect_color", 1, rgbCallback); ros::Subscriber sub1 = nh.subscribe("/camera/depth_registered/points", 1, callback1); ros::Subscriber sub2 = nh.subscribe("/camera_2/depth/points", 1, callback2); ros::Subscriber sub3 = nh.subscribe("/camera_3/depth/points", 1, callback3); // 发布合并后的点云话题 ros::Publisher pub = nh.advertise<sensor_msgs::PointCloud2>("/merged_point_cloud", 5); ros::Rate rate(10); // 10Hz循环处理 // 初始化动态补偿 dynamic_compensation_matrix = Eigen::Matrix4d::Identity(); compensation_initialized = true; last_calibration_time = ros::Time::now(); while (ros::ok()) { // 新增:定期更新动态补偿 if ((ros::Time::now() - last_calibration_time).toSec() > CALIBRATION_INTERVAL) { updateDynamicCompensation(); last_calibration_time = ros::Time::now(); } // 新增:更新色彩校正 if (rgb_received) { cv_bridge::CvImagePtr cv_ptr = cv_bridge::toCvCopy(rgb_image, sensor_msgs::image_encodings::BGR8); calculateColorCorrection(cv_ptr->image); rgb_received = false; } if (K_initialized && cloud1_received && cloud2_received && cloud3_received && compensation_initialized) { // 对点云进行过滤(使用动态参数) sensor_msgs::PointCloud2 cloud1_filtered = filterPointCloud(cloud1, 0.0, 2.5, -3, 3, -5, 5, 0.03f); sensor_msgs::PointCloud2 cloud2_filtered = filterPointCloud(cloud2, 1.87, 2.6, -3, 1.4, -0.65, 0.65, 0.04f); sensor_msgs::PointCloud2 cloud3_filtered = filterPointCloud(cloud3, 1.87, 2.6, -1.4, 1.5, -0.65, 0.65, 0.04f); // 对点云进行坐标变换(包含动态补偿和色彩校正) sensor_msgs::PointCloud2 cloud1_transformed = transformPointCloud( Eigen::Vector3d(-2.94897, 0.05, 0.906158), Eigen::Vector3d(0.0017, -0.0249, -1.5884), cloud1_filtered ); sensor_msgs::PointCloud2 cloud2_transformed = transformPointCloud( Eigen::Vector3d(-2.1, 0, 0.0), Eigen::Vector3d(0, 0, 0), cloud2_filtered ); // 合并点云(包含空洞修复) sensor_msgs::PointCloud2 merged_msg = mergePointClouds( cloud3_filtered, cloud1_transformed, cloud2_transformed ); // 发布合并结果 merged_msg.header.stamp = ros::Time::now(); pub.publish(merged_msg); // 重置标志位 cloud1_received = false; cloud2_received = false; cloud3_received = false; } ros::spinOnce(); rate.sleep(); } return 0; }
07-11
//*********************************************************************************** //Filename: SatellitePosition.cpp // //Date Author Revison History //05/08/2017 Guled Sheikh version 1 // //*********************************************************************************** // //Copyright 2017~2018. All Rights Reserved // //*********************************************************************************** #include "SatellitePosition.h" //Computes the Euclidean distance double SatellitePosition::EucldNorm(double x, double y, double z) { double norm = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2)); return norm; } // Fucntion that returns satellite positions corrected for Earth rotation errors vector<double> SatellitePosition::EarthRot_Corr(double time, vector<double> pos) { /*...Returns rotated satellite ECEF coordinates due to Earth rotation during signal travel time /*....time represents the travel time...*/ /*....WGS 84 value of the earth's rotation rate (rad/sec)...*/ double OMEGA_e = 7.2921151467e-5; double OMEGA_tau = OMEGA_e*time; Eigen::Matrix3d R3; Eigen::Vector3d POS_ROT; Eigen::Vector3d POS(pos[0], pos[1], pos[2]); vector <double> POSITION; double R11, R12, R13, R21, R22, R23, R31, R32, R33; R11 = cos(OMEGA_tau); R21 = -sin(OMEGA_tau); R31 = 0; R12 = sin(OMEGA_tau); R22 = cos(OMEGA_tau); R32 = 0; R13 = 0; R23 = 0; R33 = 1; R3 << R11, R12, R13, R21, R22, R23, R31, R32, R33; POS_ROT = R3*POS; POSITION.push_back(POS_ROT[0]); POSITION.push_back(POS_ROT[1]); POSITION.push_back(POS_ROT[2]); return POSITION; } // Function that corrects for tropospheric effects double SatellitePosition::Tropo_Corr(vector<double> pos, vector<double> ini_pos) { Eigen::Vector3d POS(pos[0], pos[1], pos[2]); Eigen::Vector3d INI_POS(ini_pos[0], ini_pos[1], ini_pos[2]); double dtrop; double tot_p = 1013; // Mbar double pwv = 16; //Mbar double pd = tot_p - pwv; // Mbar double T = 300; // Kelvins double R = 6371e3; double sat_pos_norm = EucldNorm(pos[0], pos[1], pos[2]); double rec_pos_norm = EucldNorm(ini_pos[0], ini_pos[1], ini_pos[2]); double g = acos((POS.dot(INI_POS)) / (sat_pos_norm*rec_pos_norm)); double e = atan((sat_pos_norm*cos(g) - R) / (sat_pos_norm*sin(g))); //cout << (e*180)/ PI << endd; //cin.get(); double z = (PI / 2) - e; if (z == 0) { dtrop = (0.002277 / cos(z))*(pd + (((1255 / T) + 0.05)*pwv)); } else { dtrop = (0.002277 / cos(z))*(pd + (((1255 / T) + 0.05)*pwv) - (1.16*(pow(tan(z), 2)))); } return dtrop; } // This function removes effects of ionosphere based on the iono-free model double SatellitePosition::iono_free(double count) { double gamma = pow((1575.42 / 1227.6), 2); double P1_temp = 0.0, P2_temp = 0.0, PR_temp = 0.0, C1_temp = 0.0; // Finding the pseudoranges if (find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "P1") - RinexFile->head.obstype.begin() != 0) { ptrdiff_t pos_P1 = find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "P1") - RinexFile->head.obstype.begin(); if (pos_P1 == RinexFile->head.obstype.size()) { } else { P1_temp = RinexFile->obs.record[count][pos_P1]; } } if (find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "P2") - RinexFile->head.obstype.begin() != 0) { ptrdiff_t pos_P2 = find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "P2") - RinexFile->head.obstype.begin(); if (pos_P2 == RinexFile->head.obstype.size()) { } else { P2_temp = RinexFile->obs.record[count][pos_P2]; } } if (P2_temp != 0 && P1_temp != 0) { PR_temp = (P2_temp - (gamma*P1_temp)) / (1 - gamma); } else { ptrdiff_t pos_PR = find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "C1") - RinexFile->head.obstype.begin(); PR_temp = RinexFile->obs.record[count][pos_PR]; } return PR_temp; } // This function removes effects of ionosphere based on the Klobuchar model double SatellitePosition::klobuchar(double fi, double lambda, double elev, double azimuth, double tow) { VectorXd alfa; VectorXd beta; alfa << 9.3132e-09, 1.4901e-08, -5.9605e-08, -1.1921e-07; beta << 8.8064e+04, 4.9152e+04, -1.3107e+05, -3.2768e+05; double c = 299792458, deg2semi = 1.0 / 180.0, semi2rad = PI, deg2rad = PI / 180.0, dIon1; double a = azimuth*deg2rad; // asimuth in radians double e = elev*deg2semi; // elevation angle in semicircles double psi = 0.0137 / (e + 0.11) - 0.022; //Earth Centered angle double lat_i = fi*deg2semi + psi*cos(a); // Subionospheric lat if (lat_i > 0.416) { lat_i = 0.416; } else if (lat_i < -0.416) { lat_i = -0.416; } //Subionospheric long double long_i = lambda*deg2semi + (psi*sin(a) / cos(lat_i*semi2rad)); // Geomagnetic latitude double lat_m = lat_i + 0.064*cos((long_i - 1.617)*semi2rad); double t = 4.32e4*long_i + tow; t = fmod(t, 86400.0); // Seconds of day if (t > 86400.0) { t = t - 86400.0; } if (t < 86400.0) { t = t + 86400.0; } double sF = 1.0 + 16.0* pow((0.53 - e), 3); // Slant factor // Period of model double PER = beta(0) + beta(1)*lat_m + beta(2)* pow(lat_m, 2) + beta(3)* pow(lat_m, 3); if (PER < 72000.0) { PER = 72000.0; } double x = 2.0*PI*(t - 50400.0) / PER; // Phase of the model double AMP = alfa(0) + alfa(1) *lat_m + alfa(2) * pow(lat_m, 2) + alfa(3) * pow(lat_m, 3); // Amplitud of the model if (AMP < 0.0) { AMP = 0.0; } if (abs(x) > 1.57) { dIon1 = sF * (5.0e-9); } else { dIon1 = sF * (5.0e-9 + AMP*(1.0 - x*x / 2.0 + x*x*x*x / 24.0)); } return dIon1; } // This function computes the gps time in seconds double SatellitePosition::gpstimeCalc(double year, double month, double day, double hour, double min, double sec) { double y, m, JD, gps_week, gps_seconds; double secs_per_week = 604800; // Seconds in one week //Converts the two digit year to a four digit year. //Two digit year represents a year in the range 1980 - 2079. if (year >= 80 && year <= 99) { year = 1900 + year; } if (year >= 0 && year <= 79) { year = 2000 + year; } //Calculates the 'm' term used below from the given calendar month. if (month <= 2) { y = year - 1; m = month + 12; } if (month > 2) { y = year; m = month; } //Computes the Julian date corresponding to the given calendar date. JD = floor((365.25 * y)) + floor((30.6001 * (m + 1))) + day + ((hour + min / 60 + sec / 3600) / 24) + 1720981.5; //Computes the GPS week corresponding to the given calendar date. gps_week = floor((JD - 2444244.5) / 7); //Computes the GPS seconds corresponding to the given calendar date. gps_seconds = round(((((JD - 2444244.5) / 7) - gps_week)*secs_per_week) / 0.5)*0.5; return gps_seconds; } //This functions corrects for tropospheric effects based on initial values given in the navigation file double SatellitePosition::NMF_hyd(double sat_elev) { double A = 33.748; double B = -0.782; double A1 = 38.079; double B1 = -0.8088; double Y1 = A*pow(sat_elev, B); double Y2 = A1*pow(sat_elev, B1); double Y = Y1 + Y2; return Y; } // This function initializes the observation and navigation filenames void SatellitePosition::SetFilenames(const char * ObsFile, const char * NavFile) { size_t obs_size = strlen(ObsFile); size_t nav_size = strlen(NavFile); if (ObsFile != NULL) { strcpy(obsFile, ObsFile); } if (NavFile != NULL) { strcpy(navFile, NavFile); } obsFile[obs_size] = '\0'; navFile[nav_size] = '\0'; RinexFile = new reader(SatellitePosition::obsFile, SatellitePosition::navFile); RinexFile->rinexNAVReader(RinexFile->SV_data); } //This function opens the observation and navigation files from the environment file void SatellitePosition::OpenEnvFile(ENVI_FILE & envi_records, SatellitePosition & object1, SatellitePosition & object2) { Env_File = fopen("EnvFileGMIS.txt", "rt"); if (Env_File == NULL) perror("Error opening file"); char line[MAX_STRLEN]; fgets(line, MAX_STRLEN, Env_File); while (!feof(Env_File)) { if (sizeof(line) >= 61) { if (strstr(line, "VERSION / TYPE")) { string sline(line); // convert the line (char) to string class type sLine string token = sline.substr(4, 4); // from 4th character and 4 spaces envi_records.version = token; } if (strstr(line, "BASE FILE(OBS/NAV)")) { std::istringstream iss(line); std::vector<std::string> results((std::istream_iterator<std::string>(iss)), std::istream_iterator<std::string>()); Filename1_Obs = results[0]; Filename1_Nav = results[1]; object1.SetFilenames(Filename1_Obs.c_str(), Filename1_Nav.c_str()); } if (strstr(line, "ROVER FILE(OBS/NAV)")) { std::istringstream iss2(line); std::vector<std::string> results2((std::istream_iterator<std::string>(iss2)), std::istream_iterator<std::string>()); Filename2_Obs = results2[0]; Filename2_Nav = results2[1]; object2.SetFilenames(Filename2_Obs.c_str(), Filename2_Nav.c_str()); } if (strstr(line, "BASE FINAL COORDINATES")) { string sline(line); // convert the line (char) to string class type sLine string token = sline.substr(4, 56); // from 4th character upto 56 char cline[MAX_BYTE]; // cline is a char line strncpy(cline, token.c_str(), sizeof(cline)); cline[sizeof(cline) - 1] = 0; for (char * r = strtok(cline, " "); r; r = strtok(NULL, " ")) { double rr = atof(r); envi_records.base_final_coord.push_back(rr); } } } //......... Get a new line....................... fgets(line, MAX_STRLEN, Env_File); } } // This function computes the satellite positions and stores them in a global file void SatellitePosition::Sat_Pos(SATPOS_struct &EPOCH_DATA) { RinexFile->rinexOBSReader(RinexFile->head, RinexFile->obs, RinexFile->SENTINEL); // Read the observation file epoch_count = epoch_count + 1; vector< vector<double> > pos_rot_epoch_temp; vector< vector<double> > initial_satpos_temp; vector <double> pr_epoch_temp; vector <double> P1_epoch_temp; vector <double> P2_epoch_temp; vector <double> C1_epoch_temp; vector <double> L1_epoch_temp; vector <double> L2_epoch_temp; vector <double> pr_epoch_Iono_temp; vector <double> sat_offset_epoch_temp; vector<double> sat_elev_temp; double Tropo; reader::NAVRECORDS storer; if (RinexFile->obs.NumOfSat != 0) { double count = 0; for (int j = 0; j < RinexFile->obs.NumOfSat; j++) { // Each satellite double gamma = pow((1575.42 / 1227.6), 2); double c = 299792458; double P1_temp = 0.0, P2_temp = 0.0, PR_temp = 0.0, L1_temp = 0.0, L2_temp = 0.0, C1_temp = 0.0, TIME_temp; //reader::NAVRECORDS storer; int curPrn = RinexFile->obs.prn[count]; // Current observation satelite vehicle double time_LOGGER = std::numeric_limits<double>::max(); //search through the navigation file for (size_t k = 0; k < RinexFile->SV_data.size(); k++) { if (RinexFile->SV_data[k].PRN == curPrn) { //Compare obs prn with nav prn if (time_LOGGER > abs(RinexFile->SV_data[k].gpstime - RinexFile->obs.time)) { time_LOGGER = abs(RinexFile->SV_data[k].gpstime - RinexFile->obs.time); storer = RinexFile->SV_data[k]; } } } // Finding the pseudoranges P1 code if (find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "P1") - RinexFile->head.obstype.begin() != RinexFile->head.nobstype) { ptrdiff_t pos_P1 = find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "P1") - RinexFile->head.obstype.begin(); if (pos_P1 == RinexFile->head.obstype.size()) { } else { P1_temp = RinexFile->obs.record[j][pos_P1]; } } // Finding the pseudoranges P2 code if (find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "P1") - RinexFile->head.obstype.begin() != RinexFile->head.nobstype) { ptrdiff_t pos_P2 = find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "P1") - RinexFile->head.obstype.begin(); if (pos_P2 == RinexFile->head.obstype.size()) { } else { P2_temp = RinexFile->obs.record[j][pos_P2]; } } // Finding the pseudoranges L1 carrier if (find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "L1") - RinexFile->head.obstype.begin() != RinexFile->head.nobstype) { ptrdiff_t pos_L1 = find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "L1") - RinexFile->head.obstype.begin(); if (pos_L1 == RinexFile->head.obstype.size()) { } else { L1_temp = RinexFile->obs.record[j][pos_L1]; } } // Finding the pseudoranges L2 carrier if (find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "L2") - RinexFile->head.obstype.begin() != RinexFile->head.nobstype) { ptrdiff_t pos_L2 = find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "L2") - RinexFile->head.obstype.begin(); if (pos_L2 == RinexFile->head.obstype.size()) { } else { L2_temp = RinexFile->obs.record[j][pos_L2]; } } // Finding the pseudoranges C1 code if (find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "C1") - RinexFile->head.obstype.begin() != RinexFile->head.nobstype) { ptrdiff_t pos_C1 = find(RinexFile->head.obstype.begin(), RinexFile->head.obstype.end(), "C1") - RinexFile->head.obstype.begin(); if (pos_C1 == RinexFile->head.obstype.size()) { } else { C1_temp = RinexFile->obs.record[j][pos_C1]; } } PR_temp = iono_free(j); TIME_temp = RinexFile->obs.time - (PR_temp / c); //GPS system time at time of transmission corrected for transit time // SATELLITE POSITIONING // Constants //WGS 84 value of the earth's gravitational constant for GPS user double mu = 3.986005e14; //WGS 84 value of the earth's rotation rate (rad/sec) double OMEGA_e = 7.2921151467e-5; // Initialize necessary variables from NAV double A = pow(storer.Sqrta, 2); //Semi-major axis double toe = storer.Toe; //toe = Time of Ephemeris double deltaN = storer.DeltaN; //Delta n double Mo = storer.Mo; // Mo angle double e = storer.Eccentricity; //Orbit Eccentricity double omega = storer.omega; //omega Angle // Second Harmonic Perturbations double Cus = storer.Cus; //Latitude Correction Sinus Component double Cuc = storer.Cuc; //Latitude Correction Cosinus Component double Crs = storer.Crs; //Radius Correction Sinus Component double Crc = storer.Crc; //Radius Correction Cosinus Component double Cis = storer.Cis; //Angular Velocity double Cic = storer.Cic; //Inclination Correction Cosinus Component double IDOT = storer.IDOT; //Inclination Rate double Io = storer.Io; //Initial Inclination double OMEGA = storer.OMEGA; //OMEGA Angle double OMEGADOT = storer.OMEGADOT; //Angular Velocity double SVCB = storer.SVClockBias; //SVClockBias (sec) double SVCD = storer.SVClockDrift; //SVClockDrift (sec) double SVCDR = storer.SVClockDriftRate; //SVClockDriftRate (sec) double SAT_TIME = storer.gpstime; //double SAT_TIME = storer.SEC; double tk = TIME_temp - toe; //Time from ephemeris reference epoch // Correct tk within range of -302400 to 302400 if (tk > 302400) { tk = tk - 604800; } else if (tk < -302400) { tk = tk + 604800; } // Computed mean motion (rad/sec) double n0 = sqrt(mu / (pow(A, 3))); // Corrected mean motion double n = n0 + deltaN; //Mean anomaly double Mk = Mo + n*tk; // Keep Mk with in 360 degrees ....// Mk = rem(Mk+2*pi,2*pi); // Kepler's Equation for Eccentric Anomaly (may be solved by iteration)(radians) double Ek = Mk; double Ek0 = Mk + e*sin(Ek); double limit = 1e-11; // limit while (abs(Ek - Ek0) > limit) { Ek0 = Ek; Ek = Mk + e*sin(Ek0); } // Keep Ek with in 360 degrees.....// Ek = rem(Ek + 2 * pi, 2 * pi); // True Anomaly double Y = (sqrt(1 - pow(e, 2))*sin(Ek)) / (1 - e*cos(Ek)); double X = (cos(Ek) - e) / (1 - e*cos(Ek)); double vk = atan2(Y, X); //Argument of Latitude double Phi_k = vk + omega; double del_uk = Cus*sin(2 * Phi_k) + Cuc*cos(2 * Phi_k); // Argument of Latitude Correction double del_rk = Crs*sin(2 * Phi_k) + Crc*cos(2 * Phi_k); //Radius Correction double del_ik = Cis*sin(2 * Phi_k) + Cic*cos(2 * Phi_k); //Inclination Correction //Corrected Argument of Latitude double uk = Phi_k + del_uk; //Corrected Radius double rk = A*(1 - e*cos(Ek)) + del_rk; //Corrected Inclination double ik = Io + del_ik + IDOT*tk; //Positions in orbital plane. double xk_prime = rk*cos(uk); double yk_prime = rk*sin(uk); //Corrected longitude of ascending node double OMEGA_k = OMEGA + (OMEGADOT - OMEGA_e)*tk - OMEGA_e*toe; //Earth-fixed coordinates double xk = xk_prime*cos(OMEGA_k) - yk_prime*cos(ik)*sin(OMEGA_k); double yk = xk_prime*sin(OMEGA_k) + yk_prime*cos(ik)*cos(OMEGA_k); double zk = yk_prime*sin(ik); // Satellite position without tropo, iono and Earth rotation corrections vector <double> POSITION; //Store the Earth-fixed coordinates (satellite position xk,yk,zk of satellite k) POSITION.push_back(xk); POSITION.push_back(yk); POSITION.push_back(zk); // Satellite elevation angle calculation //--------------------------------------------------------------------------------------------------------------// Eigen::Vector3d POS(POSITION[0], POSITION[1], POSITION[2]); Eigen::Vector3d INI_POS(RinexFile->head.antpos[0], RinexFile->head.antpos[1], RinexFile->head.antpos[2]); double R = 6371e3; double sat_pos_norm = EucldNorm(POSITION[0], POSITION[1], POSITION[2]); double rec_pos_norm = EucldNorm(RinexFile->head.antpos[0], RinexFile->head.antpos[1], RinexFile->head.antpos[2]); double g = acos((POS.dot(INI_POS)) / (sat_pos_norm*rec_pos_norm)); double sat_elev = (atan((sat_pos_norm*cos(g) - R) / (sat_pos_norm*sin(g))))*(180 / PI); // in degrees sat_elev_temp.push_back(sat_elev); // store the current satellite elevation //----------------------------------------------------------------------------------------------------------------// // CUT_OFF ANGLE OF 15 DEGREES if (sat_elev >= 15) { // Realativistic Correction Term (sec) double F = -4.442807633e-10; double Del_tr = F*e*sqrt(A)*sin(Ek); // Realativistic Correction Term(sec) // Satellite Clock Errors (sec) double Del_tsv = SVCB + SVCD*(SAT_TIME - toe) + SVCDR*(pow((SAT_TIME - toe), 2)) + Del_tr; // CORRECTIONS // Range before earth rotation correction double geom_range = EucldNorm((POSITION[0] - RinexFile->head.antpos[0]), (POSITION[1] - RinexFile->head.antpos[1]), (POSITION[2] - RinexFile->head.antpos[2])); double t = (geom_range) / c; // CORRECTIONS // Earth rotation correction vector <double> POSITION_ROT = EarthRot_Corr(t, POSITION); double geom_range_corr = EucldNorm((POSITION_ROT[0] - RinexFile->head.antpos[0]), (POSITION_ROT[1] - RinexFile->head.antpos[1]), (POSITION_ROT[2] - RinexFile->head.antpos[2])); pos_rot_epoch_temp.push_back(POSITION_ROT); double check_pseudo = (PR_temp - geom_range_corr) + c*(Del_tsv); // Tropo correction //double dtropo = NMF_hyd(sat_elev); // Niell Mapping Function double dtropo = Tropo_Corr(POSITION_ROT, RinexFile->head.antpos); // SAASTAMOINEN //Tropo = dtropo; // Corrected pseudorange for iono only pr_epoch_Iono_temp.push_back(PR_temp); // Corrected pseudorange for iono and tropo //double Corr_Pseudo = PR_temp - dtropo; doing tropo correc in kalman!!!!! double Corr_Pseudo = PR_temp - dtropo; pr_epoch_temp.push_back(Corr_Pseudo); P1_epoch_temp.push_back(P1_temp); P2_epoch_temp.push_back(P2_temp); C1_epoch_temp.push_back(C1_temp); L1_epoch_temp.push_back(L1_temp); L2_epoch_temp.push_back(L2_temp); sat_offset_epoch_temp.push_back(Del_tsv); initial_satpos_temp.push_back(POSITION); count = count + 1; } else { //remove the satellite from the prn vector count = count; RinexFile->obs.prn.erase(RinexFile->obs.prn.begin() + count); } } EPOCH_DATA.Sat_elev = sat_elev_temp; // Satellite elevations for the epoch EPOCH_DATA.pos_rot_epoch = pos_rot_epoch_temp; // corrected satellite positions for the epoch EPOCH_DATA.Initial_SatPos = initial_satpos_temp; EPOCH_DATA.pr_epoch = pr_epoch_temp; // Corrected pseudorange EPOCH_DATA.P1_epoch = P1_epoch_temp; EPOCH_DATA.P2_epoch = P2_epoch_temp; EPOCH_DATA.C1_epoch = C1_epoch_temp; EPOCH_DATA.L1_epoch = L1_epoch_temp; EPOCH_DATA.L2_epoch = L2_epoch_temp; EPOCH_DATA.pr_epoch_iono = pr_epoch_Iono_temp; EPOCH_DATA.sat_offset_epoch = sat_offset_epoch_temp; // satellite clock offset } } 讲解该代码
08-24
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值