• ROS_坐标变换_PCD世界坐标系<—>自车坐标系


    坐标系统

    ROS坐标变换
     ROS静态坐标变换和动态坐标变换
      tf:TransForm Frame,坐标变换
       通过右手坐标系来标定的 
     	  
     1. 静态坐标变换
     	两个物体之间的坐标变换是 固定的时     采用静态坐标变换
    	 雷达坐标系和车身坐标系
     2. 动态坐标变换
     	两个物体之间的坐标变换是 随时间变换的 采用动态坐标变换	
          车自身坐标系和世界坐标系相对位置是移动的		
     
     geometry_msgs/TransformStamped用于传输 坐标系相关位置信息,
     geometry_msgs/PointStamped    用于传输 某个坐标系内坐标点的信息
    

    变化规范

    自身坐标系之FLU坐标:X轴向前,Y轴向左,Z轴向上
        FLU - 相对于自身。 头朝向为Forword(X), 左边为Left(Y), 顶朝向为Up(Z)
        ENU - 相对于世界中的东北天(XYZ)
    	世界坐标系之ENU坐标:X轴向东,Y轴向北,Z轴向上
        世界坐标系之NWU坐标:X轴向北,Y轴向西,Z轴向上(这个坐标系最符合人类想象)
    TX_I_V   I - imu                 
    TX_S_V   S - sensor  <其他传感器 毫米波雷达等>
    TX_L_S   L - lidar
    TX_C_S	 C - camera
    TX_L_C   Transformation from LiDAR to Camera frame
    TX_Li_L  the i-th lidar in LiDAR frame
    TX_Ci_C
    
    L S C 是虚拟的,是同一个点
    Li  实体激光雷达
    Ci  实体相机
    

    图像的标定参数

    内参: camera_matrix 是3x3的内参矩阵
    畸变系数: distortion_coefficients 是5个畸变纠正参数
    外参:变换矩阵=  平移矩阵 加旋转矩阵(四元数)
     Intrinsics & Extrinsics
     从相机坐标系转换到像素坐标系中,相机内参的作用
     从世界坐标系转换到相机坐标系中,相机外参的作用
    
    欧拉角  姿态矩阵可以通过四元数和欧拉角算出
    

    位姿pose--位姿信息包含位置坐标和角度 (四元数)

      一个四元素有4个成员(x,y,z,w)。其中,对于不绕x / y / z轴旋转的 常用单位 四元数为(0,0,0,1)
    
       "pose_orientation": {
            "x": -0.0005576330351997091,
            "y": -0.0009195997450303073,
            "z": -0.9290865615830163,
    		"w": 0.3698607906598847,
            "pose_x": 6855.053677575546,
            "pose_y": -19706.759414176922,
            "pose_z": 13.437930198386312}
    
        {"pose_matrix": [
            -0.03224906846459613, 0.999477679252545, -0.0020895595499665115, 475.48624669690616,
            -0.9994492212522277, -0.032231638645109084, 0.007897823027072972, -2091.9865008569323,
            0.007826347901904247, 0.0023431061004955257, 0.999966628509332, 10.446635558269918,
            0.0,0.0,0.0,1.0]}
    
        {"ex_paramter": [
        [-0.03224906846459613, 0.999477679252545, -0.0020895595499665115, 475.48624669690616],
        [-0.9994492212522277, -0.032231638645109084, 0.007897823027072972, -2091.9865008569323], 
        [0.007826347901904247, 0.0023431061004955257, 0.999966628509332, 10.446635558269918], 
        [0.0, 0.0, 0.0, 1.0]]}	
    
    
    旋转的算法--其中一种:欧拉角。Pitch、Yaw、Roll
      沿着机身右方轴(Unity中的+X)进行旋转,称为pitch,中文叫俯仰。
      沿着机头上方轴(Unity中的+Y)进行旋转,称为Yaw,中文叫偏航。
      沿着机头前方轴(Unity中的+Z)进行旋转,称为Roll,中文叫桶滚。
      
      欧拉角的“万向节死锁”问题,是由于欧拉旋转定义本身造成的。这种围绕选旋转前固定轴的先Z、再X、再Y的旋转操作,
      与其最终所预期的三个轴向可以旋转的结果并非一定是一对一的映射。
      某些情况下是多对一的映射,造成一些旋转自由度的缺失,也就是“死锁”。
    	
    Ros 中
      变换矩阵 == 旋转矩阵 平移矩阵 
    四元数 ->  旋转矩阵 
    python_四元数q转旋转矩阵R
        orientation = pose.orientation
        position = pose.position
    	orientation.x, orientation.y, orientation.z, orientation.w
    	position.x, position.y, position.z
    	
    	r_matrix = R.from_quat([orientation.x, orientation.y, orientation.z, orientation.w]).as_matrix()
    	t_array = np.asarray([position.x, position.y, position.z]).reshape(3, 1)
    	zero_line = np.asarray([0, 0, 0, 1])
    	rt_matrix = np.vstack((np.hstack((r_matrix, t_array)), zero_line))
    	
        pose_file_obj.write(json.dumps({"ex_paramter":np.asarray(rt_matrix).reshape(4,4).tolist()}))
        pose_file_obj.write(json.dumps({"pose_matrix": rt_matrix.reshape(16).tolist()}))
     
     示例
       from scipy.spatial.transform import Rotation as R
        
       Rq=[-0.35, 1.23e-06, 4.18e-08, 0.39]
       Rm = R.from_quat(Rq)
       rotation_matrix = Rm.as_matrix()
       print('rotation:\n',rotation_matrix)
    ###
    旋转矩阵->四元数	
     
       
    ###四元数到欧拉角
        def quart_to_rpy(x, y, z, w):
            roll = math.atan2(2 * (w * x + y * z), 1 - 2 * (x * x + y * y))
            pitch = math.asin(2 * (w * y - x * z))
            yaw = math.atan2(2 * (w * z + x * y), 1 - 2 * (z * z + y * y))
            return roll, pitch, yaw
        
        # 使用 tf 库
        import tf
        (r, p, y) = tf.transformations.euler_from_quaternion([msg.orientation.x, msg.orientation.y, msg.orientation.z, msg.orientation.w])	
    

    坐标系变换

     #世界坐标转lidar坐标
           for p in points:
                xyz_array = np.asarray([p.x, p.y, p.z, 1]).reshape(4, 1)
                rt_array = np.asarray(rt_matrix).reshape(4, 4)
                new_xyz_array = np.dot(np.linalg.inv(rt_array), xyz_array)
                new_xyz = new_xyz_array.reshape(4).tolist()
    

    Python 点云处理

     numpy类型的矩阵
     # #二维数组
       [][]和[,]
       a_matrix =np.array([[1,2,3],[4,5,6]])
       print(a_matrix[1][0:])  # [x][0:]  获取第x行的全部元素(单行)
       
      array类型(N维数组ndarray)和矩阵类型matrix
          matrix其实也是一种array,只不过是维数为2的特殊array	  
    

    Python的numpy

     ##索引和切片
       整数索引--name索引--布尔索引	 
           将数据复制到新的数组
       切片:切片方式:①通过内置的 slice(start, stop, step) 函数;②通过冒号分隔切片参数 start:stop:step
       数组的切片是原数组的视图,任何对视图的修改都会反映到原数组上
       索引切片
       
       索引用来对单个成员(元素)进行访问,切片则是对一定范围内的成员(元素)进行访问
       切片通过冒号在中括号内把相隔的两个索引查找出来[0: 10]  左含右不含【)
       
       二维数组的索引和切片
        通过切片返回一个数组-步长默认为1
          数组名[维度1起始索引:终止索引:步长,维度2起始索引:终止索引:步长]
        通过索引访问一个元素 
    	  数组名[第一个维度的索引值][第二个维度的索引值]
    

    函数的解释

    ###1.点积
      a.T代表矩阵的转置
      a.dot(b)或np.dot(a,b)代表矩阵a与矩阵b做矩阵乘法
         np.dot(a,a.T)  或者a.dot(a.T)
         x为 m×n 阶矩阵,y为 n×p 阶矩阵,则相乘的结果 result 为 m×p 阶矩阵
    
      np.linalg.inv(matrix) ###就是求逆矩阵
      如一个点乘以一个矩阵后得到了一个新的点的位置,如果想通过这个点再获得矩阵转换前的位置,那我们就需要乘以这个矩阵的逆矩阵
    
    ###2.数组的组合与分隔
     水平组合
     hastck:将数组水平拼接到一起
     用法:hastck((数组A,数组B))水平拼接数组A和B
     
      垂直组合
     vstack:将数组垂直拼接到一起
     用法:vstack(数组A,数组B)垂直拼接数组A和B	
    

    矩阵

    |-------> 变换矩阵列== 旋转矩阵(Rotation Matrix) + Translation 平移
        | 1 0 0 x |  \
        | 0 1 0 y |   }-> 左边是一个3阶的单位阵(无旋转)  3x3 matrix
        | 0 0 1 z |  /
        | 0 0 0 1 |    -> 这一行用不到 (这一行保持 0,0,0,1)
    	
    	
    ##尺度矩阵(Scale Matrix) 用于缩放	--scale是一个3D向量,表示每个轴的缩放尺度。
    

    位姿信息构建转换矩阵

        from scipy.spatial.transform import Rotation as R
    	import numpy as np
        Rr = R.from_quat([orientation.x, orientation.y, orientation.z, orientation.w])
        Rr_matrix = Rr.as_matrix()
    	Tt_array = np.asarray([position.x, position.y, position.z]).reshape(3, 1)
        zero_line = np.asarray([0, 0, 0, 1])
        rt_matrix = np.vstack((np.hstack((Rr_matrix, Tt_array)), zero_line)).reshape(4,4)
    	
    	#提取
        Rr =np.asarray(rt_matrix[0:3, 0:3])
        #Tt = np.asarray([ rt_matrix[0][3], rt_matrix[1][3], rt_matrix[2][3]])
    	Tt = np.asarray(rt_matrix[:3, 3])
    	
        ###坐标系变换
            for p in points:
                xyz_array = np.asarray([p.x, p.y, p.z, 1]).reshape(4, 1)
                new_xyz_array = np.dot(np.linalg.inv(rt_array), xyz_array)
                new_xyz = new_xyz_array.reshape(4).tolist()
    
                [new_xyz[0], new_xyz[1], new_xyz[2], p.intensity, p.ring, p.timestamp]  
    
        ###坐标系变换 
            for p in points:
                point_ = np.dot(Rr.T, [p[0],p[1],p[2]]- Tt)
                new_point_x = point_[0]
                new_point_y = point_[1]
                new_point_z = point_[2]
                h = struct.pack('ffff', new_point_x, new_point_y, new_point_z, p[3])
          			  
    	### 旋转矩阵的逆等于其转置矩阵
        ### 正交矩阵的逆(inverse)等于正交矩阵的转置(transpose)  np.linalg.det() 矩阵的行列式	
            #变换数据
    	###分块计算	
            new_xyz = np.dot(transformation_matrix,old_xyz.T)
            new_array=np.concatenate((new_xyz.T[:,:3],old_array[:,3:]),axis=1)
    

    数值计算库 Eigen

    矩阵运算

     使用Eigen进行坐标变换
       转置 m.transpose()
       
      1.点积(内积)
    
         Eigen::Vector3d v(1,2,3);
         Eigen::Vector3d w(0,1,2);
         v.dot(w);
      2.变换矩阵 初始化    一般先定义为单位变换矩阵,然后再赋值旋转和平移:
      Eigen::Matrix3d m;
      m<<0.999555,-0.00658702,0.0290829,0.0030476,0.992756,0.120107,-0.0296634,-0.119964,0.992335;
      Eigen::Vector3d v;
      v<<0.0506837,-0.0582575,0.140693; 
      //构造变换矩阵
      Eigen::Isometry3d Tcw=Eigen::Isometry3d::Identity();;
      
      Tcw.rotate(m);
      Tcw.pretranslate(v);
    

    示例

     #include <Eigen/Dense>
     using Eigen::Vector3d;	
    

    参考

    点云数据常用处理:python实现  https://blog.csdn.net/taifyang/article/details/124365265
    https://blog.csdn.net/shyjhyp11/article/details/111654692
    Eigen is a C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms.
     http://eigen.tuxfamily.org/index.php?title=Main_Page
     C++矩阵库 Eigen 简介  https://blog.51cto.com/u_6725876/5134436
  • 相关阅读:
    卸载IE
    js判断是否是object、array
    正则表达式中/i,/g,/ig,/gi,/m的区别和含义
    谷歌地图控制圆圈随缩放自适应大小 js
    WGS84坐标转换GCJ02坐标 JS实现
    Google图片和NASA 网站图片的爬虫
    Yolov_3 网络结构分析
    启动Tensorboard时发生错误:class BeholderHook(tf.estimator.SessionRunHook): AttributeError: module 'tensorflow.python.estimator.estimator_lib' has no attribute 'SessionRunHook'
    MyBatis -- generator 逆向工程
    bat使用方法汇总
  • 原文地址:https://www.cnblogs.com/ytwang/p/16719991.html
Copyright © 2020-2023  润新知