Tutorial: Controlling navigation speed - subodh-malgonde/Robotics GitHub Wiki
The navigation speed of the robot is specified through a couple of launch files. In order to modify these launch files, you will need to create a copy of them and run those copies instead.
Make copies of the launch files
In addition to copying the main fetch_nav.launch file, we need to copy an additional file that is included by fetch_nav.launch.
You can see what files are included in fetch_nav.launch by running rosed fetch_navigation fetch_nav.launch.
cd fetch_api/launch
roscp fetch_navigation fetch_nav.launch .
roscp fetch_navigation move_base.launch.xml .
ls
You should see two new files: fetch_nav.launch and move_base.launch.xml.
Make a copy of the config files
If you look at move_base.launch.xml, you will see that loads two configuration files related to the move_base node: move_base.yaml and fetch/move_base.yaml.
Create a folder named config if it doesn't exist and copy these two files:
cd fetch_api/config
Both files are named move_base.yaml, so roscp will ask you which one to copy.
This command copies the main move_base.yaml (double check the numbers, which may be different for you):
> roscp fetch_navigation move_base.yaml .
You have chosen a non-unique filename, please pick one of the following:
1) /opt/ros/indigo/share/fetch_navigation/config/freight/move_base.yaml
2) /opt/ros/indigo/share/fetch_navigation/config/move_base.yaml
3) /opt/ros/indigo/share/fetch_navigation/config/fetch/move_base.yaml
#? 2
/opt/ros/indigo/share/fetch_navigation/config/move_base.yaml
This command copies the Fetch-specific configuration:
> roscp fetch_navigation move_base.yaml fetch_move_base.yaml
You have chosen a non-unique filename, please pick one of the following:
1) /opt/ros/indigo/share/fetch_navigation/config/freight/move_base.yaml
2) /opt/ros/indigo/share/fetch_navigation/config/move_base.yaml
3) /opt/ros/indigo/share/fetch_navigation/config/fetch/move_base.yaml
#? 3
/opt/ros/indigo/share/fetch_navigation/config/fetch/move_base.yaml
Edit the launch files
To run the modified versions of the launch files, you will need to start navigation using this command from now on:
roslaunch fetch_api fetch_nav.launch
Also be sure to edit any launch files you have that include fetch_nav.launch:
<include file="$(find fetch_api)/launch/fetch_nav.launch">
However, you also need to edit your copy of fetch_nav.launch to use your copy of move_base.launch.xml and the two move_base.yamls.
Edit fetch_nav.launch and replace:
<arg name="move_base_include" default="$(find fetch_navigation)/launch/include/move_base.launch.xml" />
with:
<arg name="move_base_include" default="$(find fetch_api)/launch/move_base.launch.xml" />
Edit move_base.launch.xml and replace:
<rosparam file="$(find fetch_navigation)/config/move_base.yaml" command="load" />
<rosparam file="$(find fetch_navigation)/config/$(arg name)/move_base.yaml" command="load" />
with (notice the three differences on the two lines):
<rosparam file="$(find fetch_api)/config/move_base.yaml" command="load" />
<rosparam file="$(find fetch_api)/config/fetch_move_base.yaml" command="load" />
Setting the global max speed
If you just want the robot to move more slowly overall, you can change some navigation parameters, which are read once when fetch_nav.launch starts.
Edit fetch_move_base.yaml and set the max_vel_x parameter from 1.0 to something slower, like 0.3.
You can also limit its angular velocity (spinning speed) by changing {min,max}_vel_theta.
max_vel_x is in meters/second, {min,max}_vel_theta are in radians/second.
You can experiment with the tolerances in move_base.yaml (yaw_goal_tolerance and xy_goal_tolerance).
However, we have not tested how tight of tolerances the robot can actually achieve.
Refer to the course repository for a working example of the launch/config files and the edits we made.
Dynamically adjusting the robot's speed
To dynamically adjust the robot's speed during navigation, we can rewrite the commanded velocities from move_base.
First, edit launch/move_base.launch.xml:
- <arg name="cmd_vel_topic" default="cmd_vel" />
+ <arg name="cmd_vel_topic" default="move_base_cmd_vel" />
Now, the move_base node will send velocity commands to the move_base_cmd_vel topic, which has no effect on the robot.
To get the robot moving again, we will republish the commands.
Create fetch_api/scripts/navigation_controller.py:
#! /usr/bin/env python
"""Republishes navigation commands at user-controllable speeds.
"""
import geometry_msgs.msg
import numpy as np
import rospy
import std_msgs.msg
class NavigationController(object):
def __init__(self, cmd_vel_pub):
self._cmd_vel_pub = cmd_vel_pub
self._max_speed = 1.0 # In meters/second
def nav_cmd_vel_callback(self, twist):
vec = np.array([twist.linear.x, twist.linear.y])
commanded_speed = np.linalg.norm(vec)
if commanded_speed > self._max_speed:
squared_speed = commanded_speed * commanded_speed
max_squared = self._max_speed * self._max_speed
slow_factor = squared_speed / max_squared
twist.linear.x /= slow_factor
twist.linear.y /= slow_factor
self._cmd_vel_pub.publish(twist)
def max_speed_callback(self, msg):
rospy.loginfo('Setting max speed to {}'.format(msg.data))
self._max_speed = msg.data
def main():
rospy.init_node('navigation_speed_controller')
cmd_vel_pub = rospy.Publisher('cmd_vel', geometry_msgs.msg.Twist, queue_size=10)
controller = NavigationController(cmd_vel_pub)
sub = rospy.Subscriber('move_base_cmd_vel', geometry_msgs.msg.Twist, controller.nav_cmd_vel_callback)
sub = rospy.Subscriber('navigation_controller/max_speed', std_msgs.msg.Float32, controller.max_speed_callback)
rospy.spin()
if __name__ == '__main__':
main()
Make it executable:
chmod +x fetch_api/scripts/navigation_controller.py
This node subscribes to move_base's commanded velocities on move_base_cmd_vel.
In its callback, it checks if the commanded speed exceeds a threshold.
If so, it scales the speed such that the overall speed is at most the threshold.
It then publishes the modified message to cmd_vel.
To change the maximum speed, publish the new maximum speed to navigation_controller/max_speed, which is of type std_msgs/Float32.
You will need to run this node in conjunction with fetch_nav.launch.
In the course repo, we have modified fetch_api/launch/fetch_nav.launch to also start navigation_controller as well.