Robotics StackExchange | Archived questions

Basic robot_localization example

I am attempting to get the most basic example of robot_localization working on a raspberry pi. I am new to linux and the ROS ecosystem, so I have fought through an exceptional number of issues to get it working. The information necessary to do this seems to be somewhat fragmented or over complicated for a beginner.

In order to do the localization I am using the BNO055 IMU by bosch that outputs orientation as well as standard IMU data. I am also using two incremental encoders on the wheels of lets say a "cart." This example is as simple as it can get, There are no motors and I just want to know the position of a cart that is pushed externally.

I have the system working, and it looks like filtered odom data seems to be more accurate, but I am having trouble making sure I did everything right.

The most basic question... is this the proper way to use ekf node? In the very simpliest terms do these three codes seem correct? I have simplified them into the important components

The IMU uses:

#create publisher
imu_pub = rospy.Publisher('imu/data', Imu, queue_size=1)
#init node and set rate
rospy.init_node('imu_talker', anonymous=True)
rate = rospy.Rate(10) # 10hz

while not rospy.is_shutdown():
    #PLACEHOLDER TO GET DATA FROM IMU

    #create message and header
    imu = Imu()
    imu.header.stamp = rospy.Time.now()
    imu.header.frame_id = 'imu'

    #put data into the message
    imu.orientation = quaternion
    imu.angular_velocity = ang_vel 
    imu.linear_acceleration = lin_acc

    #publish message
    imu_pub.publish(imu)

    #sleep at known rate
    rate.sleep()

The ODOM uses:

#create publishers
odom_pub = rospy.Publisher("odom", Odometry, queue_size=1)
odom_broadcaster = tf.TransformBroadcaster()

#init node and rate
rospy.init_node('odom_talker', anonymous=True)
rate = rospy.Rate(10) # 10hz

while not rospy.is_shutdown():
    #PLACEHOLDER TO GET ODOMETRY FROM ENCODERS

    #create message and header
    odom = Odometry()
    odom.header.stamp = rospy.Time.now()
    odom.header.frame_id = "odom"

    #convert euler to quaternion
    odom_quat = tf.transformations.quaternion_from_euler(0, 0, th)
    #broadcast transform
    odom_broadcaster.sendTransform((x, y, 0.), odom_quat,current_time,"base_link", "odom")


    # set the position
    odom.pose.pose = Pose(Point(x, y, 0.), Quaternion(*odom_quat))

    # set the velocity
    odom.child_frame_id = "base_link"
    odom.twist.twist = Twist(Vector3(vx, vy, 0), Vector3(0, 0, vth))

    # publish the message
    odom_pub.publish(odom)

    #sleep at known rate
    rate.sleep()

The EKF launch file uses:

<launch>

    <node pkg="robot_localization" type="ekf_localization_node" name="ekf_localization" clear_params="true">
      <param name="frequency" value="10"/>  
      <param name="sensor_timeout" value="0.2"/>  
      <param name="two_d_mode" value="true"/>

      <param name="map_frame" value="map"/>
      <param name="odom_frame" value="odom"/>
      <param name="base_link_frame" value="base_link"/>
      <param name="world_frame" value="odom"/>

      <param name="odom0" value="odom"/>
      <param name="imu0" value="/imu/data"/> 

      <rosparam param="odom0_config">[true,  true,  false, 
                                      false, false, true, 
                                      true, true, false, 
                                      false, false, true,
                                      false, false, false]</rosparam>

      <rosparam param="imu0_config">[false, false, false, 
                                     true,  true,  true, 
                                     false, false, false, 
                                     true,  true,  true,
                                     true, true, true]</rosparam>

      <param name="odom0_differential" value="true"/>
      <param name="imu0_differential" value="true"/>

      <param name="imu0_remove_gravitational_acceleration" value="false"/>

      <rosparam param="process_noise_covariance">[LARGE ARRAY with small values]</rosparam>

      <rosparam param="initial_estimate_covariance">[LARGE ARRAY with 1e-9]</rosparam>

    </node>

</launch>
  1. I have read plenty about the reference frames, but I am still having trouble understanding what to do with them practically. I see that it is necessary to transform the odom frame into the baselink (or vice versa.. not sure) But I haven't found any examples that use a transform for the IMU. I have it in the "imu" frame. Does it need to be transformed to the baselink or something like that? How does ekflocalizationnode take in IMU data? I saw that some codes use the statictransformpublisher, but I can't see that it changes anything. Does the IMU need a child frame?

  2. Continuing with the IMU. Does the ekflocalizationnode accept relative changes in orientation? or when the odometry and imu both start up are they supposed to be the same orientation. This is related to question 1 I suppose. I ask this because the BNO055 can do absolute position using the magnetometer but having and extra reference frame confuses me.

  3. The only way to use the linear acceleration and angular velocity of the imu is to catch it at its output rate of 100 Hz. If I am running the IMU node at 100 Hz do you have to run the odom node at 100 hz? Do you also have to run the ekf node at 100 Hz?

  4. What should I use for initial covariance values? Just zero until I figure accurate values out? I am currently using ones from another code for the IMU and zeroes for the odom. I have found that most launch files for this application have values already for the 15x15 matrix. What should I use initially?

  5. I see that most code uses the imu and odom as differential... what does that mean and is it neccesary?

Thanks for the help!

Asked by lasersocks on 2017-04-12 06:46:24 UTC

Comments

I have done a little more work with this, and as far as I can tell, the fused data is often less accurate than just plain odometry. I am assuming I did something wrong.

Is this not the right place to ask this question? Can someone recommend somewhere to get help?

Asked by lasersocks on 2017-04-17 13:38:27 UTC

Apologies for not responding to this. Did you ever solve this problem?

Asked by Tom Moore on 2017-07-20 04:25:16 UTC

I'm also trying to get robot_localization implement and I have to say the lack of a simple full working example of how to implement it is making learning how to use this harder than it should be. Also, consider having standard docs on the ros wiki site. People are used to those docs. Thanks!

Asked by psammut on 2017-10-20 20:45:12 UTC

EDIT* I feel like a b-hole cause i found a bunch of examples on the git hub repo.

https://github.com/cra-ros-pkg/robot_localization/blob/kinetic-devel/params/ekf_template.yaml

Asked by psammut on 2017-10-20 21:09:08 UTC

Haha! No worries.

Asked by Tom Moore on 2017-10-24 04:03:29 UTC

Answers

For anyone searching to get started with robot_localization, here's some info.

Here's the main docs that you should read through: http://docs.ros.org/lunar/api/robot_localization/html/index.html

Watch this video: https://vimeo.com/142624091

And here is the github repo that contains all the source including some examples: https://github.com/cra-ros-pkg/robot_localization

The simplest example in this repo is called ekf_template, and it comprises two files:

Bing bam boom! It's actually not that hard to get it going, the hardest part is just putting it together cause there's no simple end to end getting started guide, so don't despair!

Asked by psammut on 2017-10-27 11:25:23 UTC

Comments