Gazebo环境下基于ROS的阿克曼小车键盘控制
1. 创建资源
开始实验之前,您需要先创建实验相关资源。
- 在实验室页面,单击创建资源。
- (可选)在实验室页面左侧导航栏中,单击云产品资源列表,可查看本次实验资源相关信息(例如IP地址、子用户信息等)。
说明:资源创建过程需要3~5分钟(视资源不同开通时间有所差异,ACK等资源开通时间较长)。完成实验资源的创建后,您可以在云产品资源列表查看已创建的资源信息,例如:子用户名称、子用户密码、AK ID、AK Secret、资源中的项目名称等。
实验环境一旦开始创建则进入计时阶段,建议学员先基本了解实验具体的步骤、目的,真正开始做实验时再进行创建。
资源创建成功,可在左侧的资源卡片中查看相关资源信息以及RAM子账号信息
2. 进入Docker镜像
新建内容打开火狐浏览器。
通过RAM用户名密码登录页面,输入子用户密码登录账号。
登陆后选择左侧产品与服务中的云服务器ECS。
在所有云服务器中通过左下角地域找到正确的服务器并点击远程连接。
选择通过VNC远程连接。
选择重置VNC密码并设置新的密码后登录。
设置好进入各选项后进入Ubuntu桌面。
右键打开终端,输入命令sudo docker run -it --rm -p 6080:80 aliyun_demo运行镜像aliyun_demo。
运行成功后打开浏览器,在地址一栏输入127.0.0.1:6080进入镜像系统。
3. 代码部分
键盘控制程序使用的是raceworld1场景,由raceworld1.launch文件启动。找到/root/aliyun_demo/src/raceworld/launch文件夹中的raceworld1.launch文件并打开。
在launch文件内加载了多个控制器,其中left_rear_wheel_velocity_controller, right_rear_wheel_velocity_controller,left_front_wheel_velocity_controller,right_front_wheel_velocity_controller,left_steering_hinge_position_controller和right_steering_hinge_position_controller接收ROS消息,分别控制了左右后轮速度,左右前轮速度和转向角度。
<node name="controller_manager" pkg="controller_manager" type="spawner" respawn="false" output="screen" args="left_rear_wheel_velocity_controller right_rear_wheel_velocity_controller left_front_wheel_velocity_controller right_front_wheel_velocity_controller left_steering_hinge_position_controller right_steering_hinge_position_controller joint_state_controller"/>
在加载控制器代码的下面,加载了一个名为servo_comannds1.py的代码文件。
<node pkg="raceworld" type="servo_commands1.py" name="servo_commands" output="screen" >
打开/root/aliyun_demo/src/raceworld/scripts文件夹中的servo_comannds1.py文件我们可以看到,代码中新建了一个名为servo_comannds的节点,他订阅并接收/deepracer1/ackermann_cmd_mux/output消息。
def servo_commands(): global flag_move rospy.init_node('servo_commands', anonymous=True) # robot_name = rospy.get_param('~robot_name') rospy.Subscriber("/deepracer1/ackermann_cmd_mux/output", AckermannDriveStamped, set_throttle_steer) # spin() simply keeps python from exiting until this node is stopped rospy.spin() if __name__ == '__main__': try: servo_commands() except rospy.ROSInterruptException: pass
在接收到消息后,经过适当的转换,将速度和转向信息发布给之前所述六个控制器。
def set_throttle_steer(data): global flag_move pub_vel_left_rear_wheel = rospy.Publisher("/deepracer1/left_rear_wheel_velocity_controller/command", Float64, queue_size=1) pub_vel_right_rear_wheel = rospy.Publisher("/deepracer1/right_rear_wheel_velocity_controller/command", Float64, queue_size=1) pub_vel_left_front_wheel = rospy.Publisher("/deepracer1/left_front_wheel_velocity_controller/command", Float64, queue_size=1) pub_vel_right_front_wheel = rospy.Publisher("/deepracer1/right_front_wheel_velocity_controller/command", Float64, queue_size=1) pub_pos_left_steering_hinge = rospy.Publisher("/deepracer1/left_steering_hinge_position_controller/command", Float64, queue_size=1) pub_pos_right_steering_hinge = rospy.Publisher("/deepracer1/right_steering_hinge_position_controller/command", Float64, queue_size=1) throttle = data.drive.speed*28 print("Throttle:",throttle) steer = data.drive.steering_angle print("Steer:",steer) pub_vel_left_rear_wheel.publish(throttle) pub_vel_right_rear_wheel.publish(throttle) pub_vel_left_front_wheel.publish(throttle) pub_vel_right_front_wheel.publish(throttle) pub_pos_left_steering_hinge.publish(steer) pub_pos_right_steering_hinge.publish(steer) print("Message From servo_commands1.py Published\n")
键盘控制程序需要运行/root/aliyun_demo/src/raceworld/scripts文件夹中的key_op.py文件。
首先需要获取按键输入。
def getKey(): tty.setraw(sys.stdin.fileno()) select.select([sys.stdin], [], [], 0) key = sys.stdin.read(1) termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings) return key settings = termios.tcgetattr(sys.stdin) def pub_cmd(): index = 1 rospy.init_node("pub_cmd") pub = rospy.Publisher("/deepracer"+str(index)+"/ackermann_cmd_mux/output", AckermannDriveStamped, queue_size=10) akm = AckermannDriveStamped() while 1: x=0 a=0 key = getKey()
然后分别根据按键设置对应的速度以及转角。W为前进,S为后退,A为左前进,D为右前进,X为停止行驶,O为退出程序。
if key == 'w': print("Front") x=0.3 a=0 elif key == 's': print("Back") x=-0.3 a=0 elif key == 'a': print("Front Left") x=0.3 a=2 elif key == 'd': print("Front Right") x=0.3 a=-0.7 elif key == 'x': print("Stop") x=0 a=0 elif key == 'o': print("Exit") break else: continue
新建一个AckermannDriveStamped类型的消息并设置好相应数据后,将其作为/deepracer1/ackermann_cmd_mux/output消息发布,之后经由servo_comannd1.py中所设置的节点转换后发布给控制器,以此实现键盘对小车的控制。
akm.drive.speed = x print("Speed:",akm.drive.speed) akm.drive.steering_angle = a print("Steering_Angle:",akm.drive.steering_angle) pub.publish(akm) print("Message From key_op.py Published\n")
4. 实验操作
打开终端,输入如图所示命令开启raceworld1 Gazebo场景。
cd aliyun_demo source devel/setup.bash roslaunch raceworld raceworld1.launch
随后新建另一个终端并输入如图所示命令运行键盘控制程序。
cd aliyun_demo source devel/setup.bash rosrun raceworld key_op.py
当按下对应的按键时,小车就会开始移动。并且在两个终端中可以看到消息的发布与接收。
这时新建终端,并输入命令rostopic list,我们可以在其中找到/deepracer1/ackermann_cmd_mux/output主题。
输入rostopic info /deepracer1/ackermann_cmd_mux/output我们可以查看该主题的发布者与接收者。
同样,如果我们查看/deepracer1/left_rear_wheel_velocity_controller/command主题信息的话将会看到发布者是servo_comannds1.py中所创建的servo_commands节点,订阅者是/gazebo。
实验地址:https://developer.aliyun.com/adc/scenario/a0cd78582e2a462a8d294d9450213018