作为一名无人机飞控方向的研究生,这几年在学习了许多大佬的开源项目和博客后进行了多旋翼无人机机载计算机上的程序开发,下面做一些总结,记录一下学习到的相关经验,以及分享一些简单的开发程序,主要是在DJI M600和PX4无人机基于ROS&C++开发位置环的控制程序,希望对大家有用,个人水平有限,如果有什么错误还请指出。
安装教程可参考下面的链接
ubuntu安装ros教程
安装ros时遇到rosdep init失败的问题,可以参考下面的解决方案。
从根本上解决rosdep init的问题
使用rosdepc解决rosdep init的问题
在进行基于ROS的无人机开发时,经常需要用到串口转换工具连接机载计算机与飞控,为了方便起见最好进行串口绑定。
打开终端执行
lsusb
查看串口设备信息,以自己用到的数传电台为例,输出的信息里可以看到有一条为
Bus 001 Device 007: ID 10c4:ea60 Cygnal Integrated Products, Inc. CP210x UART Bridge / myAVR mySmartUSB light
在终端输入
sudo gedit /etc/udev/rules.d/myusb.rules
添加对应设备ID和绑定的端口号名称
KERNEL=="ttyUSB*", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE:="0777", SYMLINK+="UARTBridgeusb"
上述规则将该设备的串口号绑定为UARTBridgeusb,在程序中打开时的端口号则为/dev/UARTBridgeusb,程序中如果需要打开该设备,修改成对应的端口号即可。
终端输入su进入root模式,然后依次执行
service udev reload
service udev restart
断开串口后重新连接,输入
ls /dev
查看是否生效
有的时候需要在机载计算机开机时便启动一些程序,可以参考下面的方法添加开机启动项。
sudo gedit run_trx.sh
复制如下所示的脚本文件:
#!/bin/bash
{
gnome-terminal -x bash -c 'source /opt/ros/kinetic/setup.bash;source ~/catkin_ws/devel/setup.bash;roscore'
}&
sleep 5
{
gnome-terminal -x bash -c 'source /opt/ros/kinetic/setup.bash;source ~/catkin_ws/devel/setup.bash;rosrun *** ***'
}&
exit 0
然后保存退出,给脚本文件赋予权限
sudo chmod 777 run_trx.sh
在Ubuntu主界面点“搜索”,然后输入“启动”,打开“启动应用程序”管理器,点击添加将该脚本文件添加即可开机启动。
通过该自启动脚本将自启动roscore和希望运行的ros程序以便调试。
由于所编写的控制程序需要实时求解优化问题来实现对无人机的控制,本文采用了开源优化求解器Casadi来编写模型预测控制(MPC)的C++程序,详情可参考Casadi的官网仓库,官方的示例程序中包含了最优控制等的例子,本人也是基于给的相关示例程序来编写的,后续会给出实现过程与示例程序。
在进行环境配置的时候遇到了一些问题,这里分享自己尝试的进行环境配置过程。
在Ubuntu16中基于DJI的ROS-SDK包编写M600无人机的MPC外环控制程序时,环境配置比较简单,只需要在官方的Github仓库的release中下载编译过的库即可。
在官方的releases中下载libcasadi-linux-gcc5-v3.5.5版本(看个人需求,本人在写MATLAB仿真的时候用的也是3.5.5)。
然后放在与工作空间(即catkin_ws)同一目录下,比如我都放在了/home下,然后在所编写程序对应的CMakeLists中添加casadi的路径,使CMake能找到库文件。
在Find catkin macros and libraries部分添加如下所示:
set(casadi_DIR ../../../../libcasadi-linux-gcc5-v3.5.5/lib/cmake/casadi)
find_package(casadi REQUIRED)
if(casadi_FOUND)
message(STATUS "Found casadi ${casadi_VERSION} installed in the system")
set(casadi_INSTALLED TRUE)
else()
message(STATUS "Did not find casadi in the system")
endif()
set(casadi "../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_cbc.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_clp.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_cplex.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_gurobi.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_nlpsol.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_osqp.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_qpoases.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_qrqp.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_conic_superscs.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_importer_shell.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_integrator_collocation.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_integrator_cvodes.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_integrator_idas.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_integrator_rk.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_interpolant_bspline.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_interpolant_linear.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_csparse.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_csparsecholesky.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_lapacklu.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_lapackqr.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_ldl.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_lsqr.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_ma27.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_qr.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_symbolicqr.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_linsol_tridiag.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_nlpsol_ampl.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_nlpsol_blocksqp.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_nlpsol_bonmin.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_nlpsol_ipopt.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_nlpsol_knitro.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_nlpsol_qrsqp.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_nlpsol_scpgen.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_nlpsol_sqpmethod.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_rootfinder_fast_newton.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_rootfinder_kinsol.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_rootfinder_newton.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_rootfinder_nlpsol.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_sundials_common.so
../../../../libcasadi-linux-gcc5-v3.5.5/lib/libcasadi_xmlfile_tinyxml.so"
)
在Build部分,对于每一个包含了Casadi库的文件添加casadi以使编译通过
if(casadi_INSTALLED)
add_executable(*** src/***.cpp)
target_link_libraries(***
casadi
${catkin_LIBRARIES}
${DJIOSDK_LIBRARIES}
)
add_dependencies(*** dji_sdk_generate_messages_cpp)
endif()
这里的***为自己编写的程序名字,在进行配置时注意结合自己的路径和文件进行修改。
但是比较奇怪的是,后续在Ubuntu18上进行PX4的ROS开发时,为了移植自己编写的程序,按照上述方法进行环境配置时只能保证编译通过,但运行会提示找不到一系列so文件,经过测试发现写的set()绑定那一堆so文件注释了也不影响编译,但之前在妙算上运行并没有发现这个错误,难道是Ubuntu版本的问题?安装了casadi的deb包也无法跑程序。
后来又参考相关的帖子Ipopt安装和Casadi安装教程尝试安装Ipopt以及Casadi3.5.5,自己尝试的具体的步骤如下,注意下面的安装过程中下载的包的版本会影响环境配置,在自己的电脑上配置好以后没有注意下载包的版本,导致在无人机的机载NUC电脑上配置环境下载了比较新的包,然后编译通过,但是运行程序报了段错误。
安装IPOPT:
安装所需功能包:
sudo apt-get install cppad
sudo apt-get install gcc g++ gfortran subversion patch wget
从Ipopt网站里下载源码,此处下载的是3.12.7。
然后安装第三方库
cd ~/Ipopt-3.12.7/ThirdParty/Blas
./get.Blas
cd ../ASL
./get.ASL
cd ../Lapack
./get.Lapack
cd ../Mumps
./get.Mumps
cd ../Metis
./get.Metis
下载完成后回到Ipopt-3.12.7路径下:
cd ../../
mkdir build
cd build
安装在系统 /usr/local 目录下,默认是放在新建的 build 文件夹中
sudo ../configure --prefix=/usr/local/
sudo make
编译完可以测试是否编译成功
sudo make test
最后安装
sudo make install
从源码编译安装Casadi:
首先安装ipopt依赖:
sudo apt-get install coinor-libipopt-dev
然后从Github仓库中的Release下载casadiV3.5.5
下载完成后进入目录下
cd casadi-3.5.5
mkdir build
cd build
编译的第一步不太一样,之前直接cmake导致编译安装完成后并没有运行程序需要的一些文件,才尝试了直接下载libcasadi-linux-gcc5-v3.5.5然后手动指定CMakelists里的路径。
奇怪的是这里第一次输入,会提示找不到IPOPT,第二次输入又找到了
cmake .. -DWITH_IPOPT=true
然后就是
make
sudo make install
在所编写程序ROS包对应的CMakeLists添加以下内容:
# Casadi path
find_package(casadi REQUIRED)
if(casadi_FOUND)
message(STATUS "Found casadi ${casadi_VERSION} installed in the system")
set(casadi_INSTALLED TRUE)
message(“casadi dir ${casadi_INCLUDE_DIRS}”)
message(“casadi lib ${casadi_LIBS}”)
include_directories(/usr/local/include/casadi)
else()
message(STATUS "Did not find casadi in the system")
endif()
包含Casadi库函数的cpp文件的编译指令添加如下包含Casadi的指令:
add_executable(*** src/***.cpp)
target_link_libraries(*** casadi ${catkin_LIBRARIES})
这里的***为自己编写的程序名字,在进行配置时注意结合自己的路径和文件进行修改。
后续在给出具体的示例程序时再进行CMakeLists的完善。