# uav-sh **Repository Path**: icr2022/uav-sh ## Basic Information - **Project Name**: uav-sh - **Description**: 山西太原无人机巡检项目code - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-12 - **Last Updated**: 2026-03-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 无人机巡检项目代码简述 ### 开机自启动 山西太原电力巡检项目,涉及两个场地。分别对应的树莓派自启动脚本为`xj_sh`文件夹中的两个脚本&服务。 - 1)多彩城望府:`uav-init.service` ```bash ssh huawei@192.168.50.246 ``` - 2)悦府(地面掉高):`uav-init-uav2.service` ```bash ssh huawei@192.168.50.229 ``` 使能树莓派服务的操作如下,以`uav-init.service`为例: ```bash # 1)给可执行脚本加权限 cd xj_sh sudo chmod a+x uav_init.sh # 2) 拷贝服务至系统路径 cp uav-init.service /etc/systemd/system cp uav-init.service /lib/systemd/system # 加权限 sudo chmod 777 /etc/systemd/system/uav-init.service sudo chmod 777 /lib/systemd/system/uav-init.service # 3)建立链接 sudo ln -fs /lib/systemd/system/uav-init.service /etc/systemd/system/uav-init.service # 4) 启用服务 设置后才能开机启动 sudo systemctl enable uav-init # disable # 可以取消服务的开机自启动 # 其他一些操作 start | stop | restart | status ``` 其中,自启动脚本的**基本格式**如下(省略部分内容),挑其中的一些要点进行简单论述。 - 1)每次启动程序前,先`rosclean`,清除缓存 - 2)针对某个程序无法一次正常启动,而需要多次启动的问题,设计了指令判断。 ```bash while true; do b="frame_id:" echo "Checking /scan topic.." # timeout # 执行命令的设定时间达到限制则停止 # awk '{print $1}' 将打印字符串的第一个字符,默认分割符为 空格 a="$(timeout 3s rostopic echo -n 1 /scan | grep frame_id | awk '{print $1}' )" if [ ${a} = ${b} ]; then echo "Data received on /scan topic, continuing... " break; else echo "No data on /scan topic, restarting" # 在重启程序前,先杀掉对应的ros节点 rosnode kill /LD06 sleep 1 # 清除掉无效的ros节点(kill 不一定有效清除) rosnode cleanup sleep 1 screen -d -m -S scan bash -c 'roslaunch ldlidar_stl_ros stl27_.launch; exec /bin/bash' sleep 6 fi sleep 1 done ``` - 3)脚本最后需要有`while true; do sleep 1; done`。不然脚本启动一次之后就会死掉,对应的程序也是如此。当然有特例,如果最后是直接启动python脚本文件,无需添加该内容也能保证前面的程序一直活着,代价是无法正常执行后续的程序内容,将python文件利用roslaunch启动则能消除该bug。 ```bash #!/bin/bash echo "start ~" . /opt/ros/melodic/setup.bash screen -d -m -S roscore bash -c 'roscore ; exec /bin/bash' while true; do if [ "$(rosnode list)" ]; then echo "has core" break fi sleep 1 echo "wait core start ~" done echo "roscore success" rosclean purge -y sleep 3 source ~/catkin_ws/devel/setup.bash screen -d -m -S scan bash -c 'roslaunch ldlidar_stl_ros stl27_.launch; exec /bin/bash' sleep 4 while true; do b="frame_id:" echo "Checking /scan topic.." # timeout # 执行命令的设定时间达到限制则停止 # lidar 数据较多,1s不够 a="$(timeout 3s rostopic echo -n 1 /scan | grep frame_id | awk '{print $1}' )" if [ ${a} = ${b} ]; then echo "Data received on /scan topic, continuing... " break; else echo "No data on /scan topic, restarting" rosnode kill /LD06 sleep 1 rosnode cleanup sleep 1 screen -d -m -S scan bash -c 'roslaunch ldlidar_stl_ros stl27_.launch; exec /bin/bash' sleep 6 fi sleep 1 done echo "lidar start" while true; do sleep 1; done ``` 树莓派的`~/.config/autostart`下,创建`xxx.desktop`文件,**可以设置开机自启动**。但是这个启动**需要树莓派连接屏幕**,其将自动打开一个终端并执行命令。 ### 涉及功能包介绍 正常运行逻辑如下: ```bash 远程服务器发送上电指令 --> 机巢(esp8266)控制继电器下电 --> 无人机上电,开始启动程序 --> 远程服务器发送任务指令 --> net_con收到指令 --> offboard接收航点任务&起飞指令 --> uav_dwa连接fcu并自动解锁切入offboard,接收offboard的航点并进行无人机控制 --> 任务执行完毕,无人机返回机巢并降落 --> 机巢接收上电指令后便开始4min记时,时间一到控制继电器上电 --> 无人机延时通电模块触发,无人机下电,电池开始充电 # 无人机飞行过程中,远程服务器可以发送任务终止指令... ``` 涉及到的主要功能包: - net_con:负责与服务器&offboard进行通讯。接收服务器下发的指令、反馈无人机状态、向服务器发送到达标志位后的拍照指令;给offboard转发服务器端任务航点设置、转发无人机工作模式设置、接收到达位置的拍照指令。 - offboard: **主控程序**,负责接收任务、检测无人机当前状态、发送无人机运动目标及指令,与多个模块进行交互。内置的scripts文件夹下包含python脚本文件,利用树莓派引脚控制舵机运动。 - aruco_localization: 利用摄像头图像进行aruco降落码的检测,由offboard触发检测标志位,将输出aruco码的中心位置(目前舍弃了三维位姿估计,因为识别效果不佳)。 - uav_dwa: 接收offboard发送到无人机运动目标及指令,该功能包将与mavros进行交互,进行无人机运动控制。 - cartographer: 利用2d雷达、imu、先验地图进行重定位,为无人机提供定位数据。 其他配件功能包: - mavros:建立与飞控之间的通讯,对启动mavros时的两个配置文件进行了修改 - uvc_camera:启动树莓派上的排线摄像头 - ldliar_stl_ros:乐动雷达的驱动。 ### 其他内容 #### 1)carto地图 - 多彩城悦府: stategrid_localization_1.launch - 望府: stategrid_localization_2.launch 先建图,然后再重定位。重定位时如果能多等一会,即使初始位置和建图时位置略不同,cartographer也能够将雷达点云匹配上环境地图,目前的树莓派参数情况下,大约2min左右可以。(自启动脚本中,也是先启动定位再启动其他内容) ```bash # mavros roslaunch mavros stategrid_qgc.launch # lidar roslaunch ldlidar_stl_ros stl27.launch # carto roslaunch cartographer_ros stategrid_explore.launch # 差不多之后,保存地图至 ~/xunjian rosservice call /finish_trajectory 0 # map_1 for 多彩城悦府 map_2 for 望府 rosservice call /write_state "{filename: '${HOME}/xunjian/map_1.pbstream', include_unfinished_submaps: "true"}" rosrun cartographer_ros cartographer_pbstream_to_ros_map -map_filestem=${HOME}/xunjian/040_040 -pbstream_filename=${HOME}/xunjian/map_1.pbstream -resolution=0.05 ``` cartographer的重定位参数会影响定位效果,因为**树莓派本身算力不够**,所以当前的参数设置上都比较小,**搜索窗口比较小**。对于算力强大的机载电脑,可以将搜索窗口、线程数等都改大。 cartographer重定位时,如果启动**重定位的位姿与初始建图不一致**,也可以修改代码,通过launch参数传入相对的位姿,以便于cartographer更快的进行有效的重定位。 >参考: https://blog.csdn.net/weixin_44923488/article/details/115279437 #### 2)相机标定 进行aruco检测时,对于传入的摄像头数据话题,其将会**自动获取对应话题下的camera_info**,利用其中的相机内参解算aruco码相对相机的位置。为此,进行aruco检测前,需要对相机进行标定。 > PS:**当前的相机是反向安装的**,aruco输出的marker检测结果也是进行了处理的。要用于其他无人机设备,需要对其进行修改。 树莓派的那个排线相机模块输出受限,`1280*720`的图像只能5hz左右,为保证实时性,进行降落检测时将使用15hz的`640*480`。 **标定工具推荐使用matlab**,kalibar难以标定成功... 步骤如下: ```bash # 1) 准备checkboard,启动相机节点,进行bag录制 roslaunch uvc_camera camera_land_1.launch # 2)播放bag包,从中截取出图像(记得杀掉相机节点 or 直接实时截取图像) # 将保存图片至运行命令的当前文件夹下,建议新建一个文件夹 rosrun image_view extract_images _sec_per_frame:=0.5 image:=/image_raw # 0.5s截取一张图片 # 3)将图片导入matlab进行标定,需要设置标定板类型和大小 # 4)将标定得到的内参矩阵填入 uvc_camera/config 的某个 .yaml文件中 ``` #### 3)飞控连接 uav1中采用`usb`连接树莓派,采用硬件串口连接雷达。将`usb`端口接线5v、GND、TXD&RXD至usb端口后,树莓派下将多一个设备`/dev/ttyACM0`,通过该端口启动mavros时,**波特率随便设置**。接线时,**只接TXD&RXD树莓派无法正常检测到设备号**,尽管两个设备皆使用同一块电池供电。而连接雷达时,只需要接雷达的TX至机载电脑的RX即可。 ### 树莓派... #### 1)树莓派网络设置 目前的树莓派网络设置**只需要修改yaml文件即可**。 修改其中的**wifi账号、wifi密码**、以及网络网段(实际上不改也行)。可以连接屏幕,也可以选择通过读卡器直接修改sd卡中的内容。 ```bash sudo nano /etc/netplan/50-cloud-init.yaml ``` #### 2)排线相机设置 与树莓派连接的**排线相机默认关闭**,需要设置后才能正常使用。如果更换了新的摄像头模组,可能也需要重新进行设置后才能正常使用。此外,在进行摄像头插拔时,需要将树莓派断电,否则将导致系统崩溃... 如果树莓派上面没有raspi-config,需要先进行安装。 ```bash # 下载 .deb wget http://mirrors.ustc.edu.cn/archive.raspberrypi.org/debian/pool/main/r/raspi-config/raspi-config_20201108_all.deb # 安装相关依赖包 sudo apt install lua5.1 libatopology2 libfftw3-single3 libsamplerate0 alsa-utils # 安装 raspi-config sudo dpkg -i raspi-config_20201108_all.deb ``` 摄像头设置指令如下: ```bash # 挂载 sudo mount /dev/mmcblk0p1 /boot # 添加至用户群组 sudo usermod -aG video huawei # 用户名 # 进行配置 # 上下键选择3 --> 选择P1 Camera --> 回车使能 sudo raspi-config # 使用 v4l2查看是否检测到 video0 sudo apt-get install v4l-utils # 没有需要安装 # 会显示很多内容,如果最下面有 /dev/video0, 则说明成功检测到摄像头 # 反之,可能需要检测一下排线是否插入正确 v4l2-ctl --list-devices # 下面的指令也能检测是否连接上摄像头 vcgencmd get_camera # 正常的输出结果为 supported=1 detected=1 # 拍照测试 raspistill -v -o test.jpg # 之后,便可以正常使用 uvc_camera 功能包打开摄像头并发布数据 ``` #### 3)舵机控制 要使用树莓派的硬件引脚进行舵机控制,需要安装一些依赖库文件。目前使用5V针脚下面的12(GPIO 18, PCM_CLK)进行舵机控制。 ```bash # 1)安装 WiringPi # 建议直接拷贝提前下载好的 wringpi 文件 git clone https://github.com/WiringPi/WiringPi.git cd WiringPi # 安装 ./build # ./build uninstall # 卸载 # 查看 WiringPi 版本 gpio -v # 2)安装python依赖 sudo apt-get install python3-rpi.gpio ``` 目前使用的python控制舵机脚本位于offboard/scripts文件夹下。可以通过修改 `def Controller(rotate_msg)`函数中的`time_list`调整舵机转动的角度。`time_list`中,**两个时间相加的和为19.5**。 #### 4)开启串口 我们需要使用树莓派的**硬件串口连接飞控or雷达**,使用5V下面的8&10(GPIO14 & GPIO 15, TXD&TXD)。其中,uav1用于连接雷达,uav2用于连接飞控。硬件串口**默认关闭**,如果在**没有开启硬件串口的情况下将串口设备连接硬件串口引脚**,并给树莓派上电,**树莓派大概率无法正常开机**。 > 参考博客:https://blog.csdn.net/benchuspx/article/details/112571880 > > 此处仅简述操作,更多详细内容参见博客。 操作步骤:让树莓派开机时**进入 u-boot** 界面,然后使用**串口助手连接其硬件串口进行设置**。 - 开机进入 u-boot界面:当时选择将飞控串口线连接硬件串口,连接外部屏幕并给树莓派开机,屏幕上将输出一堆乱码,不用管。 - 串口助手进行设置:使用usb转ttl模块连接其硬件串口,并使用串口调试助手打开对应的端口。然后,给其发送指令,以取消其u-boot的等待时间。 ```bash # 设置 setenv bootdelay -2 # 执行命令后没有输出 # 保存 saveenv # 执行命令后应该会有输出 # 比如: Saving Environment to FAI... ``` > 推荐[使用windows下的安信可串口调试助手](https://docs.ai-thinker.com/tools)。 #### 5)编译时间不对 将笔记本上面的程序拷贝至树莓派上进行编译,可能会遇到时间不同步问题而无法正常编译(nvidia xavier有时候也会遇到该问题)。 ```bash find . -type f -exec touch {} \; # 单独编译某个功能包 catkin_make -DCATKIN_WHITELIST_PACKAGES=offboard # 拷贝文件夹用 scp -r , 拷贝文件使用 scp # 从本地拷贝文件至其他设备 scp -r /xunjian huawei@192.168.50.xxx:~/ # 从其他设备拷贝文件 scp -r huawei@192.168.50.xxx:~/xunjian ```