当前位置: 首页 > web >正文

罗德里格斯公式动图演示

一. 罗德里格斯公式形式:

R o t ( ω ^ , θ ) = e [ ω ] ^ × θ = I + s i n θ [ ω ^ ] × + ( 1 − c o s θ ) [ ω ^ ] × 2 Rot(\hat{\bold{\omega}}, \theta)=e^{\hat{\bold{[\omega]}}_{\times} \theta}=\bold{I}+sin\theta[\hat{\bold{\omega}}]_{\times}+(1-cos\theta)[\hat{\bold{\omega}}]_{\times}^2 Rot(ω^,θ)=e[ω]^×θ=I+sinθ[ω^]×+(1cosθ)[ω^]×2

二. 罗德里格斯公式解释:

在一个给定的坐标系 { s } \{s\} {s}下,有一个单位向量的旋转轴 ω \bold{\omega} ω,绕着这个轴旋转 θ \theta θ度的旋转矩阵为 R o t ( ω ^ , θ ) Rot(\hat{\bold{\omega}}, \theta) Rot(ω^,θ),可以使用罗德里格斯公式进行求解。

三. 最终效果

向量 v [3, 4, 5] 绕 k轴 [1, 1, 1] 旋转 180°,效果如下图所示:
在这里插入图片描述

四. 代码

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import animationdef rodrigues_rotate(_v, _k, theta):"""使用罗德里格斯公式将向量v绕单位向量k旋转theta弧度:param v: 需要旋转的向量,shape=(3,):param k: 旋转轴单位向量,shape=(3,):param theta: 旋转角度(弧度):return: 旋转后的向量,shape=(3,)"""_v = np.asarray(_v)_v = _v / np.linalg.norm(_v)  # 先归一化输入向量_k = np.asarray(_k)_k = _k / np.linalg.norm(_k)v_rot = (_v * np.cos(theta)+ np.cross(_k, _v) * np.sin(theta)+ _k * np.dot(_k, _v) * (1 - np.cos(theta)))return v_rotdef animate_rodrigues_rotation(_v, _k, _total_theta=np.pi, _frames=100, save_gif=True, gif_path="rodrigues_rotation.gif"):"""绘制向量v绕轴k旋转的动图,并保存为gif:param v: 初始向量:param k: 旋转轴:param total_theta: 总旋转角度(弧度):param frames: 动画帧数:param save_gif: 是否保存为gif:param gif_path: gif保存路径"""_v = np.asarray(_v)_v = _v / np.linalg.norm(_v)  # 先归一化输入向量_k = np.asarray(_k)_k = _k / np.linalg.norm(_k)thetas = np.linspace(0, _total_theta, _frames)vectors = np.array([rodrigues_rotate(_v, _k, theta) for theta in thetas])fig = plt.figure()ax = fig.add_subplot(111, projection="3d")# 自动根据向量和旋转轴范围设置合适的坐标轴范围all_points = np.vstack(([_v], [vectors[-1]], [_k]))max_range = np.max(np.abs(all_points)) * 1.3  # 适当放大for axis in [ax.set_xlim, ax.set_ylim, ax.set_zlim]:axis([-max_range, max_range])ax.set_xlabel("X")ax.set_ylabel("Y")ax.set_zlabel("Z")ax.quiver(0,0,0,_k[0],_k[1],_k[2],color="g",length=1.2,linewidth=2,label="Axis k",)ax.quiver(0,0,0,_v[0],_v[1],_v[2],color="r",length=1.2,linewidth=2,label="start vec",)ax.quiver(0,0,0,vectors[-1][0],vectors[-1][1],vectors[-1][2],color="y",length=1.2,linewidth=2,label="end vec",)vec_quiv = ax.quiver(0,0,0,_v[0],_v[1],_v[2],color="b",length=1.0,linewidth=2,label="Rotating v",)ax.legend()# 用于保存quiver对象quivers = [vec_quiv]def update(num):# 移除上一帧的向量quivers[0].remove()new_v = vectors[num]quivers[0] = ax.quiver(0,0,0,new_v[0],new_v[1],new_v[2],color="b",length=1.0,linewidth=2,)return quivers[0],# 5秒,interval=50ms,则frames=100ani = animation.FuncAnimation(fig, update, frames=_frames, interval=5000//_frames, blit=True)if save_gif:ani.save(gif_path, writer='pillow', fps=_frames//5)print(f"GIF已保存到: {gif_path}")plt.show()if __name__ == "__main__":# 示例:将向量 v [3, 4, 5] 绕 k轴 [1, 1, 1] 旋转 180°v = np.array([3, 4, -5])k = np.array([1, 1, 1])animate_rodrigues_rotation(v, k, _total_theta=np.pi/180*120, _frames=100, save_gif=True, gif_path="rodrigues_rotation.gif")
http://www.xdnf.cn/news/9883.html

相关文章:

  • [ Qt ] | QPushButton常见用法
  • Allegro 版本查看和降版本
  • DeepSeek:不同模式(v3、R1)如何选择?
  • 三层架构 vs SOA vs 微服务:该选谁?
  • 华为云Flexus+DeepSeek征文 | 初探华为云ModelArts Studio:部署DeepSeek-V3/R1商用服务的详细步骤
  • 大型工业控制系统中私有云计算模式的弊端剖析与反思
  • 数据结构 - 数相关计算题
  • ZigBee 协议:开启物联网低功耗通信新时代
  • 【conda报错】InvalidArchiveError
  • 基于Session与基于Redis与Token验证码登录校验
  • 并查集 c++函数的值传递和引用传递 晴神问
  • <el-date-picker>配置禁用指定日期之前的时间选择(Vue2+Vue3)
  • 尚硅谷redis7 86 redis集群分片之3主3从集群搭建
  • 自动化测试实例:Web登录功能性测试(无验证码)
  • 《深度关系-从建立关系到彼此信任》
  • 自动脚本精灵 解锁会员版 v25.05.25 智能安卓自动点击脚本助手APP
  • 深入理解 SQL 的 JOIN 查询:从基础到高级的第一步
  • 【达梦数据库】会话sp_close关闭不掉
  • LLM:decoder-only 思考
  • 【从零开始学习QT】快捷键、帮助文档、Qt窗口坐标体系
  • 我用Qt+Python实现了个监控QQ消息自动下载文件处理的办公外挂程序
  • HTML 计算网页的PPI
  • nlp中的频率就是权重吗
  • C++ 初阶 | 类和对象易错知识点(下)
  • Codeforces Round 1027 (Div. 3)(A-E)
  • React 编译器
  • 一文理清楚大模型里的RAG架构
  • 基于生产-消费模式,使用Channel进行文件传输(Tcp方式)
  • [嵌入式实验]实验四:串口打印电压及温度
  • 嵌赛笔记主控