马弗罗斯 机外 控制示例(Python)
本教程介绍了 离岸 使用 MAVROS Python 进行控制,使用 Iris 四旋翼飞行器模拟了 经典仿真场景Gazebo.它提供逐步指导,演示如何开始开发控制载具的程序并在模拟中运行代码。
教程结束时,您应该看到与下面视频中相同的行为,即缓慢起飞至 2 米高度。
警告
离岸 控制是很危险的。如果您要在真实载具上进行操作,请务必想办法重新获得手动控制权,以防出现意外。
TIP
本例使用 Python。其他 Python 示例可在此处找到: integrationtests/python_src/px4_it/mavros.
创建 ROS 软件包
打开终端,转到
~/catkin_ws/src
通讯录吁roscd # 应 cd 到 ~/catkin_ws/devel CD .. CD 来源
在
~/catkin_ws/src
目录下创建一个名为offboard_py
(在本例中)与蟑螂
依赖性:吁catkin_create_pkg offboard_py 蟑螂
在
~/catkin_ws/
目录:吁CD .. # 假设之前的目录是 ~/catkin_ws/src 柔荑花序 构建 消息来源 devel/setup.bash
现在,您应该可以通过使用
吁roscd offboard_py
要存储 Python 文件,请新建一个名为
/脚本
在包装上:吁mkdir 脚本 CD 脚本
代码
创建 ROS 软件包和脚本文件夹后,就可以开始编写 Python 脚本了。在脚本文件夹中创建 offb_node.py
文件,并赋予其可执行权限:
触摸 offb_node.py
chmod +x offb_node.py
然后,打开 offb_node.py
文件,并粘贴以下代码:
""";
* 文件:offb_node.py
* 在 Gazebo Classic 9 SITL 中堆叠和测试
""";
#!/usr/bin/env python
舶来品 蟑螂
从 几何_msgs.msg 舶来品 姿势盖章
从 mavros_msgs.msg 舶来品 国家
从 mavros_msgs.srv 舶来品 CommandBool, CommandBoolRequest, SetMode, SetModeRequest
current_state = 状态()
捍卫 状态(毫秒):
全球 current_state
current_state = 信息
如果 姓名____ == "__main__";:
rospy.init_node("offb_node_py";)
状态子 = rospy.Subscriber("mavros/state";, State、 回调 = state_cb)
本地发布 = rospy.Publisher("mavros/setpoint_position/local";, PoseStamped、 队列大小=10)
rospy.wait_for_service("/mavros/cmd/arming";)
上膛客户端 = rospy.ServiceProxy("mavros/cmd/arming";, CommandBool)
rospy.wait_for_service("/mavros/set_mode";)
设置客户端模式 = rospy.ServiceProxy("mavros/set_mode";, SetMode)
# 设定点发布必须快于 2Hz
费率 = rospy.Rate(20)
# 等待飞行控制器连接
虽然(不 rospy.is_shutdown() 和 不 current_state.connected):
rate.sleep()
姿势 = PoseStamped()
姿势.pose.position.x = 0
pose.pose.position.y = 0
pose.pose.position.z = 2
# 启动前发送几个设定点
对于 i 于 范围(100):
如果(rospy.is_shutdown()):
断裂
local_pos_pub.publish(pose)
rate.sleep()
offb_set_mode = SetModeRequest()
offb_set_mode.custom_mode = 'offboard';
arm_cmd = CommandBoolRequest()
arm_cmd.value = 正确
最后要求 = rospy.Time.now()
虽然(不 rospy.is_shutdown()):
如果(current_state.mode != "OFFBOARD"; 和 (rospy.Time.now() - last_req) >; rospy.Duration(5.0)):
如果(set_mode_client.call(offb_set_mode).mode_sent == 正确):
rospy.loginfo(已启用 OFFBOARD;)
最后要求 = rospy.Time.now()
不然:
如果(不 current_state.armed 和 (rospy.Time.now() - last_req) >; rospy.Duration(5.0)):
如果(arming_client.call(arm_cmd).success == 正确):
rospy.loginfo(载具上膛";)
最后要求 = rospy.Time.now()
local_pos_pub.publish(pose)
rate.sleep()
代码解释
mavros_msgs
包包含了操作 MAVROS 包提供的服务和主题所需的所有自定义消息。所有服务和主题及其相应的信息类型都记录在 马夫罗斯维基.
舶来品 蟑螂
从 几何_msgs.msg 舶来品 姿势盖章
从 mavros_msgs.msg 舶来品 国家
从 mavros_msgs.srv 舶来品 CommandBool, CommandBoolRequest, SetMode, SetModeRequest
我们创建了一个简单的回调,用于保存自动驾驶仪的当前状态。这样我们就可以检查连接、上膛和 离岸 旌旗
current_state = 状态()
捍卫 状态(毫秒):
全球 current_state
current_state = 信息
我们将实例化一个发布器来发布指令本地位置以及相应的客户端来请求上膛和模式更改。请注意,对于您自己的系统,"mavros"前缀可能会有所不同,因为这取决于节点在启动文件中的名称。
状态子 = rospy.Subscriber("mavros/state";, State、 回调 = state_cb)
本地发布 = rospy.Publisher("mavros/setpoint_position/local";, PoseStamped、 队列大小=10)
rospy.wait_for_service("/mavros/cmd/arming";)
上膛客户端 = rospy.ServiceProxy("mavros/cmd/arming";, CommandBool)
rospy.wait_for_service("/mavros/set_mode";)
设置客户端模式 = rospy.ServiceProxy("mavros/set_mode";, SetMode)
PX4 在两次运行之间的超时为 500 毫秒。 离岸 命令。如果超过该超时时间,指挥官将退回到载具进入前的最后一个模式。 离岸 模式。这就是为什么输出频率 必须 快于 2 赫兹,以考虑到可能出现的延迟。这也是为什么 推荐参赛 离岸 模式从 定位(POSITION) 模式这样,如果载具从 离岸 模式下,它会停在原地盘旋。
在此,我们对输出频率进行了适当设置:
# 设定点发布必须快于 2Hz
费率 = rospy.Rate(20)
在发布任何信息之前,我们需要等待 MAVROS 与自动驾驶仪之间建立连接。一旦收到心跳信息,这个循环就应立即退出。
# 等待飞行控制器连接
虽然(不 rospy.is_shutdown() 和 不 current_state.connected):
rate.sleep()
尽管 PX4 在航空航天 NED 坐标框架内运行,但 MAVROS 会将这些坐标转换为标准的 ENU 框架,反之亦然。这就是我们设置 z
为正 2:
姿势 = PoseStamped()
姿势.pose.position.x = 0
pose.pose.position.y = 0
pose.pose.position.z = 2
在进入 离岸 模式时,您必须已经开始设置点流。否则,模式切换将被拒绝。下图 100
是任意选择的。
# 启动前发送几个设定点
对于 i 于 范围(100):
如果(rospy.is_shutdown()):
断裂
local_pos_pub.publish(pose)
rate.sleep()
我们准备了用于将自定义模式设置为 离岸
.清单 支持的模式 可供参考。
offb_set_mode = SetModeRequest()
offb_set_mode.custom_mode = 'offboard';
代码的其余部分基本上不需要解释。我们尝试切换到 机外 模式,然后上膛四轴飞行器,允许其飞行。我们将服务调用间隔为 5 秒,以免自动驾驶仪被大量请求淹没。在同一个循环中,我们继续以之前定义的速率发送请求的姿势。
arm_cmd = CommandBoolRequest()
arm_cmd.value = 正确
最后要求 = rospy.Time.now()
虽然(不 rospy.is_shutdown()):
如果(current_state.mode != "OFFBOARD"; 和 (rospy.Time.now() - last_req) >; rospy.Duration(5.0)):
如果(set_mode_client.call(offb_set_mode).mode_sent == 正确):
rospy.loginfo(已启用 OFFBOARD;)
最后要求 = rospy.Time.now()
不然:
如果(不 current_state.armed 和 (rospy.Time.now() - last_req) >; rospy.Duration(5.0)):
如果(arming_client.call(arm_cmd).success == 正确):
rospy.loginfo(载具上膛";)
最后要求 = rospy.Time.now()
local_pos_pub.publish(pose)
rate.sleep()
TIP
为便于说明,本代码已简化到最低限度。在较大的系统中,通常需要创建一个新的线程,负责定期发布设定点。
创建 ROS 启动文件
在您的 offboard_py
软件包,在 ~/catkin_ws/src/offboard_py/src
名为 启动
.这里将存放软件包的启动文件。然后,创建第一个启动文件,在本例中我们将其称为 start_offb.launch
.
roscd offboard_py
mkdir 启动
CD 启动
触摸 start_offb.launch
对于 start_offb.launch
复制以下代码:
<?xml 版本="1.0";?>;
<;启动>;
<!-- 包括带有 SITL 和 Gazebo 的 MAVROS 节点 -->;
<;包括 文件="$(find px4)/launch/mavros_posix_sitl.launch";>;
</包括>;
<!-- 我们控制无人机的节点 -->;
<;网站 包="offboard_py"; 类型="offb_node.py"; 名字="offb_node_py"; 所需="true"; 产量="屏幕"; />;
</启动>;
正如您所看到的 mavros_posix_sitl.launch
文件。该文件负责启动 MAVROS、PX4 SITL、Gazebo 经典环境以及在给定世界中生成载具(更多信息请参阅文件 这里).
TIP
mavros_posix_sitl.launch
文件需要几个参数,可以根据自己的喜好进行设置,例如生成的载具或仿真场景Gazebo经典世界(请参阅 这里) 的完整列表)。
您可以覆盖在 mavros_posix_sitl.launch
在 包括 标记。例如,如果您想在 仓库.世界
,你会写出以下内容:
<!-- 包括带有 SITL 和 Gazebo 的 MAVROS 节点 -->;
<;包括 文件="$(find px4)/launch/mavros_posix_sitl.launch";>;
<;雅格 名字="世界"; 默认="$(find mavlink_sitl_gazebo)/worlds/warehouse.world";/>;
</包括>;
启动脚本
如果一切就绪,现在就可以启动并测试脚本了。
在终端中写入
玫瑰发射 offboard_py start_offb.launch
现在应该可以看到 PX4 固件启动,Gazebo Classic 应用程序正在运行。在 离岸 模式已设置且载具已上膛,则显示在 视频 应予以遵守。
警告
运行脚本时可能会出现错误提示:
未找到资源:px4 ROS 路径 [0] = ... ...
这意味着 PX4 SITL 未包含在路径中。要解决这个问题,请在 .bashrc
锉刀
消息来源 ~/PX4-Autopilot/Tools/simulation/gazebo/setup_gazebo.bash ~/PX4-自动驾驶仪 ~/PX4-Autopilot/build/px4_sitl_default
出口 ros_package_path=$ros_package_path:~/PX4-自动驾驶仪
出口 ros_package_path=$ros_package_path:~/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic
出口 gazebo_plugin_path=$GAZEBO_PLUGIN_PATH:/usr/lib/x86_64-linux-gnu/gazebo-9/plugins
现在在终端中进入主目录,运行以下命令将上述更改应用到当前终端:
消息来源 .bashrc
完成这一步后,每次打开新的终端窗口时就不必再担心这个错误了。如果它再次出现,只需 source .bashrc
就能解决问题。该解决方案来自 问题 主题,您可以在此获得更多有关该问题的信息。