无人机对地面运动目标定位---获取目标的移动方向和速度
目录
一、引子
我们利用单目无人机通过等时间间隔拍照的形式对地面某移动目标进行定位,当前,我们已经获得了每张相片上该目标的三维坐标,并且知道该无人机在飞行过程中拍照的时间间隔,那么我们就可以通过一定的计算,得到目标的运动方向和运动速度。
二、代码解释
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的博客 课设专栏 :学生成绩管理系统 专业知识专栏: 专业知识 文章目录 🍉强化学习与有监督学习的区别 🍈数据特点 🍈学习目标 🍈反馈机制 🍈策略…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
PostgreSQL——环境搭建
一、Linux # 安装 PostgreSQL 15 仓库 sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-$(rpm -E %{rhel})-x86_64/pgdg-redhat-repo-latest.noarch.rpm# 安装之前先确认是否已经存在PostgreSQL rpm -qa | grep postgres# 如果存在࿰…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)
前言: 双亲委派机制对于面试这块来说非常重要,在实际开发中也是经常遇见需要打破双亲委派的需求,今天我们一起来探索一下什么是双亲委派机制,在此之前我们先介绍一下类的加载器。 目录 编辑 前言: 类加载器 1. …...
