首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

C语言编程:坐标系的平移和旋转

  • 23-09-22 01:23
  • 3034
  • 14085
blog.csdn.net

本文总结博主在工作中遇到的坐标系转换相关问题,以及C语言编程实现。

文章目录

  • 1 问题场景
  • 2 公式推导
    • 2.1 旋转坐标系推导
    • 2.2 平移坐标系推导
    • 2.3 完整公式
  • 3 C语言编程

1 问题场景

对于ADAS算法开发,在工作中遇到过很多需要坐标系转换的场景。例如,一辆车上有很多个传感器,包括摄像头、毫米波雷达和激光雷达。在同一时刻感知到外部环境信息后,由于不同传感器基于自身坐标系,在数据融合之前需要将目标信息转换到同一个坐标系之下(通常是汽车后轴中心点)。

例如,下图中的XOY坐标系是以车辆后轴中心点为原点,车头方向为X轴正方向,垂直车身向左是Y轴正方向。X’O’Y’是前视摄像头坐标系,以摄像头位置为坐标原点,坐标轴方向和XY相同。

在这里插入图片描述
X’O’Y’坐标系相对于XOY坐标系向前平移一个距离,左右也相应的有一个距离。已知一个点P在X’O’Y’坐标系中的坐标为(x’,y’),以及已知O’点在XOY坐标系的坐标(xo’,yo’),就可以通过坐标平移算出点P在XOY坐标系中的坐标。这是坐标系平移的例子。

再举个例子,车辆在运动的过程中,方向盘打了一个角度,汽车就会做一个圆周运动。在某一时刻t0,经过Δt时间,车辆不仅产生一个位置上的平移,自身还有一个旋转。

在这里插入图片描述
结合上图,比如说在t0时刻一个目标点在XOY坐标系下的坐标是(x,y),在t1时刻车辆运动到前面一点的位置,并且车头朝向偏左了一个角度。这时候,那个目标点和车的相对位置就改变了,需要重新计算它在X’O’Y’坐标系中的坐标。利用X’O’Y’坐标系相对于XOY坐标系的距离和角度,就可以求出来目标点在心得坐标系X’O’Y’坐标系中的坐标(x’,y’)。这个例子中包含了坐标系的平移和旋转。

2 公式推导

上面场景的问题总结如下:已知点P在XOY坐标系中的坐标为(px,py),X’O’Y’坐标系的原点O’在XOY坐标系中的坐标为(ox’,oy’),求点P在X’O’Y’坐标系中的坐标。这里坐标系采用了右手系,即X向右Y向上。旋转角度定义为逆时针为正角度,以便后面的推导。

在这里插入图片描述

两个坐标系之间通过平移和旋转两种运动转换得到。为简化推导,首先基于O’点做出一个中间坐标系X’’O’Y’’,先完成旋转运动。

在这里插入图片描述

这里问题就转换为先推导(px’,py’)和(px’’,py’’)的关系,再推导(px’’,py’’)和(px,py)的关系。

2.1 旋转坐标系推导

首先,过点P做垂直线PA⊥O’Y’,PB⊥O’X’,PC⊥O’Y’’,PD⊥O’X’’,那么很容易知道∠BPD = θ,如下图所示。
在这里插入图片描述
接着过点D做DE⊥O’X’,如下:
在这里插入图片描述
这样,就可以推导出px’:
p x ′    =    ∣ O ′ E ∣    + ∣    E B ∣    =    ∣ O ′ D ∣ ⋅ cos ⁡ θ    +    ∣ P D ∣ ⋅ sin ⁡ θ    =    p x ′ ′ ⋅ cos ⁡ θ      +    p y ′ ′ ⋅ sin ⁡ θ    px';=;vert O'Evert;+vert;EBvert;=;vert O'Dvertcdotcos heta;+;vert PDvertcdotsin heta;=;px''cdotcos heta;;+;py''cdotsin heta; px′=∣O′E∣+∣EB∣=∣O′D∣⋅cosθ+∣PD∣⋅sinθ=px′′⋅cosθ+py′′⋅sinθ

接着推导py’,过点D做DF⊥PF(PF是PB的延长线),就可以推导出py’:
在这里插入图片描述
p y ′    =    ∣ P F ∣    −    ∣    B F ∣    =    ∣ P D ∣ ⋅ cos ⁡ θ    −    ∣ O D ∣ ⋅ sin ⁡ θ    =    p y ′ ′ ⋅ cos ⁡ θ      −    p x ′ ′ ⋅ sin ⁡ θ    py';=;vert PFvert;-;vert;BFvert;=;vert PDvertcdotcos heta;-;vert ODvertcdotsin heta;=;py''cdotcos heta;;-;px''cdotsin heta; py′=∣PF∣−∣BF∣=∣PD∣⋅cosθ−∣OD∣⋅sinθ=py′′⋅cosθ−px′′⋅sinθ

将上面两个推导的结果写到一起,后面的章节需要用到:
p x ′    =    p x ′ ′ ⋅ cos ⁡ θ      +    p y ′ ′ ⋅ sin ⁡ θ       p y ′    = −    p x ′ ′ ⋅ sin ⁡ θ    +    p y ′ ′ ⋅ cos ⁡ θ      px';=;px''cdotcos heta;;+;py''cdotsin heta;\; py';=-;px''cdotsin heta;+;py''cdotcos heta;; px′=px′′⋅cosθ+py′′⋅sinθpy′=−px′′⋅sinθ+py′′⋅cosθ
这里也可以用矩阵变换的方式,一步就能得出这个结论。点P相当于绕着原点顺时针转了θ角度,所以通过旋转矩阵公式可以得出变换关系。
[ p x ′ p y ′ ]    =    [ cos ⁡ θ sin ⁡ θ − sin ⁡ θ cos ⁡ θ ] [ p x ′ ′ p y ′ ′ ]

[px′py′]" role="presentation">[px′py′][px′py′]
;=;
[cos⁡θsin⁡θ−sin⁡θcos⁡θ]" role="presentation" style="position: relative;">[cosθ−sinθsinθcosθ][cos⁡θsin⁡θ−sin⁡θcos⁡θ]
[px″py″]" role="presentation" style="position: relative;">[px′′py′′][px″py″]
[px′py′​]=[cosθ−sinθ​sinθcosθ​][px′′py′′​]

2.2 平移坐标系推导

平移的推导过程就简单很多,见下图
在这里插入图片描述
就是简单的加减:

p x ′ ′    =    p x    −    o ′ x p y ′ ′    =    p y    −    o ′ y px'';=;px;-;o'x\py'';=;py;-;o'y px′′=px−o′xpy′′=py−o′y

2.3 完整公式

将上面两个小节的公式代入得出完整公式:
p x ′    =    ( p x    −    o ′ x ) ⋅ cos ⁡ θ      +    ( p y    −    o ′ y ) ⋅ sin ⁡ θ       p y ′    = −    ( p x    −    o ′ x ) ⋅ sin ⁡ θ    +    ( p y    −    o ′ y ) ⋅ cos ⁡ θ      px';=;(px;-;o'x)cdotcos heta;;+;(py;-;o'y)cdotsin heta;\; py';=-;(px;-;o'x)cdotsin heta;+;(py;-;o'y)cdotcos heta;; px′=(px−o′x)⋅cosθ+(py−o′y)⋅sinθpy′=−(px−o′x)⋅sinθ+(py−o′y)⋅cosθ
后面基于这个公式编写C语言程序

3 C语言编程

首先,分析一下这个程序的需求。输入是一个点的在旧坐标系下的坐标,以及新坐标系相对于旧坐标系的位置和旋转角度。输出是该点在新坐标系下的坐标。

这里,博主设计一个简单的函数来实现这个算法。

#include 
#include 

#define PI 3.1415926F

typedef struct Point_Tag
{
    float X;
    float Y;
} Point_Type;//点结构体

typedef struct CoordinatePosition_Tag
{
    float deltaX;
    float deltaY;
    float theta;
} CoordinatePosition_Type;//新坐标系相对旧坐标系位置结构体

//坐标系变换函数
void coordinate_transformation(const Point_Type*              const point_old_system_sp,
                               const CoordinatePosition_Type* const coordinate_position_sp,
                                     Point_Type*              const point_new_system_sp)
{
    point_new_system_sp->X =  (point_old_system_sp->X - coordinate_position_sp->deltaX) * cosf(coordinate_position_sp->theta) +
                              (point_old_system_sp->Y - coordinate_position_sp->deltaY) * sinf(coordinate_position_sp->theta);
    point_new_system_sp->Y = -(point_old_system_sp->X - coordinate_position_sp->deltaX) * sinf(coordinate_position_sp->theta) +
                              (point_old_system_sp->Y - coordinate_position_sp->deltaY) * cosf(coordinate_position_sp->theta);
}

//main函数中简单测试
int main()
{
    Point_Type point_old_system;
    CoordinatePosition_Type coordinate_position;
    Point_Type point_new_system;

    point_old_system.X = 2.0F;
    point_old_system.Y = 2.0F;
    coordinate_position.deltaX = 0.0F;
    coordinate_position.deltaY = 0.0F;
    coordinate_position.theta = (45.0F/180.0F*PI);

    coordinate_transformation(&point_old_system,&coordinate_position,&point_new_system);

    printf("NEW_X = %f,NEW_Y = %f", point_new_system.X,point_new_system.Y);

} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47

代码实现是比较简单的,就是把公式翻译成C代码。功能函数中传了三个参数,前两个指针是用来输入点在就坐标系的位置,和新坐标系在旧坐标系的位置和角度。第三个指针用于获取输出结果。

>>返回个人博客总目录

文章知识点与官方知识档案匹配,可进一步学习相关知识
C技能树首页概览160872 人正在系统学习中
注:本文转载自blog.csdn.net的chhttty的文章"https://blog.csdn.net/u013288925/article/details/131502101"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top