2022年吉林省智能无人机仿真挑战赛参赛心得(ROS+gazebo)

本文主要是介绍2022年吉林省智能无人机仿真挑战赛参赛心得(ROS+gazebo),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

比赛介绍

知识储备

示例代码

飞机飞行

人脸识别 

提交代码


首先这算是我参加的比赛中算是赛前准备比较成体系的一个比赛吧,所以就想趁着还记得写一点心得,这个比赛是吉林省机器人大赛的一个分赛道,智能无人机仿真挑战赛,我的队伍也是在这个比赛中以1分28秒的成绩获得了吉林省一等奖季军的成绩。

比赛介绍

该比赛主要就是在ubuntu系统下使用ros对gazebo环境下的仿真无人机进行操控,按照题目给出的得分点得分,得分相同的队伍按照完成时间排序,比赛使用的虚拟机和仿真环境比赛组委会是会提供的。

知识储备

做这个比赛还是需要一些知识储备的,首先要对ubuntu下的ros有所了解,关于一些ros的基础操作是要学会的,例如功能包和工作空间的创建,话题的创建和收发,对于功能包的编译等,这里比较推荐古月居的教程,真的很细致;对于所掌握的语言,一般就是C++和python,其实并不需要我们很是精通,无人机仿真赛官方提供了很多的示例代码,我们只需要在示例代码的基础上进行修改其实就足够我进行比赛了

示例代码

这里主要介绍一下官方给我们提供的文件的结构讲解,主要能够让飞机飞行的代码都存在Home文件夹中的sim_ws这个工作空间之中

 在该文件夹下,其中主要的代码存放在px4_com这个功能包之中

 在该目录下的文件都很重要:

config文件夹中主要储存着yaml参数列表文件,方便对无人机进行调参

launch文件夹中主要储存着编译后的可执行文件

scripts文件夹中主要储存python文件,python文件是可以直接执行的,不需要编译,但是如果需要调用外部库文件,也是需要编写launch文件的

src中主要储存的就是主要控制飞行的C++代码

飞机飞行

在src文件夹中的Application文件夹中存在着有关飞机飞行重要文件

 这些文件就是我们主要需要修改的文件,文件中的代码都有详细的注释,代码并不是特别难,不需要读的特别明白,只要会修改实现自己想要的功能即可,修稿之后编译执行即可检验效果,很方便易用

我所修改的文件是4x4ABCdemo.cpp,部分修改代码如下

int main(int argc, char **argv)
{ros::init(argc, argv, "collision_avoidance");ros::NodeHandle nh("~");image_transport::ImageTransport it(nh);// 频率 [20Hz]ros::Rate rate(20.0);//【订阅】Lidar数据//ros::Subscriber lidar_sub = nh.subscribe<sensor_msgs::LaserScan>("/scan", 1000, lidar_cb);//dyxros::Subscriber lidar_sub = nh.subscribe<sensor_msgs::LaserScan>("/lidar2Dscan", 1000, lidar_cb);//dyxros::Subscriber face_sub = nh.subscribe<std_msgs::String>("/face_detected", 1000,see_man);//【订阅】无人机当前位置 坐标系 NED系//ros::Subscriber position_sub = nh.subscribe<geometry_msgs::Pose>("/drone/pos", 100, pos_cb);ros::Subscriber position_sub = nh.subscribe<geometry_msgs::PoseStamped>("/mavros/local_position/pose", 100, pos_cb);  //dyx// 【发布】发送给position_control.cpp的命令ros::Publisher command_pub = nh.advertise<px4_command::command>("/px4/command", 10);//读取参数表中的参数nh.param<float>("R_outside", R_outside, 2);nh.param<float>("R_inside", R_inside, 1);nh.param<float>("p_xy", p_xy, 0.5);nh.param<float>("vel_track_max", vel_track_max, 0.5);nh.param<float>("p_R", p_R, 0.0);nh.param<float>("p_r", p_r, 0.0);nh.param<float>("vel_collision_max", vel_collision_max, 0.0);nh.param<float>("vel_sp_max", vel_sp_max, 0.0);nh.param<int>("range_min", range_min, 0.0);nh.param<int>("range_max", range_max, 0.0);nh.param<float>("A_x", A_x, 0.0);nh.param<float>("A_y", A_y, 0.0);nh.param<float>("B_x", B_x, 0.0);nh.param<float>("B_y", B_y, 0.0);nh.param<float>("C_x", C_x, 0.0);nh.param<float>("C_y", C_y, 0.0);nh.param<float>("D_x", D_x, 0.0);nh.param<float>("D_y", D_y, 0.0);    nh.param<float>("E_x", E_x, 0.0);nh.param<float>("E_y", E_y, 0.0);nh.param<float>("F_x", F_x, 0.0);nh.param<float>("F_y", F_y, 0.0);nh.param<float>("G_x", G_x, 0.0);nh.param<float>("G_y", G_y, 0.0);//获取设定的起飞高度//nh.getParam("/px4_pos_controller/Takeoff_height",fly_height);//check armint Arm_flag;cout<<"Input 1 for going:"<<endl;cin >> Arm_flag;if(Arm_flag == 1){Command_now.command = Arm;command_pub.publish(Command_now);}else return -1;ros::Duration(1).sleep();//check takeoffint Take_off_flag;//cout<<"Whether choose to Takeoff? 1 for Takeoff, 0 for quit"<<endl;//cin >> Take_off_flag;Take_off_flag=1;ros::Duration(1).sleep();if(Take_off_flag == 1){Command_now.command = Takeoff;command_pub.publish(Command_now);}else return -1;//打印现实检查参数printf_param();int check_flag;//输入1,继续,其他,退出程序,检查设定的参数是否正确//cout << "Please check the parameter and setting,1 for go on, else for quit: "<<endl;//cin >> check_flag;check_flag=1;ros::Duration(10).sleep();if(check_flag != 1){return -1;}//cout<<"Input 1:"<<endl;//cin >> ABC;ABC=1;ros::Duration(1).sleep();//初值vel_track[0]= 0;vel_track[1]= 0;vel_collision[0]= 0;vel_collision[1]= 0;vel_sp_body[0]= 0;vel_sp_body[1]= 0;vel_sp_ENU[0]= 0;vel_sp_ENU[1]= 0;//四向最小距离 初值flag_land = 0;flag_hold = 0;//输出指令初始化int comid = 1;//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Main Loop<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<while(ros::ok()){//回调一次 更新传感器状态//1. 更新雷达点云数据,存储在Laser中,并计算四向最小距离ros::spinOnce();/**************************dyx****************************************///模式2策略:ABC三点坐标已知,每次飞往ABC三点与返回原点时设定标志。if(ABC==1){if(!reach_ABC_flag[0])  //飞到A点,标记1,{collision_avoidance(A_x,A_y);float abs_distance;abs_distance = sqrt((pos_drone.pose.position.x - A_x) * (pos_drone.pose.position.x -A_x) + (pos_drone.pose.position.y - A_y) * (pos_drone.pose.position.y - A_y));cout <<"----------------------------------GO A-------------------------------" <<endl;if(abs_distance < 0.5 ){reach_ABC_flag[0]=true;ABC=2;}}}else if(ABC==2){if(!reach_ABC_flag[1]){collision_avoidance(B_x,B_y);float abs_distance;abs_distance = sqrt((pos_drone.pose.position.x - B_x) * (pos_drone.pose.position.x -B_x) + (pos_drone.pose.position.y - B_y) * (pos_drone.pose.position.y - B_y));cout <<"----------------------------------GO B-------------------------------" <<endl;if(abs_distance < 0.5 ){reach_ABC_flag[1]=true;ABC=3;}}}        else if(ABC==3){if(!reach_ABC_flag[2]){collision_avoidance(C_x,C_y);float abs_distance;abs_distance = sqrt((pos_drone.pose.position.x - C_x) * (pos_drone.pose.position.x -C_x) + (pos_drone.pose.position.y - C_y) * (pos_drone.pose.position.y - C_y));cout <<"----------------------------------GO C-------------------------------" <<endl;if(abs_distance < 0.5 ){reach_ABC_flag[2]=true;ABC=4;}}}else if(ABC==4){if(!reach_ABC_flag[3]){collision_avoidance(D_x,D_y);float abs_distance;abs_distance = sqrt((pos_drone.pose.position.x - D_x) * (pos_drone.pose.position.x -D_x) + (pos_drone.pose.position.y - D_y) * (pos_drone.pose.position.y - D_y));cout <<"----------------------------------GO D-------------------------------" <<endl;if(abs_distance < 0.4 ){reach_ABC_flag[3]=true;ABC=5;}}}else if(ABC==0){cout <<"----------------------------------Land-------------------------------" <<endl;flag_land=1;}else if(flag_see_man==1){ABC=0;}else if(flag_see_man==0){       p_xy =0.5;vel_track_max=0.5;if(ABC==5){vel_sp_ENU[0]=0;collision_avoidance(E_x,E_y);float abs_distance;abs_distance = sqrt((pos_drone.pose.position.x - E_x) * (pos_drone.pose.position.x -E_x) + (pos_drone.pose.position.y - E_y) * (pos_drone.pose.position.y - E_y));cout <<"----------------------------------SEEING RIGNT-------------------------------"<< abs_distance <<endl;if(abs_distance < 0.6 ){ABC=6;flag_count++;}}if(ABC==6){     collision_avoidance(F_x,F_y);float abs_distance;abs_distance = sqrt((pos_drone.pose.position.x - F_x) * (pos_drone.pose.position.x -F_x) + (pos_drone.pose.position.y - F_y) * (pos_drone.pose.position.y - F_y));cout <<"----------------------------------SEEING LEFT-------------------------------"<< abs_distance <<endl;if(abs_distance < 0.4 ){ABC=5;flag_count++;}}if(flag_count==3){fly_height=1.2;}if(flag_count==4){ABC=0;}}//启用ENU下的指令Command_now.command = Move_ENU;     //机体系下移动Command_now.comid = comid;comid++;Command_now.sub_mode = 2; // xy 速度控制模式 z 位置控制模式Command_now.vel_sp[0] =  vel_sp_ENU[0];Command_now.vel_sp[1] =  vel_sp_ENU[1];  //ENU frameCommand_now.pos_sp[2] =  fly_height;Command_now.yaw_sp = 0 ;if(flag_land == 1) Command_now.command = Land;command_pub.publish(Command_now);//打印printf();rate.sleep();}return 0;}

人脸识别 

关于人脸识别部分官方并没有提供更多的示例,我们需要自己编写opencv的相关代码,网上的代码也比较多,这是我们所用的代码做一个参考

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import rospy
import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image
from std_msgs.msg import String
import numpy as npclass cv:def __init__(self):    # 创建cv_bridge,声明图像的发布者和订阅者cascade_1 = rospy.get_param("~cascade_1", "")self.face_detector = cv2.CascadeClassifier(cascade_1)self.land = rospy.Publisher("face_detected", String, queue_size=10)self.bridge = CvBridge()self.image_sub = rospy.Subscriber("/camera/rgb/image_raw", Image, self.callback)self.faceFlag = Falsedef callback(self,data):# 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式try:cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")except CvBridgeError as e:print e# 显示Opencv格式的图像#cv_image=cv2.flip(cv_image,0)#cv_image=cv2.flip(cv_image,1)gray = cv2.cvtColor(cv_image, cv2.COLOR_BGR2GRAY)faces = self.face_detector.detectMultiScale(gray, 1.2, 6)if len(faces)>0:for face in faces: x, y, w, h = facecv2.rectangle(cv_image, (x, y), (x+w, y+h), (255,255,0), 2)self.faceFlag = Truecv2.imshow("Image window", cv_image)if self.faceFlag:self.land.publish("T")cv2.waitKey(0)else:cv2.waitKey(30)if __name__ == '__main__':try:# 初始化ros节点rospy.init_node("cv_bridge_test")rospy.loginfo("Starting cv_bridge_test node")cv()rospy.spin()except KeyboardInterrupt:print "Shutting down cv_bridge_test node."cv2.destroyAllWindows()

识别效果

提交代码

关于我的小组所提交的代码并不是一整个工作空间,而是对原来的sim_ws工作空间中的文件进行替换,这样就省去了很多不必要的麻烦,但是相当来说说明文档要写好。

 over

这篇关于2022年吉林省智能无人机仿真挑战赛参赛心得(ROS+gazebo)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/803968

相关文章

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

智能交通(二)——Spinger特刊推荐

特刊征稿 01  期刊名称: Autonomous Intelligent Systems  特刊名称: Understanding the Policy Shift  with the Digital Twins in Smart  Transportation and Mobility 截止时间: 开放提交:2024年1月20日 提交截止日

基于UE5和ROS2的激光雷达+深度RGBD相机小车的仿真指南(五):Blender锥桶建模

前言 本系列教程旨在使用UE5配置一个具备激光雷达+深度摄像机的仿真小车,并使用通过跨平台的方式进行ROS2和UE5仿真的通讯,达到小车自主导航的目的。本教程默认有ROS2导航及其gazebo仿真相关方面基础,Nav2相关的学习教程可以参考本人的其他博客Nav2代价地图实现和原理–Nav2源码解读之CostMap2D(上)-CSDN博客往期教程: 第一期:基于UE5和ROS2的激光雷达+深度RG

基于 YOLOv5 的积水检测系统:打造高效智能的智慧城市应用

在城市发展中,积水问题日益严重,特别是在大雨过后,积水往往会影响交通甚至威胁人们的安全。通过现代计算机视觉技术,我们能够智能化地检测和识别积水区域,减少潜在危险。本文将介绍如何使用 YOLOv5 和 PyQt5 搭建一个积水检测系统,结合深度学习和直观的图形界面,为用户提供高效的解决方案。 源码地址: PyQt5+YoloV5 实现积水检测系统 预览: 项目背景

【C++学习笔记 20】C++中的智能指针

智能指针的功能 在上一篇笔记提到了在栈和堆上创建变量的区别,使用new关键字创建变量时,需要搭配delete关键字销毁变量。而智能指针的作用就是调用new分配内存时,不必自己去调用delete,甚至不用调用new。 智能指针实际上就是对原始指针的包装。 unique_ptr 最简单的智能指针,是一种作用域指针,意思是当指针超出该作用域时,会自动调用delete。它名为unique的原因是这个

内卷时代无人机培训机构如何做大做强

在当今社会,随着科技的飞速发展,“内卷”一词频繁被提及,反映了各行业竞争日益激烈的现象。对于无人机培训行业而言,如何在这样的时代背景下脱颖而出,实现做大做强的目标,成为每个培训机构必须深思的问题。以下是从八个关键方面提出的策略,旨在帮助无人机培训机构在内卷时代中稳步前行。 1. 精准定位市场需求 深入研究市场:通过市场调研,了解无人机行业的最新趋势、政策导向及未来发展方向。 明确目标

单片机毕业设计基于单片机的智能门禁系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 💗博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师,一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP430/AVR等单片机设计 主要对象是咱们电子相关专业的大学生,希望您们都共创辉煌!✌💗 👇🏻 精彩专栏 推荐订

perl的学习记录——仿真regression

1 记录的背景 之前只知道有这个强大语言的存在,但一直侥幸自己应该不会用到它,所以一直没有开始学习。然而人生这么长,怎就确定自己不会用到呢? 这次要搭建一个可以自动跑完所有case并且打印每个case的pass信息到指定的文件中。从而减轻手动跑仿真,手动查看log信息的重复无效低质量的操作。下面简单记录下自己的思路并贴出自己的代码,方便自己以后使用和修正。 2 思路整理 作为一个IC d

【C++】作用域指针、智能指针、共享指针、弱指针

十、智能指针、共享指针 从上篇文章 【C++】如何用C++创建对象,理解作用域、堆栈、内存分配-CSDN博客 中我们知道,你的对象是创建在栈上还是在堆上,最大的区别就是对象的作用域不一样。所以在C++中,一旦程序进入另外一个作用域,那其他作用域的对象就自动销毁了。这种机制有好有坏。我们可以利用这个机制,比如可以自动化我们的代码,像智能指针、作用域锁(scoped_lock)等都是利用了这种机制。