robot localization package does not fuse imu data
Hi ! I'm using ros2 galactic to build a differential drive robot. I'm trying to fuse the encoder wheels odometry with the bno055 imu data I'm publishing the odom msg and the odom to base_link tf in the odom node , and publishing the imu msg and base_link to imu_link tf using urdf file .
everything looks fine up to this point So , now i'm trying to fuse the odom data with the imu data using robot localization package this is my ekf config file
ekf config file
ekf_filter_node: ros__parameters:
frequency: 30.0
two_d_mode: true
publish_acceleration: true
publish_tf: false
#map_frame: map # Defaults to "map" if unspecified
odom_frame: odom # Defaults to "odom" if unspecified
base_link_frame: base_link # Defaults to "base_link" ifunspecified
world_frame: odom # Defaults to the value ofodom_frame if unspecified
odom0: /odometry
odom0_config: [false, false, false,
false, false, true,
true, true, false,
false, false, true,
false, false, false]
imu0: bno055/imu
imu0_config: [false, false, false,
false, false, true,
false, false, false,
false, false, true,
true, false, false]
the ekf_filter_node subscribe to both topics and also everything looks fine , however when I hold the robot and rotate the wheels using keyboard teleport the robot in rviz moves even though the physical robot stand still. it looks like there is no imu at all . note : I checked the Imu data in rviz in looks fine as well. any help will be great. this is my odom code
def __init__(self):
super().__init__('odometry_node') #node name
self.nodename = "odometry_node"
self.get_logger().info(f"-I- {self.nodename} started")
#### parameters #######
self.rate_hz = self.declare_parameter("rate_hz", 10.0).value # the rate at which to publish the transform
self.create_timer(1.0/self.rate_hz, self.update)
self.base_width = float(self.declare_parameter('base_width', 0.185).value) # The wheel base width in meters
self.gear_ratio = float(self.declare_parameter('gear_ratio', 20).value) # The gearbox ratio
self.wheel_radius = float(self.declare_parameter('wheel_radius', 0.05).value) # The wheel radius in meter
self.base_frame_id = self.declare_parameter('base_frame_id',
'base_link').value # the name of the base frame of the robot
self.odom_frame_id = self.declare_parameter('odom_frame_id',
'odom').value # the name of the odometry reference frame
#internal data
self.angle_left = 0.0
self.angle_right = 0.0
self.omega_left = 0.0
self.omega_right = 0.0
self.x = 0.0
self.y = 0.0
self.th = 0.0
self.dx = 0.0
self.dr = 0.0
self.then = self.get_clock().now()
#subscriptions
self.create_subscription(Float32, "left_angle", self.lwheel_callback, 10)
self.create_subscription(Float32, "right_angle", self.rwheel_callback, 10)
self.create_subscription(Float32, "left_omega", self.lomega_callback, 10)
self.create_subscription(Float32, "right_omega", self.romega_callback, 10)
self.odom_pub = self.create_publisher(Odometry, "odom", 10)
self.odom_broadcaster = TransformBroadcaster(self)
def update(self):
now = self.get_clock().now()
elapsed = now - self.then
self.then = now
elapsed = elapsed.nanoseconds / NS_TO_SEC
#calculate odometry
#forward kinematics
self.dr = (self.wheel_radius/( 2* self.base_width))*(self.omega_right - self.omega_left)
self.dx = 0.5 * self.wheel_radius * (self.omega_right + self.omega_left)
#Compute odometry in typical way given the velocities of the robot
delta_x = (self.dx * cos(self.th)) * elapsed
delta_y = (self.dx * sin(self.th)) * elapsed
delta_th ...