python-3.xrospublish-subscriberospyrosbag

ValueError: data_class [Twist] is not a class


I am trying to get values from .yaml file for subscription and writing bag file in ROS. But i encounter with this error and i couldn't solve it. I guess I can't define my values as a class name in code.

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import rospy 
import rosbag
from geometry_msgs.msg import Twist

filename='test.bag'
bag = rosbag.Bag(filename, 'w')


sensor_info=rospy.get_param("/bag/sensor_info") 
move_datatype=sensor_info[1]['datatype'] # Twist
move_topic=sensor_info[1]['topic_name'] # /cmd_vel

def move_callback(msg):
    x=msg

def main():
    global x
    rospy.init_node('rosbag_save', anonymous=True)
    rospy.Subscriber(move_topic,move_datatype(),move_callback)
    while not rospy.is_shutdown():
        bag.write(f'{move_topic}',x)

if __name__ == '__main__':
    try:
        main()
    except rospy.ROSInterruptException:
        pass

here is my code

bag:
  sensor_info:
    - {"topic_name": "/multi_scan", "datatype": "LaserScan"}
    - {"topic_name": "/cmd_vel", "datatype": "Twist"}

and here is my .yaml file


Solution

  • You're getting this error because when you read the rosparam in from the server it will be stored as a string; which you can't pass to a subscriber. Instead you should convert it to the object type after reading it in. There are a couple of ways to do this, but using globals() will probably be the easiest. Essentially this returns a dictionary of everything in the global symbol table and from there you can use a key(a string) to get a value(class type). This can be done such as:

    sensor_info = rospy.get_param("/bag/sensor_info") 
    move_datatype_string = sensor_info[1]['datatype'] # Twist
    move_topic = sensor_info[1]['topic_name'] # /cmd_vel
    
    move_datatype = globals()[move_datatype_string]