15 刚体变换模块(rigid.rs)

rigid.rs是一个表示三维刚体变换(Rigid Transformation)的结构体定义,用于在计算机图形学、机器人学以及物理模拟等领域中表示物体在三维空间中的旋转和平移。在这个定义中,所有长度在变换后都保持不变,这是刚体变换的一个基本特性。

一、rigid.rs源码

//! All matrix multiplication in this module is in row-vector notation,
//! i.e. a vector `v` is transformed with `v * T`, and if you want to apply `T1`
//! before `T2` you use `T1 * T2`use crate::approxeq::ApproxEq;
use crate::trig::Trig;
use crate::{Rotation3D, Transform3D, UnknownUnit, Vector3D};use core::{fmt, hash};#[cfg(feature = "bytemuck")]
use bytemuck::{Pod, Zeroable};
use num_traits::real::Real;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};/// A rigid transformation. All lengths are preserved under such a transformation.
///
///
/// Internally, this is a rotation and a translation, with the rotation
/// applied first (i.e. `Rotation * Translation`, in row-vector notation)
///
/// This can be more efficient to use over full matrices, especially if you
/// have to deal with the decomposed quantities often.
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[repr(C)]
pub struct RigidTransform3D<T, Src, Dst> {pub rotation: Rotation3D<T, Src, Dst>,pub translation: Vector3D<T, Dst>,
}impl<T, Src, Dst> RigidTransform3D<T, Src, Dst> {/// Construct a new rigid transformation, where the `rotation` applies first#[inline]pub const fn new(rotation: Rotation3D<T, Src, Dst>, translation: Vector3D<T, Dst>) -> Self {Self {rotation,translation,}}
}impl<T: Copy, Src, Dst> RigidTransform3D<T, Src, Dst> {pub fn cast_unit<Src2, Dst2>(&self) -> RigidTransform3D<T, Src2, Dst2> {RigidTransform3D {rotation: self.rotation.cast_unit(),translation: self.translation.cast_unit(),}}
}impl<T: Real + ApproxEq<T>, Src, Dst> RigidTransform3D<T, Src, Dst> {/// Construct an identity transform#[inline]pub fn identity() -> Self {Self {rotation: Rotation3D::identity(),translation: Vector3D::zero(),}}/// Construct a new rigid transformation, where the `translation` applies first#[inline]pub fn new_from_reversed(translation: Vector3D<T, Src>,rotation: Rotation3D<T, Src, Dst>,) -> Self {// T * R//   = (R * R^-1) * T * R//   = R * (R^-1 * T * R)//   = R * T'//// T' = (R^-1 * T * R) is also a translation matrix// It is equivalent to the translation matrix obtained by rotating the// translation by Rlet translation = rotation.transform_vector3d(translation);Self {rotation,translation,}}#[inline]pub fn from_rotation(rotation: Rotation3D<T, Src, Dst>) -> Self {Self {rotation,translation: Vector3D::zero(),}}#[inline]pub fn from_translation(translation: Vector3D<T, Dst>) -> Self {Self {translation,rotation: Rotation3D::identity(),}}/// Decompose this into a translation and an rotation to be applied in the opposite order////// i.e., the translation is applied _first_#[inline]pub fn decompose_reversed(&self) -> (Vector3D<T, Src>, Rotation3D<T, Src, Dst>) {// self = R * T//      = R * T * (R^-1 * R)//      = (R * T * R^-1) * R)//      = T' * R//// T' = (R^ * T * R^-1) is T rotated by R^-1let translation = self.rotation.inverse().transform_vector3d(self.translation);(translation, self.rotation)}/// Returns the multiplication of the two transforms such that/// other's transformation applies after self's transformation.////// i.e., this produces `self * other` in row-vector notation#[inline]pub fn then<Dst2>(&self,other: &RigidTransform3D<T, Dst, Dst2>,) -> RigidTransform3D<T, Src, Dst2> {// self = R1 * T1// other = R2 * T2// result = R1 * T1 * R2 * T2//        = R1 * (R2 * R2^-1) * T1 * R2 * T2//        = (R1 * R2) * (R2^-1 * T1 * R2) * T2//        = R' * T' * T2//        = R' * T''//// (R2^-1 * T2 * R2^) = T' = T2 rotated by R2// R1 * R2  = R'// T' * T2 = T'' = vector addition of translations T2 and T'let t_prime = other.rotation.transform_vector3d(self.translation);let r_prime = self.rotation.then(&other.rotation);let t_prime2 = t_prime + other.translation;RigidTransform3D {rotation: r_prime,translation: t_prime2,}}/// Inverts the transformation#[inline]pub fn inverse(&self) -> RigidTransform3D<T, Dst, Src> {// result = (self)^-1//        = (R * T)^-1//        = T^-1 * R^-1//        = (R^-1 * R) * T^-1 * R^-1//        = R^-1 * (R * T^-1 * R^-1)//        = R' * T'//// T' = (R * T^-1 * R^-1) = (-T) rotated by R^-1// R' = R^-1//// An easier way of writing this is to use new_from_reversed() with R^-1 and T^-1RigidTransform3D::new_from_reversed(-self.translation, self.rotation.inverse())}pub fn to_transform(&self) -> Transform3D<T, Src, Dst>whereT: Trig,{self.rotation.to_transform().then(&self.translation.to_transform())}/// Drop the units, preserving only the numeric value.#[inline]pub fn to_untyped(&self) -> RigidTransform3D<T, UnknownUnit, UnknownUnit> {RigidTransform3D {rotation: self.rotation.to_untyped(),translation: self.translation.to_untyped(),}}/// Tag a unitless value with units.#[inline]pub fn from_untyped(transform: &RigidTransform3D<T, UnknownUnit, UnknownUnit>) -> Self {RigidTransform3D {rotation: Rotation3D::from_untyped(&transform.rotation),translation: Vector3D::from_untyped(transform.translation),}}
}impl<T: fmt::Debug, Src, Dst> fmt::Debug for RigidTransform3D<T, Src, Dst> {fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {f.debug_struct("RigidTransform3D").field("rotation", &self.rotation).field("translation", &self.translation).finish()}
}impl<T: PartialEq, Src, Dst> PartialEq for RigidTransform3D<T, Src, Dst> {fn eq(&self, other: &Self) -> bool {self.rotation == other.rotation && self.translation == other.translation}
}
impl<T: Eq, Src, Dst> Eq for RigidTransform3D<T, Src, Dst> {}impl<T: hash::Hash, Src, Dst> hash::Hash for RigidTransform3D<T, Src, Dst> {fn hash<H: hash::Hasher>(&self, state: &mut H) {self.rotation.hash(state);self.translation.hash(state);}
}impl<T: Copy, Src, Dst> Copy for RigidTransform3D<T, Src, Dst> {}impl<T: Clone, Src, Dst> Clone for RigidTransform3D<T, Src, Dst> {fn clone(&self) -> Self {RigidTransform3D {rotation: self.rotation.clone(),translation: self.translation.clone(),}}
}#[cfg(feature = "arbitrary")]
impl<'a, T, Src, Dst> arbitrary::Arbitrary<'a> for RigidTransform3D<T, Src, Dst>
whereT: arbitrary::Arbitrary<'a>,
{fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {Ok(RigidTransform3D {rotation: arbitrary::Arbitrary::arbitrary(u)?,translation: arbitrary::Arbitrary::arbitrary(u)?,})}
}#[cfg(feature = "bytemuck")]
unsafe impl<T: Zeroable, Src, Dst> Zeroable for RigidTransform3D<T, Src, Dst> {}#[cfg(feature = "bytemuck")]
unsafe impl<T: Pod, Src: 'static, Dst: 'static> Pod for RigidTransform3D<T, Src, Dst> {}impl<T: Real + ApproxEq<T>, Src, Dst> From<Rotation3D<T, Src, Dst>>for RigidTransform3D<T, Src, Dst>
{fn from(rot: Rotation3D<T, Src, Dst>) -> Self {Self::from_rotation(rot)}
}impl<T: Real + ApproxEq<T>, Src, Dst> From<Vector3D<T, Dst>> for RigidTransform3D<T, Src, Dst> {fn from(t: Vector3D<T, Dst>) -> Self {Self::from_translation(t)}
}#[cfg(test)]
mod test {use super::RigidTransform3D;use crate::default::{Rotation3D, Transform3D, Vector3D};#[test]fn test_rigid_construction() {let translation = Vector3D::new(12.1, 17.8, -5.5);let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);let rigid = RigidTransform3D::new(rotation, translation);assert!(rigid.to_transform().approx_eq(&rotation.to_transform().then(&translation.to_transform())));let rigid = RigidTransform3D::new_from_reversed(translation, rotation);assert!(rigid.to_transform().approx_eq(&translation.to_transform().then(&rotation.to_transform())));}#[test]fn test_rigid_decomposition() {let translation = Vector3D::new(12.1, 17.8, -5.5);let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);let rigid = RigidTransform3D::new(rotation, translation);let (t2, r2) = rigid.decompose_reversed();assert!(rigid.to_transform().approx_eq(&t2.to_transform().then(&r2.to_transform())));}#[test]fn test_rigid_inverse() {let translation = Vector3D::new(12.1, 17.8, -5.5);let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);let rigid = RigidTransform3D::new(rotation, translation);let inverse = rigid.inverse();assert!(rigid.then(&inverse).to_transform().approx_eq(&Transform3D::identity()));assert!(inverse.to_transform().approx_eq(&rigid.to_transform().inverse().unwrap()));}#[test]fn test_rigid_multiply() {let translation = Vector3D::new(12.1, 17.8, -5.5);let rotation = Rotation3D::unit_quaternion(0.5, -7.8, 2.2, 4.3);let translation2 = Vector3D::new(9.3, -3.9, 1.1);let rotation2 = Rotation3D::unit_quaternion(0.1, 0.2, 0.3, -0.4);let rigid = RigidTransform3D::new(rotation, translation);let rigid2 = RigidTransform3D::new(rotation2, translation2);assert!(rigid.then(&rigid2).to_transform().approx_eq(&rigid.to_transform().then(&rigid2.to_transform())));assert!(rigid2.then(&rigid).to_transform().approx_eq(&rigid2.to_transform().then(&rigid.to_transform())));}
}

二、结构体字段说明:

  • rotation: 这是一个Rotation3D类型的字段,表示旋转变换。Rotation3D是另一个结构体,用于表示三维空间中的旋转。Src和Dst是泛型参数,分别代表旋转前后的坐标系。
  • translation: 这是一个Vector3D类型的字段,表示平移变换。Vector3D是一个表示三维向量的结构体,Dst表示平移后的坐标系。
  • 变换顺序:在这个结构体中,旋转是先于平移应用的,即先进行旋转(Rotation * Translation),然后进行平移。这里的乘法表示的是变换的组合,但在行向量表示法中,通常理解为矩阵乘法,其中旋转矩阵乘以平移向量(实际上是通过扩展平移向量为齐次坐标形式后进行矩阵乘法)。

三、方法

  1. 构造方法 new:
  • 这个方法用于创建一个新的 RigidTransform3D 实例。
  • 它接受一个旋转 Rotation3D<T, Src, Dst> 和一个平移 Vector3D<T, Dst> 作为参数。
  • 这里的 T 表示数值类型,Src 和 Dst 分别表示旋转和平移的单位类型。
  1. cast_unit 方法:
  • 这个方法用于将 RigidTransform3D 实例的单位从一种类型转换为另一种类型。
  • 它要求数值类型 T 实现 Copy trait,以便可以复制数值。
  • Src2 和 Dst2 是新的单位类型。
  1. identity 方法:
  • 用于构造一个表示恒等变换的 RigidTransform3D 实例。
  • 恒等变换意味着物体不会发生任何旋转或平移。
    +这个方法要求数值类型 T 实现 Real 和 ApproxEq traits。
  1. to_transform 方法:
  • 这个方法将 RigidTransform3D 转换为一个更一般的 Transform3D 实例。
  • 它要求数值类型 T 实现 Trig trait,以便可以进行三角函数计算。
  • 方法内部,首先将旋转转换为变换,然后将平移转换为变换,并将这两个变换组合起来。
  1. to_untyped 和 from_untyped 方法:
  • to_untyped 方法用于去除单位,只保留数值值,返回一个单位类型为 UnknownUnit 的 RigidTransform3D 实例。
  • from_untyped 方法则相反,它接受一个单位类型为 UnknownUnit 的 RigidTransform3D 实例,并为其添加单位,返回一个新的 RigidTransform3D 实例。
  1. fmt::Debug实现:
  • 为RigidTransform3D实现了Debug trait,允许使用{:?}格式化字符串来打印该类型的实例。
  • 在实现中,通过f.debug_struct(“RigidTransform3D”)创建一个调试结构体,并添加rotation和translation两个字段,最后调用.finish()完成结构体的构建。
  1. PartialEq和Eq实现:
  • 为RigidTransform3D实现了PartialEq trait,允许比较两个实例是否相等。
  • 通过比较rotation和translation两个成员是否相等来确定两个RigidTransform3D实例是否相等。
  • 实现了Eq trait,这通常是在实现PartialEq之后自动实现的,表示RigidTransform3D实例之间的相等性是一致和反射的。
  1. hash::Hash实现:
  • 为RigidTransform3D实现了Hash trait,允许该类型的实例被哈希。
  • 实现中,通过调用self.rotation.hash(state)和self.translation.hash(state)将rotation和translation两个成员的值合并到哈希状态中。
  1. Copy和Clone实现:
  • 如果T实现了Copy trait,则RigidTransform3D也实现了Copy trait,允许通过复制位模式来复制实例。
  • 如果T实现了Clone trait,则RigidTransform3D也实现了Clone trait,允许通过调用clone方法来创建实例的深拷贝。
  1. arbitrary::Arbitrary实现(依赖proptest库):
  • 为RigidTransform3D实现了Arbitrary trait,允许在属性测试中自动生成实例。
  • 通过调用arbitrary::Arbitrary::arbitrary(u)?分别为rotation和translation生成任意值。
  1. Zeroable和Pod实现(依赖bytemuck库):
  • 如果T实现了Zeroable trait,则RigidTransform3D也实现了Zeroable trait,允许将实例的内存区域清零。
  • 如果T实现了Pod trait(Plain Old Data,简单旧数据),且Src和Dst具有静态生命周期,则RigidTransform3D也实现了Pod trait,表示实例的内存布局是平凡的,可以安全地复制和比较内存块。
  1. 从Rotation3D和Vector3D的类型转换:
  • 如果T实现了Real trait(通常表示实数类型,如浮点数)和ApproxEq trait(允许近似相等比较),则可以从Rotation3D<T, Src, Dst>和Vector3D<T, Dst>类型转换为RigidTransform3D<T, Src, Dst>。
  • 提供了from_rotation和from_translation的便捷方法(虽然在这段代码中没有直接定义这些方法,但从上下文中可以推断出这一点)。

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

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

相关文章

GPT与Deepseek等数据驱动AI的缺点

当前数据驱动的AI&#xff08;包括GPT与Deepseek等各种大小模型&#xff09;只进行了数/物理性的初步探索&#xff0c;尚未触及人机环境生态系统的复杂性。也就是说&#xff0c;当前的数据驱动型 AI&#xff0c;虽然在处理大量数据、解决特定任务方面取得了显著进展&#xff0c…

阿里云盘PC端打不开解决办法

阿里云盘服务中心 搜索&#xff1a;PC端无法启动怎么办 选择问题 PC端双击云盘图标没有反应&#xff08;windows系统&#xff09; 下载null.sys&#xff0c;先执行压缩包里面的 null.reg 注册表&#xff0c;再按官方文档操作&#xff0c;不然会报错&#xff0c;搞完建议重启一…

树莓派pico入坑笔记,故障解决:请求 USB 设备描述符失败,故障码(43)

今天心血来潮&#xff0c;拿出吃灰的pico把玩一下&#xff0c;打开thonny&#xff0c;上电&#xff0c;然后...... 上电识别不到端口&#xff0c;windows报错&#xff0c;请求 USB 设备描述符失败&#xff0c;故障码&#xff08;43&#xff09; 一开始以为是坏了&#xff08;磕…

Linux——文件系统

一、从硬件出发 1&#xff09;磁盘的主要构成 通常硬盘是由盘片、主轴、磁头、摇摆臂、马达、永磁铁等部件组成&#xff0c;其中一个硬盘中有多块盘片和多个磁头&#xff0c;堆叠在一起&#xff0c;工作时由盘片旋转和摇摆臂摇摆及逆行寻址从而运作&#xff0c;磁头可以对盘片…

FPGA 时钟多路复用

时钟多路复用 您可以使用并行和级联 BUFGCTRL 的组合构建时钟多路复用器。布局器基于时钟缓存 site 位置可用性查找最佳布局。 如果可能&#xff0c;布局器将 BUFGCTRL 布局在相邻 site 位置中以利用专用级联路径。如无法实现&#xff0c;则布局器将尝试将 BUFGCTRL 从…

C++底层学习预备:模板初阶

文章目录 1.编程范式2.函数模板2.1 函数模板概念2.2 函数模板原理2.3 函数模板实例化2.3.1 隐式实例化2.3.2 显式实例化 2.4 模板参数的匹配原则 3.类模板希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 进入STL库学习之前我们要先了解有关模板的…

Baklib如何在知识管理领域成为领军者与六款产品的综合评析

内容概要 在知识管理领域&#xff0c;Baklib凭借其卓越的技术和创新的产品线&#xff0c;已经确立了行业的领导地位。作为一个全面的知识管理平台&#xff0c;Baklib为企业提供了高效、便捷的知识存储和管理方案&#xff0c;帮助组织有效整合内外部知识资源。其主要特点包括强…

Baklib阐明企业内容管理与内容中台的本质差异

内容概要 在快速发展的数字时代&#xff0c;企业对信息的管理愈加重视。内容管理在企业日常运营中扮演了重要角色&#xff0c;而随着技术的不断进步&#xff0c;内容中台的概念逐渐走入视野。了解这两者的不同&#xff0c;不仅有助于企业更有效地管理内容&#xff0c;还能提升…

Java 大视界 -- Java 大数据在智能电网中的应用与发展趋势(71)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

deepseek 本地化部署和小模型微调

安装ollama 因为本人gpu卡的机器系统是centos 7, 直接使用ollama会报 所以ollama使用镜像方式进行部署&#xff0c; 拉取镜像ollama/ollama 启动命令 docker run -d --privileged -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama 查看ollama 是否启动…

【腾讯前端面试】纯css画图形

之前参加腾讯面试&#xff0c;第一轮是笔试&#xff0c;面试官发的试卷里有一题手写css画一个扇形、一个平行四边形……笔试时间还是比较充裕的&#xff0c;但是我对这题完全没有思路&#x1f62d;于是就空着了&#xff0c;最后也没过。 今天偶然翻到廖雪峰大佬的博客里提到了关…

物联网 STM32【源代码形式-ESP8266透传】连接OneNet IOT从云产品开发到底层MQTT实现,APP控制 【保姆级零基础搭建】

一、MQTT介绍 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;是一种基于发布/订阅模式的轻量级通讯协议&#xff0c;构建于TCP/IP协议之上。它最初由IBM在1999年发布&#xff0c;主要用于在硬件性能受限和网络状况不佳的情…

探秘Linux IO虚拟化:virtio的奇幻之旅

在当今数字化时代&#xff0c;虚拟化技术早已成为推动计算机领域发展的重要力量。想象一下&#xff0c;一台物理主机上能同时运行多个相互隔离的虚拟机&#xff0c;每个虚拟机都仿佛拥有自己独立的硬件资源&#xff0c;这一切是如何实现的呢&#xff1f;今天&#xff0c;就让我…

MATLAB实现单层竞争神经网络数据分类

一.单层竞争神经网络介绍 单层竞争神经网络&#xff08;Single-Layer Competitive Neural Network&#xff09;是一种基于竞争学习的神经网络模型&#xff0c;主要用于数据分类和模式识别。其核心思想是通过神经元之间的竞争机制&#xff0c;使得网络能够自动学习输入数据的特…

网络协议基础

文章目录 前言一、网络协议分层1.应用层2.传输层3.网络层4.数据链路层5.物理层 二、图解IP1.IP基本认识&#xff08;1&#xff09;IP的作用&#xff08;2&#xff09;IP与MAC的关系 2.IP地址的基础知识&#xff08;1&#xff09;IP地址的定义&#xff08;2&#xff09;IP地址的…

(CICD)自动化构建打包、部署(Jenkins + maven+ gitlab+tomcat)

一、平滑发布与灰度发布 **什么叫平滑&#xff1a;**在发布的过程中不影响用户的使用&#xff0c;系统不会因发布而暂停对外服务&#xff0c;不会造成用户短暂性无法访问&#xff1b; **什么叫灰度&#xff1a;**发布后让部分用户使用新版本&#xff0c;其它用户使用旧版本&am…

【C语言】自定义类型讲解

文章目录 一、前言二、结构体2.1 概念2.2 定义2.2.1 通常情况下的定义2.2.2 匿名结构体 2.3 结构体的自引用和嵌套2.4 结构体变量的定义与初始化2.5 结构体的内存对齐2.6 结构体传参2.7 结构体实现位段 三、枚举3.1 概念3.2 定义3.3 枚举的优点3.3.1 提高代码的可读性3.3.2 防止…

deep generative model stanford lecture note3 --- latent variable

1 Introduction 自回归模型随着gpt的出现取得很大的成功&#xff0c;还是有很多工程上的问题并不是很适合使用自回归模型&#xff1a; 1&#xff09;自回归需要的算力太大&#xff0c;满足不了实时性要求&#xff1a;例如在自动驾驶的轨迹预测任务中&#xff0c;如果要用纯自回…

变形金刚多元宇宙

涉及的公司&#xff1a; 日本Takara公司 Diaclone可变形机器人玩具 Microman可变形机器人玩具 孩之宝 孩之宝与Takara签订协议后&#xff0c;孩之宝开始使用Takara的专利进行研发。 漫威 为了推广玩具&#xff0c;1984年5月&#xff0c;孩之宝玩具与漫威《变形金刚》漫画试探…

Day33【AI思考】-分层递进式结构 对数学数系的 终极系统分类

文章目录 **分层递进式结构** 对数学数系的 **终极系统分类**总览**一、数系演化树&#xff08;纵向维度&#xff09;**数系扩展逻辑树**数系扩展逻辑** **二、代数结构对照表&#xff08;横向维度&#xff09;**数系扩展的数学意义 **三、几何对应图谱&#xff08;空间维度&am…