机器人编程趣味实践14-机器人三维仿真(Gazebo+TurtleBot3)
【摘要】 之前,介绍了节点、主题、服务和行动等基本概念,以及rqt和rosbag2等工具。
采用了官方改版的二维环境,那么现在玩耍一下更为逼真的三维仿真环境吧。
仿真软件Gazebo机器人TurtleBot3
TurtleBot3支持仿真开发环境,可以在仿真中用虚拟机器人编程开发。 有两种开发环境可以做到这一点,一种是使用带有 3D 可视化工具 RViz 的假节点,另一种是使用...
之前,介绍了节点、主题、服务和行动等基本概念,以及rqt和rosbag2等工具。
采用了官方改版的二维环境,那么现在玩耍一下更为逼真的三维仿真环境吧。
- 仿真软件Gazebo
- 机器人TurtleBot3
TurtleBot3支持仿真开发环境,可以在仿真中用虚拟机器人编程开发。 有两种开发环境可以做到这一点,一种是使用带有 3D 可视化工具 RViz 的假节点,另一种是使用 3D 机器人模拟器 Gazebo。
- 假节点适合用机器人模型和运动进行测试,但不支持传感器。
- 如果需要执行 SLAM 或导航,Gazebo 将是一个可行的解决方案,因为它支持 IMU、LDS 和摄像头等传感器。
环境配置
-
# TURTLEBOT3_MODEL
-
export GAZEBO_MODEL_PATH=$GAZEBO_MODEL_PATH:/home/zhangrelay/RobSoft/turtlebot3/src/simulations/turtlebot3_gazebo/models
-
export TURTLEBOT3_MODEL=burger
-
-
# ROS2
-
source /opt/ros/foxy/setup.bash
-
-
#colcon
-
source /usr/share/colcon_cd/function/colcon_cd.sh
源码编译
可以使用deb直接安装:
- sudo apt install ros-foxy-turtlebot3-gazebo
注意包要装全。
这里,采用源码编译如下:
- colcon build
功能包列表如上所示。
仿真实践
1 启动环境
- ros2 launch turtlebot3_gazebo empty_world.launch.py
蓝色射线为激光的可视化效果。
empty_world.launch代码如下:
-
import os
-
-
from ament_index_python.packages import get_package_share_directory
-
from launch import LaunchDescription
-
from launch.actions import ExecuteProcess
-
from launch.actions import IncludeLaunchDescription
-
from launch.launch_description_sources import PythonLaunchDescriptionSource
-
from launch.substitutions import LaunchConfiguration
-
-
TURTLEBOT3_MODEL = os.environ['TURTLEBOT3_MODEL']
-
-
-
def generate_launch_description():
-
use_sim_time = LaunchConfiguration('use_sim_time', default='True')
-
world_file_name = 'empty_worlds/' + TURTLEBOT3_MODEL + '.model'
-
world = os.path.join(get_package_share_directory('turtlebot3_gazebo'),
-
'worlds', world_file_name)
-
launch_file_dir = os.path.join(get_package_share_directory('turtlebot3_gazebo'), 'launch')
-
pkg_gazebo_ros = get_package_share_directory('gazebo_ros')
-
-
return LaunchDescription([
-
IncludeLaunchDescription(
-
PythonLaunchDescriptionSource(
-
os.path.join(pkg_gazebo_ros, 'launch', 'gzserver.launch.py')
-
),
-
launch_arguments={'world': world}.items(),
-
),
-
-
IncludeLaunchDescription(
-
PythonLaunchDescriptionSource(
-
os.path.join(pkg_gazebo_ros, 'launch', 'gzclient.launch.py')
-
),
-
),
-
-
ExecuteProcess(
-
cmd=['ros2', 'param', 'set', '/gazebo', 'use_sim_time', use_sim_time],
-
output='screen'),
-
-
IncludeLaunchDescription(
-
PythonLaunchDescriptionSource([launch_file_dir, '/robot_state_publisher.launch.py']),
-
launch_arguments={'use_sim_time': use_sim_time}.items(),
-
),
-
])
2 圆周运动
之前和之前二维环境圆周运动的指令非常类似哦。
- ros2 topic pub --rate 2 /cmd_vel geometry_msgs/msg/Twist "{linear: {x: 1.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.8}}"
3 键盘遥控
使用如下命令启动键盘遥控:
- ros2 run turtlebot3_teleop teleop_keyboard
键盘遥控代码如下:
-
import os
-
import select
-
import sys
-
import rclpy
-
-
from geometry_msgs.msg import Twist
-
from rclpy.qos import QoSProfile
-
-
if os.name == 'nt':
-
import msvcrt
-
else:
-
import termios
-
import tty
-
-
BURGER_MAX_LIN_VEL = 0.22
-
BURGER_MAX_ANG_VEL = 2.84
-
-
WAFFLE_MAX_LIN_VEL = 0.26
-
WAFFLE_MAX_ANG_VEL = 1.82
-
-
LIN_VEL_STEP_SIZE = 0.01
-
ANG_VEL_STEP_SIZE = 0.1
-
-
TURTLEBOT3_MODEL = os.environ['TURTLEBOT3_MODEL']
-
-
msg = """
-
Control Your TurtleBot3!
-
---------------------------
-
Moving around:
-
w
-
a s d
-
x
-
-
w/x : increase/decrease linear velocity (Burger : ~ 0.22, Waffle and Waffle Pi : ~ 0.26)
-
a/d : increase/decrease angular velocity (Burger : ~ 2.84, Waffle and Waffle Pi : ~ 1.82)
-
-
space key, s : force stop
-
-
CTRL-C to quit
-
"""
-
-
e = """
-
Communications Failed
-
"""
-
-
-
def get_key(settings):
-
if os.name == 'nt':
-
return msvcrt.getch().decode('utf-8')
-
tty.setraw(sys.stdin.fileno())
-
rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
-
if rlist:
-
key = sys.stdin.read(1)
-
else:
-
key = ''
-
-
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
-
return key
-
-
-
def print_vels(target_linear_velocity, target_angular_velocity):
-
print('currently:\tlinear velocity {0}\t angular velocity {1} '.format(
-
target_linear_velocity,
-
target_angular_velocity))
-
-
-
def make_simple_profile(output, input, slop):
-
if input > output:
-
output = min(input, output + slop)
-
elif input < output:
-
output = max(input, output - slop)
-
else:
-
output = input
-
-
return output
-
-
-
def constrain(input_vel, low_bound, high_bound):
-
if input_vel < low_bound:
-
input_vel = low_bound
-
elif input_vel > high_bound:
-
input_vel = high_bound
-
else:
-
input_vel = input_vel
-
-
return input_vel
-
-
-
def check_linear_limit_velocity(velocity):
-
if TURTLEBOT3_MODEL == 'burger':
-
return constrain(velocity, -BURGER_MAX_LIN_VEL, BURGER_MAX_LIN_VEL)
-
else:
-
return constrain(velocity, -WAFFLE_MAX_LIN_VEL, WAFFLE_MAX_LIN_VEL)
-
-
-
def check_angular_limit_velocity(velocity):
-
if TURTLEBOT3_MODEL == 'burger':
-
return constrain(velocity, -BURGER_MAX_ANG_VEL, BURGER_MAX_ANG_VEL)
-
else:
-
return constrain(velocity, -WAFFLE_MAX_ANG_VEL, WAFFLE_MAX_ANG_VEL)
-
-
-
def main():
-
settings = None
-
if os.name != 'nt':
-
settings = termios.tcgetattr(sys.stdin)
-
-
rclpy.init()
-
-
qos = QoSProfile(depth=10)
-
node = rclpy.create_node('teleop_keyboard')
-
pub = node.create_publisher(Twist, 'cmd_vel', qos)
-
-
status = 0
-
target_linear_velocity = 0.0
-
target_angular_velocity = 0.0
-
control_linear_velocity = 0.0
-
control_angular_velocity = 0.0
-
-
try:
-
print(msg)
-
while(1):
-
key = get_key(settings)
-
if key == 'w':
-
target_linear_velocity =\
-
check_linear_limit_velocity(target_linear_velocity + LIN_VEL_STEP_SIZE)
-
status = status + 1
-
print_vels(target_linear_velocity, target_angular_velocity)
-
elif key == 'x':
-
target_linear_velocity =\
-
check_linear_limit_velocity(target_linear_velocity - LIN_VEL_STEP_SIZE)
-
status = status + 1
-
print_vels(target_linear_velocity, target_angular_velocity)
-
elif key == 'a':
-
target_angular_velocity =\
-
check_angular_limit_velocity(target_angular_velocity + ANG_VEL_STEP_SIZE)
-
status = status + 1
-
print_vels(target_linear_velocity, target_angular_velocity)
-
elif key == 'd':
-
target_angular_velocity =\
-
check_angular_limit_velocity(target_angular_velocity - ANG_VEL_STEP_SIZE)
-
status = status + 1
-
print_vels(target_linear_velocity, target_angular_velocity)
-
elif key == ' ' or key == 's':
-
target_linear_velocity = 0.0
-
control_linear_velocity = 0.0
-
target_angular_velocity = 0.0
-
control_angular_velocity = 0.0
-
print_vels(target_linear_velocity, target_angular_velocity)
-
else:
-
if (key == '\x03'):
-
break
-
-
if status == 20:
-
print(msg)
-
status = 0
-
-
twist = Twist()
-
-
control_linear_velocity = make_simple_profile(
-
control_linear_velocity,
-
target_linear_velocity,
-
(LIN_VEL_STEP_SIZE / 2.0))
-
-
twist.linear.x = control_linear_velocity
-
twist.linear.y = 0.0
-
twist.linear.z = 0.0
-
-
control_angular_velocity = make_simple_profile(
-
control_angular_velocity,
-
target_angular_velocity,
-
(ANG_VEL_STEP_SIZE / 2.0))
-
-
twist.angular.x = 0.0
-
twist.angular.y = 0.0
-
twist.angular.z = control_angular_velocity
-
-
pub.publish(twist)
-
-
except Exception as e:
-
print(e)
-
-
finally:
-
twist = Twist()
-
twist.linear.x = 0.0
-
twist.linear.y = 0.0
-
twist.linear.z = 0.0
-
-
twist.angular.x = 0.0
-
twist.angular.y = 0.0
-
twist.angular.z = 0.0
-
-
pub.publish(twist)
-
-
if os.name != 'nt':
-
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
-
-
-
if __name__ == '__main__':
-
main()
简单加入中文方便使用:
阅读源码非常重要。
4 节点
5 主题
6 服务
ros2 service list -t
- /apply_joint_effort [gazebo_msgs/srv/ApplyJointEffort]
- /apply_link_wrench [gazebo_msgs/srv/ApplyLinkWrench]
- /clear_joint_efforts [gazebo_msgs/srv/JointRequest]
- /clear_link_wrenches [gazebo_msgs/srv/LinkRequest]
- /delete_entity [gazebo_msgs/srv/DeleteEntity]
- /gazebo/describe_parameters [rcl_interfaces/srv/DescribeParameters]
- /gazebo/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
- /gazebo/get_parameters [rcl_interfaces/srv/GetParameters]
- /gazebo/list_parameters [rcl_interfaces/srv/ListParameters]
- /gazebo/set_parameters [rcl_interfaces/srv/SetParameters]
- /gazebo/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
- /get_model_list [gazebo_msgs/srv/GetModelList]
- /pause_physics [std_srvs/srv/Empty]
- /reset_simulation [std_srvs/srv/Empty]
- /reset_world [std_srvs/srv/Empty]
- /robot_state_publisher/describe_parameters [rcl_interfaces/srv/DescribeParameters]
- /robot_state_publisher/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
- /robot_state_publisher/get_parameters [rcl_interfaces/srv/GetParameters]
- /robot_state_publisher/list_parameters [rcl_interfaces/srv/ListParameters]
- /robot_state_publisher/set_parameters [rcl_interfaces/srv/SetParameters]
- /robot_state_publisher/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
- /rqt_gui_py_node_4338/describe_parameters [rcl_interfaces/srv/DescribeParameters]
- /rqt_gui_py_node_4338/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
- /rqt_gui_py_node_4338/get_parameters [rcl_interfaces/srv/GetParameters]
- /rqt_gui_py_node_4338/list_parameters [rcl_interfaces/srv/ListParameters]
- /rqt_gui_py_node_4338/set_parameters [rcl_interfaces/srv/SetParameters]
- /rqt_gui_py_node_4338/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
- /spawn_entity [gazebo_msgs/srv/SpawnEntity]
- /teleop_keyboard/describe_parameters [rcl_interfaces/srv/DescribeParameters]
- /teleop_keyboard/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
- /teleop_keyboard/get_parameters [rcl_interfaces/srv/GetParameters]
- /teleop_keyboard/list_parameters [rcl_interfaces/srv/ListParameters]
- /teleop_keyboard/set_parameters [rcl_interfaces/srv/SetParameters]
- /teleop_keyboard/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
- /turtlebot3_diff_drive/describe_parameters [rcl_interfaces/srv/DescribeParameters]
- /turtlebot3_diff_drive/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
- /turtlebot3_diff_drive/get_parameters [rcl_interfaces/srv/GetParameters]
- /turtlebot3_diff_drive/list_parameters [rcl_interfaces/srv/ListParameters]
- /turtlebot3_diff_drive/set_parameters [rcl_interfaces/srv/SetParameters]
- /turtlebot3_diff_drive/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
- /turtlebot3_imu/describe_parameters [rcl_interfaces/srv/DescribeParameters]
- /turtlebot3_imu/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
- /turtlebot3_imu/get_parameters [rcl_interfaces/srv/GetParameters]
- /turtlebot3_imu/list_parameters [rcl_interfaces/srv/ListParameters]
- /turtlebot3_imu/set_parameters [rcl_interfaces/srv/SetParameters]
- /turtlebot3_imu/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
- /turtlebot3_joint_state/describe_parameters [rcl_interfaces/srv/DescribeParameters]
- /turtlebot3_joint_state/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
- /turtlebot3_joint_state/get_parameters [rcl_interfaces/srv/GetParameters]
- /turtlebot3_joint_state/list_parameters [rcl_interfaces/srv/ListParameters]
- /turtlebot3_joint_state/set_parameters [rcl_interfaces/srv/SetParameters]
- /turtlebot3_joint_state/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
- /turtlebot3_laserscan/describe_parameters [rcl_interfaces/srv/DescribeParameters]
- /turtlebot3_laserscan/get_parameter_types [rcl_interfaces/srv/GetParameterTypes]
- /turtlebot3_laserscan/get_parameters [rcl_interfaces/srv/GetParameters]
- /turtlebot3_laserscan/list_parameters [rcl_interfaces/srv/ListParameters]
- /turtlebot3_laserscan/set_parameters [rcl_interfaces/srv/SetParameters]
- /turtlebot3_laserscan/set_parameters_atomically [rcl_interfaces/srv/SetParametersAtomically]
- /unpause_physics [std_srvs/srv/Empty]
7 行动
SLAM和导航时候再补充。
8 更多
可参考前13篇中对应案例,在此三维环境中进行实践哦。
总结
由二维环境到三维环境,仿真更炫酷,但是原理和指令几乎一样,学一招全掌控!
文章来源: zhangrelay.blog.csdn.net,作者:zhangrelay,版权归原作者所有,如需转载,请联系作者。
原文链接:zhangrelay.blog.csdn.net/article/details/117570035
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)