1. LIZI的基本參數
參考LIZI官網。
2. LIZI的基礎使用
啓動順序:
(1)按電源開關打開電源。
(2)按PC開關,鬆開後等待3-5s,之後機器人會自檢它的系統。作爲自檢的一部分,LIZI可能會輕微的旋轉車輪。
注意,在啓動過程中PC按鈕會閃爍藍光。如果發生錯誤,則會閃爍紅光。
(3)連接HDMI顯示器及USB外設,通過ctrl+alt+T調出終端,執行此命令 roslaunch lizi lizi.launch
啓動後,PC按鈕會保持藍光。
(4)打開一個新的終端,執行此命令 rqt
打開如下可視化控制窗口,即可控制小車速度。
(5)關閉機器人
爲了延長機器人的生命週期,推薦採用如下方式關閉機器人:
先關閉電腦,在PC按鈕燈熄滅後關閉電源。
參考官方使用手冊。
3.LIZI的ROS開發
1 在啓動lizi.launch的時候通過配置參數去控制lizi的啓動。
gazebo - 在gazebo仿真中啓動robot
cam - 啓動前方RGB相機
depth_cam - 啓動前方RGB-D相機
lidar - 啓動激光雷達
diagnos - 發佈機器人診斷信息(可以通過 rqt_robot_monitor監控)
move_base - 啓動move_base包
map - 加載地圖到map server
gmapping - 啓動gmapping SLAM . 需要開啓 move_base和 lidar
hector_slam - 啓動 Hector SLAM . 需要開啓 move_base和 lidar
amcl - 啓動 AMCL 自適應蒙特卡拉定位. 需要開啓 move_base、lidar及map
2.通過修改命名空間啓動多個機器人
啓動文件參考如下
<?xml version="1.0" encoding="UTF-8"?>
<!-- lizi top-level launch -->
<launch>
<group ns="lizi117"><!-- chang the namespace-->
<!-- gazebo -->
<arg name="gazebo" default="false" doc="execute lizi inside gazebo sim"/>
<arg name="world" default="worlds/empty.world"/>
<arg name="x" default="0.0"/>
<arg name="y" default="0.0"/>
<arg name="z" default="0.0"/>
<arg name="Y" default="0.0" />
<!-- hardware -->
<arg name="cam" default="false"/>
<arg name="depth_cam" default="false"/>
<arg name="lidar" default="true"/>
<arg name="diagnos" default="true"/>
<arg name="rviz" default="false"/>
<!-- navigation and mapping -->
<arg name="gmapping" default="false"/>
<arg name="hector_slam" default="false"/>
<arg name="amcl" default="false"/>
<arg name="have_map" default="false" doc="set to true to use pre-saved map"/>
<arg name="map" default="/home/lizi115/catkin_ws/src/lizi/lizi_navigation/maps/2.yaml" doc="pre-saved map path"/>
<arg name="move_base" default="false"/>
<arg name="robot_localization" default="false"/>
<node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher" respawn="false" output="screen"/>
<group if="$(arg diagnos)">
<include file="$(find lizi_hw)/launch/diagnostics.launch" />
</group>
<group if="$(arg amcl)">
<include file="$(find lizi_control)/launch/lizi_controllers.launch" >
<arg name="enable_mbc_odom_tf" value="false"/>
</include>
</group>
<group if="$(arg robot_localization)">
<include file="$(find lizi_control)/launch/lizi_controllers.launch" >
<arg name="enable_mbc_odom_tf" value="false"/>
</include>
</group>
<group unless="$(arg robot_localization)">
<group unless="$(arg amcl)">
<include file="$(find lizi_control)/launch/lizi_controllers.launch" >
<arg name="enable_mbc_odom_tf" value="true"/>
</include>
</group>
</group>
<include file="$(find espeak_ros)/launch/espeak_ros.launch" />
<group if="$(arg have_map)">
<node name="map_server" pkg="map_server" type="map_server" args="$(arg map)" />
</group>
<!--if no one publish map-odom tf, load static tf-->
<group unless="$(arg gmapping)">
<group unless="$(arg hector_slam)">
<group unless="$(arg amcl)">
<group unless="$(arg robot_localization)">
<node pkg="tf" type="static_transform_publisher" name="map_odom_broadcaster" args="0 0 0 0 0 0 /map /odom 20" />
</group>
</group>
</group>
</group>
<!--load simulation stuff-->
<group if="$(arg gazebo)">
<!-- <env name="GAZEBO_MODEL_PATH" value="$(find lizi_gazebo)/models:$(optenv GAZEBO_MODEL_PATH)"/>-->
<param name="robot_description" command="$(find xacro)/xacro '$(find lizi_description)/urdf/lizi_gazebo.xacro' --inorder
depth_cam:=$(arg depth_cam)
cam:=$(arg cam)
urf:=true
imu:=true
gps:=true
lidar:=true" />
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="world_name" value="$(arg world)"/>
<arg name="gui" value="true"/>
</include>
<node name="lizi_spawn" pkg="gazebo_ros" type="spawn_model" output="screen" args="-urdf -param robot_description -model lizi -x $(arg x) -y $(arg y) -z $(arg z) -Y $(arg Y)" />
</group>
<!--load hardware stuff-->
<group unless="$(arg gazebo)">
<param name="robot_description" command="$(find xacro)/xacro '$(find lizi_description)/urdf/lizi.xacro' --inorder" />
<include file="$(find lizi_hw)/launch/lizi_hw.launch" />
<group if="$(arg depth_cam)">
<include file="$(find lizi_hw)/launch/d435_cam.launch" />
</group>
<group if="$(arg cam)">
<include file="$(find lizi_hw)/launch/microsoft_cam.launch" />
</group>
<group if="$(arg lidar)">
<include file="$(find lizi_hw)/launch/hokuyu_lidar.launch" />
</group>
</group>
<group if="$(arg gmapping)">
<include file="$(find lizi_navigation)/launch/gmapping.launch" />
</group>
<group if="$(arg hector_slam)">
<include file="$(find lizi_navigation)/launch/hector_slam.launch" />
</group>
<group if="$(arg robot_localization)">
<include file="$(find lizi_navigation)/launch/robot_localization.launch" />
</group>
<group if="$(arg amcl)">
<node pkg="tf" type="static_transform_publisher" name="map_odom_broadcaster" args="0 0 0 0 0 0 /map /odom 20" />
<include file="$(find lizi_navigation)/launch/amcl.launch" >
<!--arg name="x" value="$(arg x)"/>
<arg name="y" value="$(arg y)"/>
<arg name="Y" value="$(arg Y)"/-->
</include>
</group>
<group if="$(arg move_base)">
<include file="$(find lizi_navigation)/launch/move_base.launch" />
<rosparam file="$(find lizi_navigation)/config/move_base_params.yaml" command="load" ns="move_base"/>
<rosparam file="$(find lizi_navigation)/config/costmap_common_params.yaml" command="load" ns="move_base/global_costmap" />
<rosparam file="$(find lizi_navigation)/config/costmap_common_params.yaml" command="load" ns="move_base/local_costmap" />
<rosparam file="$(find lizi_navigation)/config/local_costmap_params.yaml" command="load" ns="move_base/local_costmap" />
<rosparam file="$(find lizi_navigation)/config/global_costmap_params.yaml" command="load" ns="move_base/global_costmap"/>
</group>
<group if="$(arg rviz)">
<node name="rviz" type="rviz" pkg="rviz"/>
</group>
</group>
</launch>
通過此方式啓動後各小車的話題名都會在命名空間下。如lizi117/battery。
3.通過調用move_base實現小車自主運動。
move_base提供了動作服務器接口供外部進行調用操作,我們需要建立一個客戶端去發送請求。
此處參考動作服務器的調用ros::actionlib動作服務器(action server)在動作客戶端(action client)中的調用教程。
通過rostopic list查看動作服務器的接口。move_base客戶端代碼調用參考如下:
附send_goal.cpp、CMakeLists.txt 、package.xml
/*
* send_goal.cpp
*
* Created on: 2018.11.15
* Author: wxw
*/
#include <ros/ros.h>
#include <move_base_msgs/MoveBaseAction.h>
#include <actionlib/client/simple_action_client.h>
/*move_base_msgs::MoveBaseAction
move_base在world中的目標
*/
typedef actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> MoveBaseClient;
int main(int argc, char** argv) {
ros::init(argc, argv, "send_goals_node");
/*
// create the action client
// true causes the client to spin its own thread
//don't need ros::spin()
創建action客戶端,參數1:action名,參數2:true,不需要手動調用ros::spin(),會在它的線程中自動調用。
*/
MoveBaseClient ac("move_base", true);
// Wait 60 seconds for the action server to become available
ROS_INFO("Waiting for the move_base action server");
ac.waitForServer(ros::Duration(60));
ROS_INFO("Connected to move base server");
// Send a goal to move_base1
//目標的屬性設置
move_base_msgs::MoveBaseGoal goal;
goal.target_pose.header.frame_id = "map";
goal.target_pose.header.stamp = ros::Time::now();
goal.target_pose.pose.position.x = 0.262;
goal.target_pose.pose.position.y = 0.2;
goal.target_pose.pose.orientation.z = -0.78;
goal.target_pose.pose.orientation.w = 0.618;
ROS_INFO("");
ROS_INFO("Sending goal");
ac.sendGoal(goal);
// Wait for the action to return
ac.waitForResult();
if (ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
ROS_INFO("You have reached the goal!");
else
ROS_INFO("The base failed for some reason");
// Send a goal to move_base2
//目標的屬性設置
move_base_msgs::MoveBaseGoal goal;
goal.target_pose.header.frame_id = "map";
goal.target_pose.header.stamp = ros::Time::now();
goal.target_pose.pose.position.x = 1.18;
goal.target_pose.pose.orientation.z = -0.175;
goal.target_pose.pose.orientation.w = 0.98;
ROS_INFO("");
ROS_INFO("Sending goal");
ac.sendGoal(goal);
// Wait for the action to return
ac.waitForResult();
if (ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
ROS_INFO("You have reached the goal!");
else
ROS_INFO("The base failed for some reason");
return 0;
}
#CMakeLists.txt
cmake_minimum_required(VERSION 2.8.3)
project(movewanted)
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
geometry_msgs
sensor_msgs
nav_msgs
tf
actionlib
move_base_msgs
)
catkin_package(
INCLUDE_DIRS
CATKIN_DEPENDS roscpp std_msgs sensor_msgs geometry_msgs nav_msgs actionlib move_base_msgs
)
include_directories(
${catkin_INCLUDE_DIRS}
)
link_directories(
${catkin_LIB_DIRS} )
add_executable(send_goal src/send_goal.cpp)
target_link_libraries(send_goal
${catkin_LIBRARIES}
)
<!--package.xml-->
<?xml version="1.0"?>
<package>
<name>movewanted</name>
<version>1.0.0</version>
<description>The move point package</description>
<maintainer email="[email protected]">wxw</maintainer>
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>roscpp</build_depend>
<build_depend>rospy</build_depend>
<build_depend>rostime</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>geometry_msgs</build_depend>
<build_depend>nav_msgs</build_depend>
<build_depend>move_base_msgs</build_depend>
<build_depend>actionlib</build_depend>
<build_depend>tf</build_depend>
<test_depend>rosbag</test_depend>
<run_depend>roscpp</run_depend>
<run_depend>rospy</run_depend>
<run_depend>rostime</run_depend>
<run_depend>std_msgs</run_depend>
<run_depend>sensor_msgs</run_depend>
<run_depend>geometry_msgs</run_depend>
<run_depend>nav_msgs</run_depend>
<run_depend>move_base_msgs</run_depend>
<run_depend>actionlib</run_depend>
<run_depend>tf</run_depend>
</package>