unity 调用C++追踪物体后的位姿通过 dll,左右手坐标转化2

news2024/12/30 1:09:48

外参矩阵转四元数,左右手坐标系转化1_天人合一peng的博客-CSDN博客

在之前1的基础上更新

通过定位已经求得了物体的4*4的位姿矩阵,将其变化为四元数并从opengl的右手坐标转化为unity的左手坐标系。

body2world_pose().matrix()为计算得到的4*4的位姿矩阵

    body1_world2body_pose.matrix() <<
        1.0f, 0.0f, 0.0f, 0.095f,
        0.0f, 1.0f, 0.0f, 0.1f,
        0.0f, 0.0f, 1.0f, -0.4f,
        0.0f, 0.0f, 0.0f, 1.0f;

------------------------------C++ dll----------------------------

			Eigen::Matrix<float, 4, 4> matrix_body2world_pose;
			//Eigen::Matrix<float, 3, 3> matrix_rotation;
			Eigen::Matrix3d matrix_rotation;

			Eigen::Quaterniond matrix_quarternion;

			matrix_body2world_pose = body1_ptr->body2world_pose().matrix();
			//body1_ptr->geometry2world_pose().matrix();
			//for (size_t i = 0; i < 4; i++)
			//{
			//	for (size_t j = 0; j < 4; j++)
			//	{
			//		std::cout << matrix_body2world_pose(i, j) << "\t";
			//	}

			//}

			//取出旋转矩阵
			for (size_t i = 0; i < 3; i++)
			{
				for (size_t j = 0; j < 3; j++)
				{
					matrix_rotation(i, j) = matrix_body2world_pose(i, j);
				}
			}
			
			//matrix_rotation(0, 2) *= -1;
			//matrix_rotation(1, 2) *= -1;
			//matrix_rotation(2, 0) *= -1;
			//matrix_rotation(2, 1) *= -1;

			//将旋转矩阵转化为四元数
			matrix_quarternion = Eigen::Quaterniond(matrix_rotation);
			//std::cout << "---------------matrix_quarternion-----------------" << std::endl;
			std::cout << matrix_quarternion << std::endl;
			//std::cout << matrix_quarternion.x() << "\t" <<matrix_quarternion.y() << "\t"  
			//	<< matrix_quarternion.z() << "\t" << matrix_quarternion.z() << "\t" << std::endl;


			//右手坐标转化为左手坐标:旋转 x,z取反,平移y取反

			保存表示旋转的四元数和平移的值
			float location[7] = { -matrix_quarternion.x(), matrix_quarternion.y(), -matrix_quarternion.z(), matrix_quarternion.w(),
									matrix_body2world_pose(0, 3), -matrix_body2world_pose(1, 3),matrix_body2world_pose(2, 3) };
			memcpy(pos_array, location, sizeof(float) * 7);

另一种求四元数方法

//计算四元数

int sign(float x)
{
	return x >= 0 ? 1 : -1;
}

float myMax(float x, float y)
{
	return x > y ? x : y;
}

void QuaternionFromMatrix(const cv::Mat& R, float quat[])
{
	// Adapted from: http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
	/*quat[0] = (float)sqrt(myMax(0.0, 1 + R.ptr<float>(0)[0] + R.ptr<float>(1)[1] + R.ptr<float>(2)[2]))/2;
	quat[1] = (float)sqrt(myMax(0.0, 1 + R.ptr<float>(0)[0] - R.ptr<float>(1)[1] - R.ptr<float>(2)[2]))/2;
	quat[2] = (float)sqrt(myMax(0.0, 1 - R.ptr<float>(0)[0] + R.ptr<float>(1)[1] - R.ptr<float>(2)[2]))/2;
	quat[3] = (float)sqrt(myMax(0.0, 1 - R.ptr<float>(0)[0] - R.ptr<float>(1)[1] + R.ptr<float>(2)[2]))/2;
	quat[1] *= sign(R.ptr<float>(2)[1] - R.ptr<float>(1)[2]);
	quat[2] *= sign(R.ptr<float>(0)[2] - R.ptr<float>(2)[0]);
	quat[3] *= sign(R.ptr<float>(1)[0] - R.ptr<float>(0)[1]);*/
	//R.convertTo(R, CV_32F);
	quat[0] = (float)sqrt(myMax(0.0, 1 + R.at<float>(0, 0) + R.at<float>(1, 1) + R.at<float>(2, 2))) / 2;

	quat[1] = (float)sqrt(myMax(0.0, 1 + R.at<float>(0, 0) - R.at<float>(1, 1) - R.at<float>(2, 2))) / 2;
	quat[2] = (float)sqrt(myMax(0.0, 1 - R.at<float>(0, 0) + R.at<float>(1, 1) - R.at<float>(2, 2))) / 2;
	quat[3] = (float)sqrt(myMax(0.0, 1 - R.at<float>(0, 0) - R.at<float>(1, 1) + R.at<float>(2, 2))) / 2;

	quat[1] *= sign(R.at<float>(2, 1) - R.at<float>(1, 2));
	quat[2] *= sign(R.at<float>(0, 2) - R.at<float>(2, 0));
	quat[3] *= sign(R.at<float>(1, 0) - R.at<float>(0, 1));
	//quat[0]为w, quat[1]为x, quat[2]为y, quat[3]为z
}
			另一种方法计算四元数
			cv::Mat body_r = cv::Mat(3, 3, CV_32F);
			cv::Mat matrix_r = cv::Mat(3, 3, CV_32F);
			//取出旋转矩阵
			for (size_t i = 0; i < 3; i++)
			{
				for (size_t j = 0; j < 3; j++)
				{
					matrix_r.at<float>(i,j) = matrix_body2world_pose(i, j);
				}
			}


			float siyuanshu[4] = { 0, 0, 0, 0 };
			QuaternionFromMatrix(matrix_r, siyuanshu);


			cv::Mat matrix_trans = cv::Mat(3, 1, CV_32F);
			matrix_trans.at<float>(0, 0) = matrix_body2world_pose(0, 3);
			matrix_trans.at<float>(1, 0) = matrix_body2world_pose(1, 3);
			matrix_trans.at<float>(2, 0) = matrix_body2world_pose(2, 3);



			//右手坐标转化为左手坐标:旋转 x,z取反,平移y取反
			保存表示旋转的四元数和平移的值
			float location[7] = { siyuanshu[0], -siyuanshu[1], siyuanshu[2], -siyuanshu[3],
									 matrix_body2world_pose(0, 3), -matrix_body2world_pose(1, 3), matrix_body2world_pose(2, 3) };
			memcpy(pos_array, location, sizeof(float) * 7);

------------------------------------------------------unity---------------------------------

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Runtime.InteropServices;


public class useDll : MonoBehaviour
{

    [DllImport("run_on_camera_sequence")]
    static extern void main();

    [DllImport("run_on_camera_sequence")]
    static extern int start_track(int iteration, float[] pos_array, int[] is_update);



    private float[] pos_array = new float[7];
    private int[] is_update = new int[2];



    bool stop_run = false;
    public GameObject Target;



    int iteration = 0;

    // Start is called before the first frame update
    void Start()
    {

        main();
        //print(is_update[0]);

    }

    // Update is called once per frame
    void Update()
    {

        start_track(iteration, pos_array, is_update);
        iteration += 1;

        // unity Quaternion的赋值顺序是x,y,z,w
        //Target.transform.localRotation = new Quaternion( pos_array[1], pos_array[2], pos_array[3], pos_array[0]);
        Target.transform.localRotation = new Quaternion(pos_array[0], pos_array[1], pos_array[2], pos_array[3]);
        Target.transform.localPosition = new Vector3(pos_array[4], pos_array[5], pos_array[6]);


        print("-------[0]------" + is_update[0] + "-------[1]------" + is_update[1]);

    }
}

在unity赋值是一定是先赋旋转再赋平移才会正确,先后不一样,因为,旋转先赋值相当于在坐标原点旋转这和其不在坐标原点的旋转效果一样,但如果先平移,后再旋转就不是一回事了。

unity里面先将物体的旋转调整为opengl沉浸的和unity中相机看的一样。我想这个是必须的?为什么呢,物体的位姿是实时给------------------但实事证明这样是对的。

 然后在motopart上给物体赋值

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Go语言之结构体

在实际开发中&#xff0c;我们可以将一组类型不同的、但是用来描述同一件事物的变量放到结构体中。例如&#xff0c;在校学生有姓名、年龄、身高、成绩等属性&#xff0c;学了结构体后&#xff0c;我们就不需要再定义多个变量了&#xff0c;将它们都放到结构体中即可。 在Go语言…

基于linux下的高并发服务器开发(第三章)- 3.7 线程属性

int pthread_attr_init(pthread_attr_t *attr);- 初始化线程属性变量int pthread_attr_destroy(pthread_attr_t *attr);- 释放线程属性的资源int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate);- 获取线程分离的状态属性int pthread_attr_setdet…

【Redis】所以延迟双删有啥用

文章目录 1、何为延时双删2、常用缓存策略2.1、介绍2.2、先删缓存后更库2.3、先更库后删缓存2.4、使用场景 3、延时双删实现4、为什么要使用延时双删5、方案选择6、延时双删真的完美吗7、如何确定延时的时间 1、何为延时双删 延迟双删&#xff08;Delay Double Delete&#xf…

Jupyter 安装、简单操作及工作路径更换

一、Jupyter下载安装 pip install jupyterAnaconda是Python另一个非常流行的发行版&#xff0c;它之后有着自己的叫做“conda”的安装工具。用户可以使用它来安装很多第三方包。然而&#xff0c;Anaconda会预装很多包&#xff0c;包括了Jupyter Notebook,所以若已经安装了Anac…

VUE3 语法教程

vue3 起步 刚开始学习 Vue&#xff0c;我们不推荐使用 vue-cli 命令行工具来创建项目&#xff0c;更简单的方式是直接在页面引入 vue.global.js 文件来测试学习。 Vue3 中的应用是通过使用 createApp 函数来创建的&#xff0c;语法格式如下&#xff1a; const app Vue.crea…

cmder 使用简介

文章目录 1. cmder 简介2. 下载地址3. 安装4. 配置环境变量5. 添加 cmder 到右键菜单6. 解决中文乱码问题 1. cmder 简介 cmder 是一个增强型命令行工具&#xff0c;不仅可以使用 windows 下的所有命令&#xff0c;更爽的是可以使用 linux的命令, shell 命令。 2. 下载地址 …

机器学习深度学习——预备知识(下)

机器学习&&深度学习——预备知识&#xff08;下&#xff09; 4 微积分4.1 导数和微分4.2 偏导数4.3 梯度4.4 链式法则 5 自动微分5.1 简单例子5.2 非标量变量的反向传播5.3 分离计算5.4 Python控制流的梯度计算 6 概率6.1 基本概率论6.1.1 概率论公理 6.2 处理多个随机…

5.1 Bootstrap 插件概览

文章目录 Bootstrap 插件概览data 属性编程方式的 API避免命名空间冲突事件 Bootstrap 插件概览 在前面 布局组件 章节中所讨论到的组件仅仅是个开始。Bootstrap 自带 12 种 jQuery 插件&#xff0c;扩展了功能&#xff0c;可以给站点添加更多的互动。即使您不是一名高级的 Jav…

超参数优化 - 贝叶斯优化的实现

目录 1. 基于Bayes_opt实现GP优化 1.1 定义目标函数 1.2 定义参数空间 1.3 定义优化目标函数的具体流程 4. 定义验证函数&#xff08;非必须&#xff09; 5. 执行实际优化流程 2. 基于HyperOpt实现TPE优化 2.1 定义目标函数 2.2 定义参数空间 2.3 定义优化目标函数的…

Asp.Net WebForm ViewState

ViewState用于保存服务器控件(runat"server")状态便于在触发回调后&#xff08;PostBack&#xff09;恢复页面。 页面拖入一个Form id"form1" runat"server",里面添加一个<asp:Button id"Button1" Text"删除" OnClick&q…

python:对 GEDI 数据进行高斯滤波处理

作者:CSDN @ _养乐多_ 在本篇博客中,我们将学习如何使用 Python 对 GEDI(Global Ecosystem Dynamics Investigation)激光雷达数据进行高斯滤波处理。高斯滤波是一种平滑滤波方法,可以有效减少噪声和突变,提高数据的平滑性和连续性。我们将使用 pandas 和 scipy.signal 库…

STM32MP157驱动开发——LED 驱动( GPIO 子系统)

文章目录 编写思路GPIO子系统的LED驱动程序(stm32mp157)如何找到引脚功能和配置信息在设备树中添加 Pinctrl 信息leddrv.cledtest.cMakefile编译测试 编写思路 阅读&#xff1a;STM32MP157驱动开发——GPIO 和 和 Pinctrl 子系统的概念可知利用GPIO子系统去编写LED驱动&#x…

Mysql基础(下)之函数,约束,多表查询,事务

&#x1f442; 回到夏天&#xff08;我多想回到那个夏天&#xff09; - 傲七爷/小田音乐社 - 单曲 - 网易云音乐 截图自 劈里啪啦 -- 黑马Mysql&#xff0c;仅学习使用 &#x1f447;原地址 47. 基础-多表查询-表子查询_哔哩哔哩_bilibili 目录 &#x1f982;函数 &#x1f3…

Spark(35):Structured Streaming 概述

目录 0. 相关文章链接 1. 什么是Structured Streaming 2. Structure Streaming 快速入门 2.1. 导入依赖 2.2. 代码实现 2.3. 程序测试 2.4. 代码说明 0. 相关文章链接 Spark文章汇总 1. 什么是Structured Streaming 从 spark2.0 开始, spark 引入了一套新的流式计算模…

新Viewport单位

本文为翻译本文译者为 360 奇舞团前端开发工程师原文标题&#xff1a;New Viewport Units原文作者&#xff1a;Ahmad Shadeed原文地址&#xff1a;https://ishadeed.com/article/new-viewport-units/ 自 2012 年以来&#xff0c;我们一直在使用 CSS viewport 单位。它们对于帮助…

RGB简单人脸活体检测(Liveness Detection)

参考&#xff1a; https://github.com/minivision-ai/Silent-Face-Anti-Spoofing&#xff08;主要这个库&#xff09; https://github.com/computervisioneng/face-attendance-system&#xff08;使用案例&#xff09; ##概念&#xff1a; 活体检测是指针对人脸识别过程中的人脸…

TSDB - VictoriaMetrics 技术原理浅析

一、前言 在监控领域&#xff0c;通常需要指标存储组件TSDB&#xff0c;目前开源的TSDB组件比较多&#xff0c;各个组件性能、高可用性、维护成本等等各有差异。本文不分析选型问题&#xff0c;重点讲解VictoriaMetrics&#xff08;后面简称为vm&#xff09;。 有兴趣的朋友建议…

Linux中常用的一些shell命令

很多的时候我们知道有一个命令&#xff0c;但不知道它的详细用法&#xff0c;可以来搜索下。但有些时候压根不知道有这个命令&#xff0c;比如vimdiff和diff这两个命令&#xff0c;知道人就比较少。 本节内容主要汇总一下Linux中常用的一些shell命令。 1. 文件和目录操作 ls …

win11安装MySQL5.7.43的问题清单

文章目录 1、win11查看自己电脑有没有安装mysql法1法2 2、完全清除之前安装的mysql3、 mysql的安装法1法2 4、遇到的一些问题1) ‘mysql‘不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件2) 忘记mysql的密码3)mysql启动不了:本地计算机上的MySQL服务启动后停止4…

机器学习深度学习——torch.nn模块

机器学习&&深度学习——torch.nn模块 卷积层池化层激活函数循环层全连接层 torch.nn模块包含着torch已经准备好的层&#xff0c;方便使用者调用构建网络。 卷积层 卷积就是输入和卷积核之间的内积运算&#xff0c;如下图&#xff1a; 容易发现&#xff0c;卷积神经网…