自动驾驶两个传感器之间的坐标系转换

news/2025/2/26 7:43:16

有两种方式可以实现两个坐标系的转换。
车身坐标系下一个点p_car,需要转换到相机坐标系下,旋转矩阵R_car2Cam,平移矩阵T_car2Cam。点p_car在相机坐标系下记p_cam.

方法1:先旋转再平移

p_cam = T_car2Cam * p_car + T_car2Cam
需要注意的是,这里的平移矩阵T_car2Cam是车身坐标系原点在相机坐标系下面的坐标!
用具体数值表示如下:

import numpy as np

rot = np.array([[ 4.6776832e-04, -9.9942386e-01, -3.3936482e-02],
       [ 3.1350527e-02,  3.3934463e-02, -9.9893224e-01],
       [ 9.9950832e-01, -5.9665786e-04,  3.1348340e-02]])

tran = np.array([0.106073,  1.411398, -1.971551])

p_veh = np.array([3, 6, 8]).reshape(3, 1)
p_cam_1 = rot.dot(p_veh) + tran.reshape(3,1)
print(p_cam_1)

#[[-6.16055871]
 #[-6.28240156]
 #[ 1.27418073]]

方法2:先平移再旋转

在方法1中, 是把p经过旋转,转到相机坐标系, 再加上平移向量,这个平移向量就是相机坐标系的,所以可以直接相加减。
同样的,我们这里的方法2是需要先平移,就要求平移的向量是车身坐标系下的才能相加减。就是我们如果现在需要先平移,那么就要求这个平移向量是在车身坐标系下的才能直接相加减。
即需要知道相机坐标原点相对于车身坐标系。

如图就是把左边的相机坐标系原点(0,0,0)先平移到车身坐标系的原点(0,0,0)处,注意平移后的还是在相机坐标系下,现在tran = np.array([0.106073, 1.411398, -1.971551])是相机坐标系下,car坐标系原点的位置。
就是在相机坐标系下一个点Q(0.106073, 1.411398, -1.971551),我现在就要把我相机坐标系原点挪到这个Q点。就是Q点在新相机坐标系下是(0, 0, 0). 所以之前的点n转到以Q点为原点的新相机坐标系需要经过n-(0.106073, 1.411398, -1.971551),

比如之前的原点(0,0,0)转到新平移后的Q为原点相机坐标系下是:(0,0,0)-(0.106073, 1.411398, -1.971551)

相机坐标系原点平移到车身坐标系原点,这个时候还差一步旋转。旋转,注意这个时候的旋转矩阵是需要相机坐标系到车身坐标系的,因为我们现在点都在相机坐标系下,只是平移了,需要相机到车身的旋转矩阵,直接R_car2Cam取个逆就是。

Cam_0_to_car = inv(R_car2Cam) * (Cam_0 - T_car2Cam)

import numpy as np

R_car2Cam = np.array([[ 4.6776832e-04, -9.9942386e-01, -3.3936482e-02],
       [ 3.1350527e-02,  3.3934463e-02, -9.9893224e-01],
       [ 9.9950832e-01, -5.9665786e-04,  3.1348340e-02]])

T_car2Cam = np.array([0.106073,  1.411398, -1.971551])

p_car = np.array([3, 6, 8]).reshape(3, 1)
p_cam_1 = R_car2Cam.dot(p_car) + T_car2Cam.reshape(3,1)
print(p_cam_1)

                                      #旋转矩阵的逆等于其转置
Cam_0_to_car = (np.dot(R_car2Cam.T, (np.array([[0, 0, 0]]).T - T_car2Cam[..., np.newaxis])).T).reshape(3,1)
p_cam_2 = R_car2Cam.dot(p_car - Cam_0_to_car)
print(p_cam_2)
输出:
[[-6.16055871]
 [-6.28240156]
 [ 1.27418073]]
[[-6.16055872]
 [-6.28240152]
 [ 1.27418082]]

RT矩阵的逆

import numpy as np

R_car2Cam = np.array([[ 4.6776832e-04, -9.9942386e-01, -3.3936482e-02],
       [ 3.1350527e-02,  3.3934463e-02, -9.9893224e-01],
       [ 9.9950832e-01, -5.9665786e-04,  3.1348340e-02]])

T_car2Cam = np.array([0.106073,  1.411398, -1.971551])

p_car = np.array([3, 6, 8]).reshape(3, 1)
p_cam_1 = R_car2Cam.dot(p_car) + T_car2Cam.reshape(3,1)
print(p_cam_1)



Cam_0_to_car = (np.dot(R_car2Cam.T, (np.array([[0, 0, 0]]).T - T_car2Cam[..., np.newaxis])).T).reshape(3,1)
p_cam_2 = R_car2Cam.dot(p_car - Cam_0_to_car)
print(p_cam_2)



rt = np.eye(4)
rt[:3, :3] = R_car2Cam
rt[:3, -1] = T_car2Cam
rt_1 = np.linalg.inv(rt)

print("===>rt")
print(rt)
print("===>inv rt")
print(rt_1)

print("==>>Cam_0_to_car")
print(Cam_0_to_car)
[[-6.16055871]
 [-6.28240156]
 [ 1.27418073]]
[[-6.16055872]
 [-6.28240152]
 [ 1.27418082]]
===>rt
[[ 4.6776832e-04 -9.9942386e-01 -3.3936482e-02  1.0607300e-01]
 [ 3.1350527e-02  3.3934463e-02 -9.9893224e-01  1.4113980e+00]
 [ 9.9950832e-01 -5.9665786e-04  3.1348340e-02 -1.9715510e+00]
 [ 0.0000000e+00  0.0000000e+00  0.0000000e+00  1.0000000e+00]]
===>inv rt
[[ 4.67768326e-04  3.13505285e-02  9.99508364e-01  1.92628402e+00]
 [-9.99423904e-01  3.39344610e-02 -5.96657759e-04  5.69405203e-02]
 [-3.39364847e-02 -9.98932217e-01  3.13483392e-02  1.47529553e+00]
 [ 0.00000000e+00  0.00000000e+00  0.00000000e+00  1.00000000e+00]]
==>>Cam_0_to_car
[[1.92628394]
 [0.05694051]
 [1.47529556]]

这里求相机坐标原点在车身坐标系下的坐标, 其实用RT矩阵再求逆就可以得到。


http://www.niftyadmin.cn/n/5868323.html

相关文章

【JavaWeb13】了解ES6的核心特性,对于提高JavaScript编程效率有哪些潜在影响?

文章目录 🌍一. ES6 新特性❄️1. ES6 基本介绍❄️2. 基本使用2.1 let 声明变量2.2 const 声明常量/只读变量2.3 解构赋值2.4 模板字符串2.5 对象拓展运算符2.6 箭头函数 🌍二. Promise❄️1. 基本使用❄️2. 如何解决回调地狱问题2.1回调地狱问题2.2 使…

【SpringBoot】——分组校验、自定义注解、登入验证(集成redis)、属性配置方式、多环境开发系统学习知识

🎼个人主页:【Y小夜】 😎作者简介:一位双非学校的大三学生,编程爱好者, 专注于基础和实战分享,欢迎私信咨询! 🎆入门专栏:🎇【MySQL&#xff0…

【uniapp】上传文件流图片

需求:从接口下载指定文件,把这个文件再上传到后端。 背景:文件的上传、下载接口都是现有的,原本在pc端下载使用的responseType为blob,在uniapp不支持。如果按照原本的方式请求接口,返回的值会是字符串&…

【算法基础篇】-字符串

字符串篇 一、最长回文子串二、二进制求和三、字符串相乘今日分享这里 一、最长回文子串 最长回文子串 给你一个字符串 s,找到 s 中最长的 回文 子串。 讲解: 我们这里使用的是中心扩展方法,其实类似于暴力枚举,但是时间复杂度…

Java集合性能优化面试题

Java集合性能优化面试题 初始化优化 Q1: 如何优化集合的初始化&#xff1f; public class CollectionInitializationExample {// 1. 合理设置初始容量public void initializationOptimization() {// 不好的实践&#xff1a;使用默认容量List<String> badList new Arr…

Java23种设计模式案例

目录 一、概述 二、创建型模式 (Creational Patterns) 单例模式 (Singleton Pattern) 工厂方法模式 (Factory Method Pattern) 抽象工厂模式 (Abstract Factory Pattern) 建造者模式 (Builder Pattern) 原型模式 (Prototype Pattern) 三、结构型模式 (Structu…

浏览器深度解析:打造极速、安全、个性化的上网新体验

在数字化时代,浏览器作为我们获取信息、娱乐休闲的重要工具,其性能与功能直接影响着我们的上网体验。今天,我将为大家介绍一款备受好评的浏览器——Yandex浏览器,并深入解析其独特功能与优势,帮助大家更好地了解并选择这款上网神器。 一、知名公司背书,开源项目融合 Yan…

@KafkaListener和KafkaTemplate自动装配原理分析

依赖项和配置信息参见另一篇博文KafkaListener的配置使用&#xff0c;这里主要借助源码分析KafkaListener和KafkaTemplate自动装配原理。 1、KafkaAutoConfiguration 源码分析 KafkaAutoConfiguration类自动装配生成了生产者客户端KafkaTemplate的bean和消费者基础ConsumerFa…