无人机对地面运动目标定位---获取目标的移动方向和速度
目录
一、引子
我们利用单目无人机通过等时间间隔拍照的形式对地面某移动目标进行定位,当前,我们已经获得了每张相片上该目标的三维坐标,并且知道该无人机在飞行过程中拍照的时间间隔,那么我们就可以通过一定的计算,得到目标的运动方向和运动速度。
二、代码解释
1.导入的数据是由相片名称及目标点的三维数据构成的txt文件,所以我们需要建立字符串分割函数,获取txt文件内的数据。
2.定义圆周率数值
3.定义方向计算函数
4.从txt文件提取所需信息
5.计算目标在相邻相片间的方向变化角
6.计算目标在相邻相片间的移动距离及运动速度
三、完整代码展示
四、结果展示
本文所有代码均由CSDN用户CV-X.WANG提供,任何个人或者团体,不得进行商用和教学活动,引用或部分引用,均需获得授权。
一、引子
我们利用单目无人机通过等时间间隔拍照的形式对地面某移动目标进行定位,当前,我们已经获得了每张相片上该目标的三维坐标,并且知道该无人机在飞行过程中拍照的时间间隔,那么我们就可以通过一定的计算,得到目标的运动方向和运动速度。
二、代码解释
1.导入的数据是由相片名称及目标点的三维数据构成的txt文件,所以我们需要建立字符串分割函数,获取txt文件内的数据。
//字符串分割
vector<string> split(const string &s, char delimiter) {vector<string> tokens;string token;istringstream tokenStream(s);while (getline(tokenStream, token, delimiter)) {tokens.push_back(token);}return tokens;
}
2.定义圆周率数值
#define M_PI 3.14159265358979323846 // pi
3.定义方向计算函数
为获取目标在平面方向的移动方向,本文采用了在军事领域常见的360°方向法。即以正北为0°方向,顺时针方向为0-360°,比如说,正东方向:在我们的方向系统中即为90°方向。
这其中,
double lon1_rad = lon1 * M_PI / 180.0;
double lat1_rad = lat1 * M_PI / 180.0;
double lon2_rad = lon2 * M_PI / 180.0;
double lat2_rad = lat2 * M_PI / 180.0;
为弧度制。
//方向函数
double calculateDirectionAngle(double lon1, double lat1, double lon2, double lat2) {// Convert degrees to radiansdouble lon1_rad = lon1 * M_PI / 180.0;double lat1_rad = lat1 * M_PI / 180.0;double lon2_rad = lon2 * M_PI / 180.0;double lat2_rad = lat2 * M_PI / 180.0;// Calculate delta longitude and convert to radiansdouble delta_lon_rad = (lon2 - lon1) * M_PI / 180.0;// Calculate y and x componentsdouble y = sin(delta_lon_rad) * cos(lat2_rad);double x = cos(lat1_rad) * sin(lat2_rad) - sin(lat1_rad) * cos(lat2_rad) * cos(delta_lon_rad);// Calculate direction angle in radiansdouble direction_rad = atan2(y, x);// Convert direction angle to degreesdouble direction_deg = direction_rad * 180.0 / M_PI;// Ensure direction angle is within [0, 360) degreesif (direction_deg < 0) {direction_deg += 360.0;}return direction_deg;
}
4.从txt文件提取所需信息
ifstream file("LBH.txt");if (!file.is_open()) {cerr << "Could not open the file!" << endl;return 1;}string line;// Skip the header linegetline(file, line);vector<vector<string>> extractedData;// Read each line from the filewhile (getline(file, line)) {vector<string> columns = split(line, '\t');if (columns.size() < 16) {cerr << "Invalid line format" << endl;continue;}// Extract the required columns: 0, 13, 14, 15vector<string> extractedColumns;extractedColumns.push_back(columns[0]); // Image NameextractedColumns.push_back(columns[13]); // LongitudeextractedColumns.push_back(columns[14]); // LatitudeextractedColumns.push_back(columns[15]); // AltitudeextractedData.push_back(extractedColumns);}file.close();
5.计算目标在相邻相片间的方向变化角
cout << "Direction angles between adjacent image centers:" << endl;for (size_t i = 1; i < extractedData.size(); ++i) {//三角函数计算用弧度制double lon1 = (stod(extractedData[i - 1][1]))* M_PI/180; // Longitude double lat1 = (stod(extractedData[i - 1][2]))* M_PI / 180; // Latitude double lon2 = (stod(extractedData[i][1]))* M_PI / 180; // Longitude double lat2 = (stod(extractedData[i][2]))* M_PI / 180; // Latitude //计算方向变化角也要用弧度制double direction_angle = calculateDirectionAngle(lon1, lat1, lon2, lat2);cout << "lon1=" << lon1 << endl << "lat1=" << lat1 << endl << "lon2=" << lon2 << endl << "lat2=" << lat2 << endl;// Output Directioncout << "Direction from " << extractedData[i - 1][0] << " to " << extractedData[i][0] << ": " << direction_angle << " degrees" << endl;
6.计算目标在相邻相片间的移动距离及运动速度
请注意:此处我们获得距离的计算式为:
这只是最简单的一个演示,实际情况下,我们需要考虑坐标系统、测区位置等等一系列的条件,从而获得更为精准的Distance。
double lon2_1 = lon2 - lon1;double lat2_1 = lat2 - lat1;double lon_ = lon2_1 / 2;//1/2的Δlondouble lat_ = lat2_1 / 2; //1 / 2的Δlatdouble sin2lon_ = sin(lon_)*sin(lon_);//sin²(1/2Δlon)double sin2lat_ = sin(lat_)*sin(lat_); //sin²(1 / 2Δlat)double cos_lat1 = cos(lat1);double cos_lat2 = cos(lat2);double sqrtA = sqrt(sin2lat_+ cos_lat1* cos_lat2*sin2lon_);//cout << "Direction from " << extractedData[i - 1][0] << " to " << extractedData[i][0] << ": " << "sqrtA =" << sqrtA << endl;double asinA = asin(sqrtA);//长半轴 短半轴 单位是mint a_r = 6378137.0;int b_r = 6356752;double Earth_R = (2 * a_r + b_r) / 3;double Distance = 2 * Earth_R*asinA;cout << "Distance From " << extractedData[i - 1][0] << " to " << extractedData[i][0] << ": " << "=" << Distance <<" meter"<< endl;int time = 3;//拍照间隔 sdouble speed = Distance / time;cout << "Speed From " << extractedData[i - 1][0] << " to " << extractedData[i][0] << ": " << "=" << speed << " meter per second" << endl;}
三、完整代码展示
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cmath>using namespace std;
#define M_PI 3.14159265358979323846 // pi
// Function to split a string by a delimiter
vector<string> split(const string &s, char delimiter) {vector<string> tokens;string token;istringstream tokenStream(s);while (getline(tokenStream, token, delimiter)) {tokens.push_back(token);}return tokens;
}// direction angle in degrees
//原理是 在平面上以正北方向为0°方向,顺时针为0-360°
double calculateDirectionAngle(double lon1, double lat1, double lon2, double lat2) {// Convert degrees to radiansdouble lon1_rad = lon1 * M_PI / 180.0;double lat1_rad = lat1 * M_PI / 180.0;double lon2_rad = lon2 * M_PI / 180.0;double lat2_rad = lat2 * M_PI / 180.0;// Calculate delta longitude and convert to radiansdouble delta_lon_rad = (lon2 - lon1) * M_PI / 180.0;// Calculate y and x componentsdouble y = sin(delta_lon_rad) * cos(lat2_rad);double x = cos(lat1_rad) * sin(lat2_rad) - sin(lat1_rad) * cos(lat2_rad) * cos(delta_lon_rad);// Calculate direction angle in radiansdouble direction_rad = atan2(y, x);// Convert direction angle to degreesdouble direction_deg = direction_rad * 180.0 / M_PI;// Ensure direction angle is within [0, 360) degreesif (direction_deg < 0) {direction_deg += 360.0;}return direction_deg;
}int main() {ifstream file("LBH.txt");if (!file.is_open()) {cerr << "Could not open the file!" << endl;return 1;}string line;// Skip the header linegetline(file, line);vector<vector<string>> extractedData;// Read each line from the filewhile (getline(file, line)) {vector<string> columns = split(line, '\t');if (columns.size() < 16) {cerr << "Invalid line format" << endl;continue;}// Extract the required columns: 0, 13, 14, 15vector<string> extractedColumns;extractedColumns.push_back(columns[0]); // Image NameextractedColumns.push_back(columns[13]); // LongitudeextractedColumns.push_back(columns[14]); // LatitudeextractedColumns.push_back(columns[15]); // AltitudeextractedData.push_back(extractedColumns);}file.close();// Calculate direction angles between adjacent image centerscout << "Direction angles between adjacent image centers:" << endl;for (size_t i = 1; i < extractedData.size(); ++i) {//三角函数计算用弧度制double lon1 = (stod(extractedData[i - 1][1]))* M_PI/180; // Longitude double lat1 = (stod(extractedData[i - 1][2]))* M_PI / 180; // Latitude double lon2 = (stod(extractedData[i][1]))* M_PI / 180; // Longitude double lat2 = (stod(extractedData[i][2]))* M_PI / 180; // Latitude //计算方向变化角也要用弧度制double direction_angle = calculateDirectionAngle(lon1, lat1, lon2, lat2);cout << "lon1=" << lon1 << endl << "lat1=" << lat1 << endl << "lon2=" << lon2 << endl << "lat2=" << lat2 << endl;// Output Directioncout << "Direction from " << extractedData[i - 1][0] << " to " << extractedData[i][0] << ": " << direction_angle << " degrees" << endl;double lon2_1 = lon2 - lon1;double lat2_1 = lat2 - lat1;double lon_ = lon2_1 / 2;//1/2的Δlondouble lat_ = lat2_1 / 2; //1 / 2的Δlatdouble sin2lon_ = sin(lon_)*sin(lon_);//sin²(1/2Δlon)double sin2lat_ = sin(lat_)*sin(lat_); //sin²(1 / 2Δlat)double cos_lat1 = cos(lat1);double cos_lat2 = cos(lat2);double sqrtA = sqrt(sin2lat_+ cos_lat1* cos_lat2*sin2lon_);//cout << "Direction from " << extractedData[i - 1][0] << " to " << extractedData[i][0] << ": " << "sqrtA =" << sqrtA << endl;double asinA = asin(sqrtA);//长半轴 短半轴 单位是mint a_r = 6378137.0;int b_r = 6356752;double Earth_R = (2 * a_r + b_r) / 3;double Distance = 2 * Earth_R*asinA;cout << "Distance From " << extractedData[i - 1][0] << " to " << extractedData[i][0] << ": " << "=" << Distance <<" meter"<< endl;int time = 3;//拍照间隔 sdouble speed = Distance / time;cout << "Speed From " << extractedData[i - 1][0] << " to " << extractedData[i][0] << ": " << "=" << speed << " meter per second" << endl;}//cin.get();return 0;
}
四、结果展示
本文所有代码均由CSDN用户CV-X.WANG提供,任何个人或者团体,不得进行商用和教学活动,引用或部分引用,均需获得授权。
相关文章:

无人机对地面运动目标定位---获取目标的移动方向和速度
目录 一、引子 我们利用单目无人机通过等时间间隔拍照的形式对地面某移动目标进行定位,当前,我们已经获得了每张相片上该目标的三维坐标,并且知道该无人机在飞行过程中拍照的时间间隔,那么我们就可以通过一定的计算,得…...

管理才是最根本的核心竞争力
相信大家对于华为提出的“管理是核心竞争力”“管理才是企业的核心竞争力”等言论并不陌生,而华为的确也一直践行这样的理念。比如,在华为发展历史上很艰难的2002年,华为仍然坚持重点抓管理。总裁任正非后来提到:“2002年华为快崩…...
Raid阵列中硬盘损坏后,新硬盘可以直接换上吗?
RAID更换的方式基本类似,这里以RAID 1为例。 1. 关闭服务器:确保服务器或RAID控制器处于关闭或已停止状态,以避免数据写入或损坏。确定损坏硬盘:通过RAID控制器的管理界面,确定哪一块硬盘在RAID 中损坏。 2. 拆卸原硬…...

Python爬虫康复训练——笔趣阁《神魂至尊》
还是话不多说,很久没写爬虫了,来个bs4康复训练爬虫,正好我最近在看《神魂至尊》,爬个txt文件下来看看 直接上代码 """ 神魂至尊网址-https://www.bqgui.cc/book/1519/ """ import requests from b…...
Kaptcha验证码
Kaptcha验证码 Kaptcha 是一个用于生成验证码的开源库,在 Java 中使用它可以轻松地为应用程序添加验证码功能。 一、引入依赖 首先,需要在项目的 pom.xml 文件(如果是 Maven 项目)中添加 Kaptcha 的依赖: <depend…...

Rufus 制作启动盘 | 便携的工作空间
唠唠闲话 最近服务器硬盘故障多,在修复过程中,学习了一些操作,这里做个记录。本期主要介绍 U盘启动盘的制作,以及持久化存储。 U 盘启动盘 镜像选择 Ubuntu 的版本命名遵循 “Adjective Animal” 的模式,即 “形容…...
python函数参数
Python 函数参数是函数定义时用于接收传递给函数的值的变量。在Python中,函数可以有多种类型的参数,这增加了函数的灵活性和可重用性。下面是一些主要的参数类型: 1. 位置参数(Positional Arguments) 位置参数是最常…...

深入理解 XML 和 HTML 之间的区别
在现代网络技术的世界中,XML(可扩展标记语言)和 HTML(超文本标记语言) 是两个非常重要的技术。尽管它们都使用标签和属性的格式来描述数据,但它们在形式和用途上有显著的区别。 概述 什么是 XMLÿ…...

代码随想录算法训练营第四十四天|188.买卖股票的最佳时机IV、309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费
188.买卖股票的最佳时机IV 题目链接:188.买卖股票的最佳时机IV 文档讲解:代码随想录 状态:不会 思路: 在股票买卖1使用一维dp的基础上,升级成二维的即可。 定义dp[k1][2],其中 dp[j][0] 表示第j次交易后持…...

YOLOv8改进 添加CVPR2024 PKINet中注意力机制CAAttention
一、PKINet论文 论文地址:2403.06258 (arxiv.org) 二、CAAttention结构 CAA(Context Anchor Attention)注意力模块是一种用于捕捉长距离上下文信息的并行模块。 在计算机视觉领域中,上下文信息是指与目标物体或任务相关的周围环境和语境信息。上下文信息可以帮助我们更好…...

油猴Safari浏览器插件:Tampermonkey for Mac 下载
Tampermonkey 是一个强大的浏览器扩展,用于运行用户脚本,这些脚本可以自定义和增强网页的功能。它允许用户在网页上执行各种自动化任务,比如自动填写表单、移除广告、改变页面布局等。适用浏览器: Tampermonkey 适用于多数主流浏览…...
如何在Vue中添加事件监听器
在Vue中添加事件监听器主要有两种方式:在模板中直接添加和使用Vue实例的方法。以下将详细解释这两种方法。 1. 在模板中直接添加 在Vue的模板中,你可以直接在HTML元素上使用v-on指令(或其简写形式)来监听DOM事件,并在…...

软设之UML图中的用例图
UML图中用例图 用例图描述一组用例,参与者及它们之间的关系 关系包括: 包含关系,扩展关系,泛化关系 用例建模的流程: 识别参与者 合并需求获得用例 细化用例描述 调整用例模型...
弹性伸缩高性能计算服务一一黑石裸金属服务器
在电商、直播、游戏等业务场景中,对服务器的性能、安全性和稳定性要求尤为苛刻。黑石裸金属服务器作为一种创新的计算服务,以其独特的优势,满足了这些行业对高性能计算服务的迫切需求。本文将详细解析黑石裸金属服务器的优势,并在…...

欢乐钓鱼大师攻略:西沙群岛攻略,内置自动辅助云手机!
《欢乐钓鱼大师》是一款以钓鱼为主题的休闲游戏,玩家可以在虚拟的钓鱼世界中体验真实的钓鱼乐趣,并通过捕捉各种珍稀鱼类来提升自己的钓鱼技能和成就。在这篇攻略中,我们将重点介绍如何在西沙群岛区域有效地捕捉各种典藏鱼类,并提…...
Apipost接口测试工具的原理及应用详解(六)
本系列文章简介: 随着软件行业的快速发展,API(应用程序编程接口)作为不同软件组件之间通信的桥梁,其重要性日益凸显。API的质量直接关系到软件系统的稳定性、性能和用户体验。因此,对API进行严格的测试成为…...
矩阵的奇异值(Singular Values)
矩阵的奇异值(Singular Values)是奇异值分解(SVD)过程中得到的一组重要特征值。它们在许多应用中非常重要,如信号处理、数据压缩和统计学等。以下是对奇异值及其计算和性质的详细解释: 奇异值分解…...

清空flowable的表定义的相关表
更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio 演示地址:RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码: h…...
Tailwind CSS 在vue里 的使用
在Vue项目中使用Tailwind CSS,你需要按照以下步骤操作: 安装Tailwind CSS npm包: npm install -D tailwindcss postcss autoprefixer 使用Tailwind CSS CLI工具创建配置文件: npx tailwindcss init -p 3.在tailwind.config.js中…...

【人工智能】--强化学习(2.0)
个人主页:欢迎来到 Papicatch的博客 课设专栏 :学生成绩管理系统 专业知识专栏: 专业知识 文章目录 🍉强化学习与有监督学习的区别 🍈数据特点 🍈学习目标 🍈反馈机制 🍈策略…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...

零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...

GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...

Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...