You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ROS_INFO("Spinning until killed publishing %s to world", static_turtle_name.c_str());
1902
+
ros::spin();
1903
+
return 0;
1904
+
};
1905
+
```
1906
+
Lets understand the code. First we create a broadcaster object of type `StaticTransformBroadcaster`. This will be used to broadcast transforms over ROS. Then we create the transform packet, which is of type `geometry_msgs::TransformStamped`.
1907
+
1908
+
1909
+
Instead of writing a custom broadcaster, we privilige the use of tf2_ros api for broadcasting messages. tf2_ros::static_broadcast_publisher can be used as a node to publish transforms. Normally, we invoke these nodes from roslaunch files.
if (argc != 2){ROS_ERROR("need turtle name as argument"); return -1;};
1953
+
turtle_name = argv[1];
1954
+
}
1955
+
else
1956
+
{
1957
+
private_node.getParam("turtle", turtle_name);
1958
+
}
1959
+
1960
+
ros::NodeHandle node;
1961
+
ros::Subscriber sub = node.subscribe(turtle_name+"/pose", 10, &poseCallback);
1962
+
1963
+
ros::spin();
1964
+
return 0;
1965
+
};
1966
+
```
1967
+
Here, we create a node representing the parent frame, which has a callback function. The callback function is passed the sensor message that tells it the relative pose of the child frame with respect to it. Itthen calculate the transform and populates the TransformStamped object. This is then broadcast.
1968
+
1969
+
### Listener
1970
+
The basic code for a listener is as follows
1971
+
```
1972
+
tf2_ros::Buffer tfBuffer;
1973
+
tf2_ros::TransformListener tfListener(tfBuffer);
1974
+
```
1975
+
Once the listener is instantiated, it starts receiving tf2 transformations over the wire and buffers them for upto 10 seconds. The TransformListener object should be scoped to persist. If it does not persist, then its cache will be unable to fill and almost every query will fail.
1976
+
1977
+
To obtain transform between two frames "turtle1" and "turtle2", we invoke the following
tf2 allows you to define a local frame for each sensor, link in your system. For every frame we need to add to the system, we need to create a node. In the code for that node, we instantiate a broadcaster and TransformStamped object. We assign our new frame as child_frame_id and one of the existing frames as parent frame.
1982
+
1843
1983
## Navigation Stack
1844
1984
The job of thenavigation stack is to take information from odometry and sensor streams and output velocity commands to a mobile base. A navigation stack requires that the robot should be publishing sensor messages of the correct type and have a tf transform tree in place. The navigation stack also needs to be configured for the shape and dynamics of the specific robot to perform at a high level.
1845
1985
@@ -1851,7 +1991,146 @@ Navigation stack assumes that robot is configured in a particular manner in orde
1851
1991
The white components are required components. The blue components must be created for each robot. Gray components are optional and already implemented.
1852
1992
1853
1993
1. Setup up the [transform configuration](http://wiki.ros.org/navigation/Tutorials/RobotSetup/TF)
1854
-
2.
1994
+
2. Sensor Information
1995
+
3. Odometry Information
1996
+
4. Base Controller
1997
+
5. Mapping
1998
+
1999
+
### Transform Configuration
2000
+
We will understand the basics of transform configuration. We will use these techniques to configure the transform for our turtlebot.
2001
+
2002
+
Lets assume we have a robot with a geometry identified in the image below
2003
+

2004
+
2005
+
2006
+
To define and store the relationship between base_link and base_laser frames using tf, we need to add them to a transform tree. To create a trasnform tree for our simple example, we'll create two nodes, one for "base_link" and other for "base_laser" coordinate frames. Before creating edges, we need to assign one node as parent or reference node. Assuming base_link to be the parent, we calculate transform as
2007
+
x:0.1, y:0, z:0.2.
2008
+
2009
+
Once this transform tree is setup, converting the laser scan received in base_laser to base_link is done by making a call to tf library.
2010
+
2011
+
Let's make this concrete by looking at some code
2012
+
2013
+
#### Code Description
2014
+
Our goal is to transform the laser data to base_link frame. So how to build the transform tree.
2015
+
2016
+
First, we create a node responsible for publishing the transform in our system. Next we create a listener node to transform data published over ROS. This node will be capable of applying the transform to a point.
2017
+
2018
+
We will create a catkin package for our robot.
2019
+
```
2020
+
> mkdir -p ~/tutorial_ws/src
2021
+
> cd ~/tutorial_ws/src/
2022
+
> catkin_create_pkg robot_setup_tf roscpp tf geometry_msgs # these are dependencies for this package
2023
+
```
2024
+
**Broadcaster Node**</br>
2025
+
Now we create the broadcaster node, which will broadcast the base_laser -> base_link transform over ROS.
We use the `tf::TransformBroadcaster` object, to publish transforms. The `sendTransform` method requires 5 arguments which are
2053
+
1. rotation transform: this is in quaternion format
2054
+
2. translation transform: we determine the position of laser_link w.r.t. base_link.
2055
+
3. timestamp: time at which this transform was calculated
2056
+
4. parent node: name of parent node
2057
+
5. child node: name of child node
2058
+
2059
+
2060
+
**Using Transform: Listener Node**</br>
2061
+
We are going to write a node that uses the published transform. It will take a point in laser_link frame as input and transform it to represent it in base_link frame.
We need to create a `tf:TransformListener` object. It automatically subscribes to the transform message topic over ROS and manager all transform data coming in over the wire.
2113
+
2114
+
We create a custom function `transformPoint(const tf::TransformListener & listener)`, that takes a point in laser_link frame and transforms it to base_link frame. This function will serve as callback for ros::Timer created in main() of our program.
2115
+
2116
+
2117
+
Suppose we have a point in the laser_link frame like `geometry_msgs::PointStamped laser_point`. We want to transform it to `base_point` which is of the same type. To perform this transform, we'll call the `transformPoint` method of the `tf::TransformListener` object. This method takes 3 arguments.
2118
+
2119
+
1. target frame name: base_link in our case
2120
+
2. TransformPoint object to be transformed: the point we are transforming
2121
+
3. TransformPoint object to hold the result:
2122
+
2123
+
#### Building the code
2124
+
Now we modify the CMakeLists.txt file and add the following lines
0 commit comments