绘制lidar点云pose

输入点云序列,得到点云的运动轨迹,并生成周围点云拼接得到的点云地图

#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/point_cloud2.hpp>
#include <geometry_msgs/msg/transform_stamped.hpp>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl_conversions/pcl_conversions.h>#include <iostream>
#include <pcl/registration/icp.h>
#include <pcl/registration/ndt.h>
#include <pcl/common/common.h>
#include <pcl/common/transforms.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/kdtree/kdtree_flann.h>
//打印矩阵,临时用,就不讲究float和double的通用了,也可以template
void printMat4(Eigen::Matrix4f mat)
{std::cout<<"lidar matrix is :"<<std::endl;for(int i=0;i<mat.rows();i++){for(int j=0;j<mat.cols();j++){std::cout<<mat(i,j)<<" , ";}std::cout<<std::endl;}
}
//保存轨迹,用的是变换矩阵的3*4子矩阵,按照行主序展开。用逗号做分隔。
void writePoseList(const std::vector<Eigen::Matrix4d>& matrices, const std::string& filename)
{std::ofstream file(filename);if (!file.is_open()){std::cout << "Failed to open file: " << filename << std::endl;return;}// 写入每个矩阵到文件for (size_t i = 0; i < matrices.size(); i++){const Eigen::Matrix4d& matrix = matrices[i];// 写入序号file << i + 1 << ",";// 写入矩阵元素,不写入最后一行for (int row = 0; row < 3; row++){for (int col = 0; col < 4; col++){file << matrix(row, col);// 在每个元素之间添加逗号,除了最后一个元素if (row != 2 || col != 3)file << ",";}}file << std::endl;}file.close();
}
//读取外参imu2lidar
Eigen::Matrix4d loadExtrinsic()
{Eigen::Matrix4d extrinsic;extrinsic << 0.70710678, 0.70710678, 0.0, -1.477,-0.70710678, 0.70710678, 0.0, -0.77,0.0, 0.0, 1.0, -0.66,0.0, 0.0, 0.0, 1.0;return extrinsic;
}
//读取imu的变换矩阵的3*4子矩阵,按照行主序展开。用 空格做分隔。得到一个imu的按照时间排序的pose-position信息(不是pp的增量,是相对起点坐标系的结果)
std::vector<Eigen::Matrix4d> loadIMU()
{std::vector<Eigen::Matrix4d> imu_pp;std::string filename = "/home/apollo/zr/code/imu_pose_0914_nn.txt";std::ifstream file(filename);if (!file.is_open()){std::cout << "Failed to open file: " << filename << std::endl;return imu_pp;}std::string line;while (std::getline(file, line)){Eigen::Matrix4d matrix = Eigen::Matrix4d::Identity();double value;std::stringstream ss(line);// 读取每行的值并赋给矩阵for (int i = 0; i < 13; i++){ss >> value;if(i==0)continue;matrix((i-1) / 4, (i-1) % 4) = value;}imu_pp.push_back(matrix);}file.close();return imu_pp;
}
//src到tgt的icp匹配,得到src点云到icp点云的变换矩阵
Eigen::Matrix4f icp_calib(pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_src, pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_tgt)
{// pcl::PointCloud<pcl::PointXYZI>::Ptr cloudAll(//     new pcl::PointCloud<pcl::PointXYZI>);// *cloudAll = *cloud_src + *cloud_tgt;// pcl::io::savePCDFileBinary(path_out+"All.pcd", *cloudAll);double icpMaxCorrespondenceDistance_=3;//100int icpMaximumIterations_=100;//100double icpTransformationEpsilon_=1e-10;double icpEuclideanFitnessEpsilon_=0.001;double icpFitnessScoreThresh_=0.3;//0.3Eigen::Matrix4f transInit = Eigen::Matrix4f::Identity();pcl::IterativeClosestPoint<pcl::PointXYZI, pcl::PointXYZI> icp;icp.setMaxCorrespondenceDistance(icpMaxCorrespondenceDistance_); icp.setMaximumIterations(icpMaximumIterations_);icp.setTransformationEpsilon(icpTransformationEpsilon_);icp.setEuclideanFitnessEpsilon(icpEuclideanFitnessEpsilon_);icp.setInputSource(cloud_src);icp.setInputTarget(cloud_tgt);pcl::PointCloud<pcl::PointXYZI>::Ptr transCurrentCloudInWorld(new pcl::PointCloud<pcl::PointXYZI>());icp.align(*transCurrentCloudInWorld,transInit.matrix());//迭代效果不理想,原因尚未定位到???Eigen::Matrix4f transWorldCurrent = Eigen::Matrix4f::Identity();if (icp.hasConverged() == false ) //|| icp.getFitnessScore() > icpFitnessScoreThresh_{std::cout << "ICP locolization failed    the score is   " << icp.getFitnessScore() << std::endl;return transWorldCurrent;} else {transWorldCurrent = icp.getFinalTransformation();// printMat4(transWorldCurrent);}return transWorldCurrent;
}
int main(int argc, char** argv)
{//***************load imu****************std::vector<Eigen::Matrix4d> imu_poses = loadIMU();//***************load extrinsic****************Eigen::Matrix4d extrinsic_mct2lidar;extrinsic_mct2lidar = loadExtrinsic();std::cout << "extrinsic_mct2lidar:\n" << extrinsic_mct2lidar << std::endl;Eigen::Matrix4d extrinsic_lidar2mct = extrinsic_mct2lidar.inverse();std::cout << "extrinsic_lidar2mct:\n" << extrinsic_lidar2mct << std::endl;std::string path = "/home/apollo/zr/code/genFeature0914/surf";Eigen::Matrix4d lidarPose = Eigen::Matrix4d::Identity();std::vector<Eigen::Matrix4d> lidarPoseList;pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_all(new pcl::PointCloud<pcl::PointXYZI>);for(int count=26;count<325;count++){//***************load lidar****************pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_src(new pcl::PointCloud<pcl::PointXYZI>);std::string pcd1 =path+std::to_string(count+1)+".pcd";std::cout << "pcd_file: " << count << "\n";if (pcl::io::loadPCDFile(pcd1, *cloud_src) < 0) {std::cout << "cannot open pcd_file: " << pcd1 << "\n";exit(1);}pcl::PointCloud<pcl::PointXYZI>::Ptr cloud_tgt(new pcl::PointCloud<pcl::PointXYZI>);std::string pcd2 =path+std::to_string(count)+".pcd";if (pcl::io::loadPCDFile(pcd2, *cloud_tgt) < 0) {std::cout << "cannot open pcd_file: " << pcd2 << "\n";exit(1);}//***************process icp****************Eigen::Matrix4f Rt_f = icp_calib(cloud_src,cloud_tgt);Eigen::Matrix4d Rt = Rt_f.cast<double>();lidarPose = lidarPose * Rt;lidarPoseList.push_back(lidarPose);pcl::PointCloud<pcl::PointXYZI>::Ptr currentFeatureCloudInWorld(new pcl::PointCloud<pcl::PointXYZI>);pcl::transformPointCloud (*cloud_src, *currentFeatureCloudInWorld, lidarPose);*cloud_all = *cloud_all+*currentFeatureCloudInWorld;}//保存lidar轨迹writePoseList(lidarPoseList, "/home/apollo/zr/code/pose_lidar0914.csv");//保存lidar建图pcl::io::savePCDFileBinary("/home/apollo/zr/code/lidar0914map.pcd", *cloud_all);return 0;
}

读取csv文件绘制行主序展开3*4位姿图

import numpy as np
from scipy.spatial.transform import Rotation
import csv
import os
from datetime import datetime
import time
#读取csv文件
def readcsv_convert(csv_file):#得到datas 二维listdatas = []with open(csv_file, 'r') as file:for line in file:line = line.strip().split(',')datas.append(list(map(float, line[1:])))#得到csv_data_list 一维list,每个元素都是矩阵形式# csv_data_list=[]# for data in datas:#     # 将列表转为 3x4 的矩阵#     matrix = np.reshape(data, (3, 4))#     # 创建一个 4x4 的旋转平移矩阵#     transform_matrix = np.identity(4)#     # 将矩阵的前三行赋值为输入的矩阵,最后一行为 [0, 0, 0, 1]#     transform_matrix[:3, :] = matrix#     transform_matrix[3, :] = [0, 0, 0, 1]#     # print(transform_matrix)#     csv_data_list.append(transform_matrix)return datas#保存二维list
def data_to_txt(txt_file,data_list):with open(txt_file, 'w') as txt_file:for item in data_list:# txt_file.write(str(item) + '\n')line = ','.join(map(str, item))txt_file.write(line + '\n')
#保存x,y,theta的pose-position增量或者pose-position
# def data_to_txt_plane(txt_file,x,y,theta):
#     with open(txt_file, 'w') as txt_file:
#         for i in range(len(x)):
#             txt_file.write(f'{x[i]}, {y[i]}, {theta[i]}\n')#从变换矩阵里提取平面运动信息:X,Y,Theta
def redrawMatrix2XYTheta(data):# 提取位置信息x_in = [row[3] for row in data]y_in = [row[7] for row in data]import numpy as npfrom scipy.spatial.transform import Rotation# 转换旋转矩阵为欧拉角euler_angles_list = []for row in data:# 提取相关数据rotation_matrix = np.array(row).reshape(3, 4)sub_matrix = rotation_matrix[:, :3]# 创建Rotation对象rotation = Rotation.from_matrix(sub_matrix)# 将旋转矩阵转换为欧拉角euler_angles = rotation.as_euler('xyz', degrees=True)euler_angles_list.append(euler_angles)theta_in = [row[2] for row in euler_angles_list]return x_in,y_in,theta_in
#绘制平面运动信息,输入为x,y,theta的全局值,不是增量值
def draw(x,y,theta,lenOfDirection):import matplotlib.pyplot as pltplt.plot(x, y, 'bo')# 绘制点的方向for xi, yi, ti in zip(x, y, theta):dx = lenOfDirection * np.sin(np.deg2rad(ti))dy = lenOfDirection * np.cos(np.deg2rad(ti))plt.arrow(xi, yi, dx, dy, head_width=0.2, color='red')# 设置图形坐标轴范围# plt.xlim(min(x) -1, max(x) + 1)# plt.ylim(min(y) -1, max(y) + 1)plt.xlim(-15, 15)plt.ylim(-45, 5)# 显示图形plt.show()#齐次化函数 :3*4->4*4
def homogenize_matrix(matrix):new_matrix = [row + [0] for row in matrix]  # 在每一行末尾添加0new_row = [0] * 4  # 创建全为0的行new_row[3] = 1  # 在最后一列添加1new_matrix.append(new_row)  # 添加到新的矩阵return new_matrix# # 示例用法
csv_file = 'pose_lidar0914.csv'  # 输入的 CSV 文件名
csv_data_list = readcsv_convert(csv_file)
# x_mct,y_mct,theta_mct = redrawMatrix2XYTheta([row[1:] for row in csv_data_list])
x_mct,y_mct,theta_mct = redrawMatrix2XYTheta(csv_data_list)
# drawGPS(RPY_n, gps_n)
draw(x_mct,y_mct,theta_mct,0.9)
# data_to_txt_plane("mct_pose.csv",x_mct,y_mct,theta_mct)

#rpy转旋转矩阵 输出csv文件

import numpy as np
from scipy.spatial.transform import Rotation
import csv
import os
from datetime import datetime
import timedef euler_to_rotation_matrix(roll, pitch, yaw):# 将角度转换为弧度roll_rad = np.deg2rad(roll)pitch_rad = np.deg2rad(pitch)yaw_rad = np.deg2rad(yaw)# 输入已经是弧度# roll_rad = roll# pitch_rad = pitch# yaw_rad = yaw# 创建旋转对象并进行转换r = Rotation.from_euler('xyz', [roll_rad, pitch_rad, yaw_rad], degrees=False)rotation_matrix = r.as_matrix()# 验证 : 使用 numpy.linalg 模块中的函数将旋转矩阵转换为欧拉角# euler_angles = np.degrees(np.around(np.array([#     np.arctan2(rotation_matrix[2, 1], rotation_matrix[2, 2]),#     np.arctan2(-rotation_matrix[2, 0], np.sqrt(rotation_matrix[2, 1]**2 + rotation_matrix[2, 2]**2)),#     np.arctan2(rotation_matrix[1, 0], rotation_matrix[0, 0])# ]), decimals=2))return rotation_matrix#GPS转墨卡托,注意此时坐标系就是墨卡托系了,既不是imu也不是gnss了
def gps_to_Mercator(x,y):a = 6378.137e = 0.0818192k0 = 0.9996E0 = 500N0 = 0ret = [0,0]zoneNum = int(x / 6) + 31lamda0 = (zoneNum - 1) * 6 - 180 + 3lamda0 = lamda0 * np.pi / 180.0phi = y * np.pi / 180.0lamda = x * np.pi / 180.0v = 1.0 / np.sqrt(1 - np.power(e,2) * np.power(np.sin(phi),2))A = (lamda - lamda0) * np.cos(phi)T = np.tan(phi) * np.tan(phi)C = np.power(e,2) * np.cos(phi) * np.cos(phi) / (1 - np.power(e,2))s = (1 - np.power(e,2) / 4.0 - 3 * np.power(e,4) / 64.0 - 5 * np.power(e,6) / 256.0)* phi \- (3 * np.power(e,2) / 8.0 + 3 * np.power(e,4) / 32.0 + 45 * np.power(e,6) / 1024.0) * np.sin(2 * phi) \+ (15 * np.power(e,4) / 256.0 + 45 * np.power(e,6) / 1024.0) * np.sin(4 * phi) \- 35 * np.power(e,6) / 3072.0 * np.sin(6 * phi)UTME = E0 + k0 * a * v * (A + (1 - T + C) * np.power(A,3) / 6 + (5 - 18 * T + np.power(T,2)) * np.power(A,5) / 120)UTMN = N0 + k0 * a * (s + v * np.tan(phi) * (np.power(A,2) / 2 + (5 - T + 9 * C + 4 * np.power(C,2)) * np.power(A,4) \/ 24  + (61 - 58 * T + np.power(T,2))* np.power(A,6) / 720.0))ret[0] = UTME * 1000ret[1] = UTMN * 1000return ret#读取lidar数据的时间戳,从实际时间格式转unix格式
def read_lidar_timestamp(file_dir):files = os.listdir(file_dir)#files.sort(key=lambda x: int(x.replace("lidar6611_","").split('_')[0]))files.sort(key=lambda x: int(x.replace("lidar6600_","")[0]))Length_lidar = len(files)lidar_stamp = np.zeros((Length_lidar))i = 0char_fix = '_'list_lidar_time = []for Num in files:temp = Num.split(char_fix)[-1]list_lidar_time.append(temp.replace(".pcd",""))#使用 datetime.strptime 函数将时间字符串 list_lidar_time[i] 转换为 datetime 对象。strptime 函数使用给定的格式字符串 "%Y-%m-%d-%H-%M-%S.%f" 解析时间字符串,将其转换为 datetime 对象,并将结果赋给 time_lidar 变量。time_lidar = datetime.strptime(list_lidar_time[i],"%Y-%m-%d-%H-%M-%S.%f")#将 datetime 对象 time_lidar 转换为时间戳。首先,time_lidar.timetuple() 函数返回 time.struct_time 对象,表示 datetime 对象的日期和时间部分。然后,time.mktime 函数将 time.struct_time 对象转换为秒数的时间戳。接下来,将时间戳乘以 1000.0,然后加上微秒部分的毫秒表示 time_lidar.microsecond / 1000.0。最后,将结果转换为整数,并将其赋值给 lidar_stamp[i] 变量。lidar_stamp[i] = int(time.mktime(time_lidar.timetuple()) * 1000.0 + time_lidar.microsecond / 1000.0)i = i+1return lidar_stamp#读取imu-gnss数据的时间戳,从实际时间格式转unix格式
def read_gps_timestamp(list_gpstime):gps_stamp = np.zeros((len(list_gpstime)))for k in range(0,len(list_gpstime)):   time_gps = datetime.strptime(list_gpstime[k],"%Y/%m/%d %H:%M:%S:%f")      gps_stamp[k] = int(time.mktime(time_gps.timetuple()) * 1000.0 + time_gps.microsecond / 1000.0)return gps_stamp#插值
def interpolation(lidar_stamp, gps_stamp, RPY_o, gps_o):length_lidar = len(lidar_stamp)length_gps = len(gps_stamp)RPY = np.zeros((3,length_lidar))gps = np.zeros((3,length_lidar))j = 0for m in range(0, length_lidar):for j in range(j,length_gps):if lidar_stamp[m] <= gps_stamp[j]:diff_time = gps_stamp[j]-gps_stamp[j-1]diff_lg = abs(lidar_stamp[m] - gps_stamp[j])diff_gl = abs(gps_stamp[j-1] - lidar_stamp[m])frac_gl = diff_lg/diff_timefrac_lg = diff_gl/diff_timeRPY[0,m] = frac_gl*RPY_o[0,j-1]+frac_lg*RPY_o[0,j]RPY[1,m] = frac_gl*RPY_o[1,j-1]+frac_lg*RPY_o[1,j]RPY[2,m] = frac_gl*RPY_o[2,j-1]+frac_lg*RPY_o[2,j]gps[0,m] = frac_gl*gps_o[0,j-1]+frac_lg*gps_o[0,j]gps[1,m] = frac_gl*gps_o[1,j-1]+frac_lg*gps_o[1,j]gps[2,m] = frac_gl*gps_o[2,j-1]+frac_lg*gps_o[2,j] break   return RPY, gpscsv_data_list=[]
# 读取csv文件并将gnss坐标系转换为墨卡托坐标系
def readcsv_convert(csv_file,file_dir):length_gps = len(open(csv_file).readlines())-1offset = np.zeros((3,length_gps))ret_c = np.zeros((3,length_gps))gps_o = np.zeros((3,length_gps))RPY_o = np.zeros((3,length_gps))list_gpstime = []n = 0with open(csv_file, 'r') as csv_file:reader = csv.reader(csv_file)next(reader)for row in reader:  list_gpstime.append(row[0])       gps_o[0,n] = row[2]gps_o[1,n] = row[1]gps_o[2,n] = row[3]RPY_o[0,n] = row[4]RPY_o[1,n] = row[5]RPY_o[2,n] = row[6]n = n+1csv_file.closegps_stamp = read_gps_timestamp(list_gpstime)lidar_stamp = read_lidar_timestamp(file_dir)[RPY_n, gps_n] = interpolation(lidar_stamp, gps_stamp, RPY_o, gps_o)for p in range(0,RPY_n.shape[1]):rotation_matrix = euler_to_rotation_matrix(RPY_n[0,p], RPY_n[1,p], RPY_n[2,p])ret = gps_to_Mercator(gps_n[0,p], gps_n[1,p])ret_c[0,p] = ret[0]ret_c[1,p] = ret[1]ret_c[2,p] = gps_n[2,p]flattened_matrix = rotation_matrix.flatten(order='C').tolist() #行主序if(p!=0):offset[0,p] = ret_c[0,p]-ret_c[0,0]offset[1,p] = ret_c[1,p]-ret_c[1,0]offset[2,p] = ret_c[2,p]-ret_c[2,0] csv_data_list.append([lidar_stamp[p],flattened_matrix[0],flattened_matrix[1],flattened_matrix[2], offset[0,p],flattened_matrix[3],flattened_matrix[4],flattened_matrix[5],offset[1,p],flattened_matrix[6],flattened_matrix[7],flattened_matrix[8],offset[2,p]])return RPY_n, gps_n,csv_data_list#保存pp矩阵
def data_to_txt(txt_file,data_list):with open(txt_file, 'w') as txt_file:for item in data_list:# txt_file.write(str(item) + '\n')line = ','.join(map(str, item))txt_file.write(line + '\n')
# 保存x,y,theta
def data_to_txt_plane(txt_file,x,y,theta):with open(txt_file, 'w') as txt_file:for i in range(len(x)):txt_file.write(f'{x[i]}, {y[i]}, {theta[i]}\n')# 从pp矩阵中提取x,y,theta
def redrawMCT(data):# 提取位置信息x_in = [row[3] for row in data]y_in = [row[7] for row in data]import numpy as npfrom scipy.spatial.transform import Rotation# 转换旋转矩阵为欧拉角euler_angles_list = []for row in data:# 提取相关数据rotation_matrix = np.array(row).reshape(3, 4)sub_matrix = rotation_matrix[:, :3]# 创建Rotation对象rotation = Rotation.from_matrix(sub_matrix)# 将旋转矩阵转换为欧拉角euler_angles = rotation.as_euler('xyz', degrees=True)euler_angles_list.append(euler_angles)theta_in = [row[2] for row in euler_angles_list]return x_in,y_in,theta_in# 绘制gps
def drawGPS(RPY_n, gps_n):x=[ele*1e7-1187744343.4 for ele in gps_n[0]]y=[ele*1e7-319735719.5 for ele in gps_n[1]]theta=[ele for ele in RPY_n[2]]print(x[0])print(y[0])draw(x,y,theta,50)#绘制坐标和方向
def draw(x,y,theta,lenOfDirection):import matplotlib.pyplot as pltplt.plot(x, y, 'bo')# 绘制点的方向for xi, yi, ti in zip(x, y, theta):dx = lenOfDirection * np.sin(np.deg2rad(ti))dy = lenOfDirection * np.cos(np.deg2rad(ti))plt.arrow(xi, yi, dx, dy, head_width=0.2, color='red')# 设置图形坐标轴范围plt.xlim(min(x) -1, max(x) + 1)plt.ylim(min(y) -1, max(y) + 1)# plt.xlim(min(x) -1, max(x) + 1)# plt.ylim(min(x) -1, max(x) + 1)# 显示图形plt.show()# 齐次化
def homogenize_matrix(matrix):new_matrix = [row + [0] for row in matrix]  # 在每一行末尾添加0new_row = [0] * 4  # 创建全为0的行new_row[3] = 1  # 在最后一列添加1new_matrix.append(new_row)  # 添加到新的矩阵return new_matrix#转换到lidar坐标系
def cvt2LidarPose(matrix1,imupose):# 提取位置信息x_in = []y_in = []import numpy as npfrom scipy.spatial.transform import Rotation# 转换旋转矩阵为欧拉角euler_angles_list = []rotation_matrix = np.array(imupose[0]).reshape(3, 4)imupose_homo = homogenize_matrix(rotation_matrix)print(matrix1)print(imupose_homo)lidar_pose1 = np.dot(matrix1, imupose_homo)lidar_pose = np.dot(rotation_matrix, matrix1)# lidar_pose = rotation_matrix*matrix1sub_matrix = lidar_pose[:3, :3]# print('lidar_pose:')# print(lidar_pose)# print('lidar_pose1:')# print(lidar_pose1)# print(sub_matrix)# rotation = Rotation.from_matrix(sub_matrix)# euler_angles = rotation.as_euler('xyz', degrees=True)# print(euler_angles)for row in imupose:# 提取相关数据rotation_matrix = np.array(row).reshape(3, 4)lidar_pose = np.dot(rotation_matrix, matrix1)# lidar_pose = rotation_matrix*matrix1sub_matrix = lidar_pose[:3, :3]# print(rotation_matrix)# print(sub_matrix)# 创建Rotation对象rotation = Rotation.from_matrix(sub_matrix)# 将旋转矩阵转换为欧拉角euler_angles = rotation.as_euler('xyz', degrees=True)euler_angles_list.append(euler_angles)x_in.append(lidar_pose[0,3])y_in.append(lidar_pose[1,3])theta = [row[2] for row in euler_angles_list]x=x_iny=y_inreturn x,y,theta# # 示例用法
csv_file = 'lidar_imu_0914.csv'  # 输入的 CSV 文件名
file_dir = "lidar_0914"
txt_file = 'imu_pose_0914.csv'  # 输出的 TXT 文件名
RPY_n, gps_n,csv_data_list = readcsv_convert(csv_file, file_dir)
data_to_txt(txt_file,csv_data_list)
x_mct,y_mct,theta_mct = redrawMCT([row[1:] for row in csv_data_list])
# drawGPS(RPY_n, gps_n)
draw(x_mct,y_mct,theta_mct,0.5)
data_to_txt_plane("mct_pose.csv",x_mct,y_mct,theta_mct)import math
# 将角度转换为弧度
angle_rad = math.radians(45)
# 计算正弦值
sin45 = math.sin(angle_rad)
cos45 = math.cos(angle_rad)
# imu2lidar
# matrix2 = np.array([[cos45, sin45, 0, -1.477], [sin45, -cos45, 0, -0.77],[0, 0, -1, -0.66],[0, 0, 0, 1]])
# mct2lidar  注意imupose已经转到MCT下了,用的mct的pose,所以只需要从mct转到lidar下的外参
matrix2 = np.array([[cos45, sin45, 0, -1.477], [-sin45, cos45, 0, -0.77],[0, 0, 1, -0.66],[0, 0, 0, 1]])
matrix1 = np.linalg.inv(matrix2)
print("imu2lidar:")
print(matrix2)
print("lidar2imu:")
print(matrix1)
x_lidar,y_lidar,theta_lidar = cvt2LidarPose(matrix1,[row[1:] for row in csv_data_list])
draw(x_lidar,y_lidar,theta_lidar,0.5)
data_to_txt_plane("lidar_pose.csv",x_lidar,y_lidar,theta_lidar)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/89132.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

(数组/字符串) 380. O(1) 时间插入、删除和获取随机元素 ——【Leetcode每日一题】

❓ 380. O(1) 时间插入、删除和获取随机元素 难度&#xff1a;中等 实现 RandomizedSet 类&#xff1a; RandomizedSet() 初始化 RandomizedSet 对象bool insert(int val) 当元素 val 不存在时&#xff0c;向集合中插入该项&#xff0c;并返回 true &#xff1b;否则&#x…

Fortran IMSL库申请学生许可安装

最近使用IMSL想求个定积分&#xff0c;发现之前用的imsl7.0不支持&#xff0c;会说明许可证已经过期&#xff0c;不得不自己申请一个许可。 首先是之前的blog&#xff1a;VS2022 Fortran 配置IMSL库 这次自己申请了一个学生许可证&#xff0c;大致需要学校邮箱&#xff0c;学…

YUM 升级 PHP7

文章目录 YUM 升级 PHP71. 查看当前 PHP 信息2. YUM 安装 PHP73. 查看 PHP 版本4. 启动PHP-FPM YUM 升级 PHP7 参考地址&#xff1a;网站地址 参考地址&#xff1a;网站地址 1. 查看当前 PHP 信息 # 查看 PHP 版本信息 php -v# 查看 yum 源中 PHP 信息 yum list | grep php2. …

(c语言)数组的排序插入和删除

#include<stdio.h> void PaiXu(int arr[11]) //排序 { int i, j 0; for (i 0; i < 10; i) { for (j 0; j < 10 - i-1; j) { if (arr[j] > arr[j 1]) { int t arr[j]; …

python经典百题之static定义静态变量的方法

题目: 学习 static 定义静态变量 程序分析 在Python中&#xff0c;“static”&#xff08;静态变量&#xff09;的概念通常与类的属性相关联。虽然Python没有严格的静态变量概念&#xff0c;但可以通过类属性或模块级变量来模拟静态变量的功能。我们将探讨三种不同的方法来模…

Kafka-UI

有多款kafka管理应用&#xff0c;目前选择的是github上star最多的UI for Apache Kafka。 关于 To run UI for Apache Kafka, you can use either a pre-built Docker image or build it (or a jar file) yourself. UI for Apache Kafka is a versatile, fast, and lightweight…

工作中Git管理项目和常见问题处理

工作中Git管理项目和常见问题处理 Git仓库的管理方式为什么会出现无法push到线上处理方法 Git仓库的管理方式 共用统一仓库,不同开发人员使用不同分支 步骤 下载代码 git clone <url>查看分支 git branch创建并切换分支 git checkout -b dev分支名称保持和远程分支一…

代码随想录算法训练营第五十天 | 123.买卖股票的最佳时机III 188. 买卖股票的最佳时机 IV

1. 买卖股票的最佳时机 III 123. 买卖股票的最佳时机 III - 力扣&#xff08;LeetCode&#xff09; * 定义 5 种状态: * 0: 没有操作, 1: 第一次买入, 2: 第一次卖出, 3: 第二次买入, 4: 第二次卖出 class Solution {public int maxProfit(int[] prices) {int length prices.l…

8.2 Jmeter if控制器使用

前提&#xff1a;jmeter脚本需要用到if控制器&#xff0c;if判断如果查询不到&#xff0c;则去新增。 1、添加if控制器 线程组-->逻辑控制器-->如果(if)控制器 1&#xff09;、Expression (must evaluate to true or false) &#xff1a;表达式&#xff08;值必须是tru…

程序开发常用在线工具汇总

菜鸟工具# https://c.runoob.com/ 编码# ASCII码# https://www.habaijian.com/ 在线转换# https://www.107000.com/T-Ascii/http://www.ab126.com/goju/1711.html Base64# 在线转换# https://www.qqxiuzi.cn/bianma/base64.htmhttp://www.mxcz.net/tools/Unicode.aspx …

计算机视觉与深度学习-图像分割-视觉识别任务03-实例分割-【北邮鲁鹏】

目录 参考定义Mark R-CNN结构思路Mask R-CNN训练阶段使用的Mask样例Mask R-CNN实例分割结果Mask R-CNN检测姿态 参考 论文题目&#xff1a;Mask R-CNN 论文链接&#xff1a;论文下载 论文代码&#xff1a;Facebook代码链接&#xff1b;Tensorflow版本代码链接&#xff1b; K…

用AI解决量子学问题

3 人工智能用于量子力学 在这一部分中&#xff0c;我们提供了有关如何设计高级深度学习方法以有效学习神经波函数的技术评述。在第3.1节中&#xff0c;我们概述了一般情况下定义和解决量子多体问题的方法。在第3.2节中&#xff0c;我们介绍了学习量子自旋系统基态的方法。在第…

4G工业路由器高效数据传输助力光伏发电站管理

光伏发电站是能源产业中一种利用太阳能技术将光转化为电能的常见设施。随着物联网技术与环保能源的不断进步和应用的普及&#xff0c;光伏发电站的管理也变得更加便捷高效。 光伏发电站结合4G工业路由器实现远程监控管理&#xff0c;并用于采集发电站中的传感器数据和监控信息…

Ubuntu 安装Kafka

在本指南中&#xff0c;我们将逐步演示如何在 Ubuntu 22.04 上安装 Apache Kafka。 在大数据中&#xff0c;数以百万计的数据源生成了大量的数据记录流&#xff0c;这些数据源包括社交媒体平台、企业系统、移动应用程序和物联网设备等。如此庞大的数据带来的主要挑战有两个方面…

BUUCTF:[MRCTF2020]套娃

查看源码发现 PHP非法参数名传参问题&#xff0c;详细请参考我的这篇文章&#xff1a;谈一谈PHP中关于非法参数名传参问题 正则这里绕过使用%0a换行符绕过&#xff0c;payload: /?b.u.p.t23333%0a 得到下一步信息&#xff1a;secrettw.php 注释中的是JsFuck&#xff0c;用这…

ES6新增属性

13.ES6 1.json概述 1.什么是json 一种轻量级的数据格式键必须带双引号值如果是字符串,必须带双引号 2.json能做什么 进行网络传输,其他语言也支持json配置文件 3.json注意点 json里面不能写注释值如果是字符串,必须带引号,值如果是字符串,也必须加不能到json的后面加分号…

如何快速重置模型原点

1、什么是模型原点&#xff1f; 模型原点是三维建模中的概念&#xff0c;它是指在一个虚拟三维空间中确定的参考点。模型原点通常位于模型的几何中心或基本组件的中心位置。如图所示&#xff1a; 可以看到模型的原点在模型的几何中心 2、模型原点的作用 知道了什么是模型原点&…

微服务保护

1.初识Sentinel 1.1.雪崩问题及解决方案 1.雪崩问题 微服务中&#xff0c;服务间调用关系错综复杂&#xff0c;一个微服务往往依赖于多个其它微服务。 如图&#xff0c;如果服务提供者I发生了故障&#xff0c;当前的应用的部分业务因为依赖于服务I&#xff0c;因此也会被阻塞…

问题记录1

问题1 int* twoSum(int* nums, int numsSize, int target, int* returnSize){int i 0, j 0;int numlist[2];for (i 0; i < numsSize; i){for (j 0; j < numsSize; j) {if (target nums[i] nums[j]) {numlist[0] nums[i];numlist[1] nums[j];*returnSize 2;retu…

【C++入门指南】C如何过渡到C++?祖师爷究竟对C++做了什么?

【C入门指南】C如何过渡到C&#xff1f;祖师爷究竟对C做了什么&#xff1f; 前言一、命名空间1.1 命名空间的定义1.2 命名空间使用 二、C输入、输出2.1 std命名空间的使用惯例 三、缺省参数3.1 缺省参数的定义3.2 缺省参数分类 四、函数重载4.1 函数重载概念4.2 C支持函数重载的…