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);//dyx
    ros::Subscriber lidar_sub = nh.subscribe<sensor_msgs::LaserScan>("/lidar2Dscan", 1000, lidar_cb);//dyx
    ros::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 arm
    int 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 takeoff
    int 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 frame
        Command_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 np

class 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 = False

    def 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 = face
                cv2.rectangle(cv_image, (x, y), (x+w, y+h), (255,255,0), 2)
            self.faceFlag = True
	    
        
        cv2.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

  • 2
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

别人家的孩子380

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值