Ask Your Question
0

Trying to transmit a 1 by 4 array message to subscriber

asked 2019-09-24 12:10:17 -0600

haloted gravatar image

updated 2019-09-24 23:38:01 -0600

jayess gravatar image

I am having trouble trying to publish correctly a 1 by 4 array message generated using a for loop based on test data. My system is a ubuntu 16.04 running Kinetic.
The error occurred in the pub.publish(message) line. Below is my code:

# Import Packages
import sys

sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')

from raisim_gym.algo.ppo2 import PPO2
import os
import math
import argparse
import pickle

def action2Thrust(mylist):       
    _actionMean = 2.5
    _actionStd = 2

    Newthrust = mylist.astype(float)*_actionStd
    Newthrust += _actionMean
    return Newthrust


# Have to add the path again so that import rospy works. 
sys.path.append('/opt/ros/kinetic/lib/python2.7/dist-packages')

import rospy
from std_msgs.msg import String
from transmit_thrust.msg import ThrustAction


# Function to map the action value to true thrust range none negative to the range between 
# 0.5 to 4.5 scale

if __name__ == '__main__':
    try:
        # configuration
        parser = argparse.ArgumentParser()
        parser.add_argument('-w', '--weight', help='trained weight path', type=str, default='')
        args = parser.parse_args()

        weight_path = args.weight

        if weight_path == "":
            print("Can't find trained weight, please provide a trained weight with --weight switch\n")

        else:

            print("Loaded weight from {}\n".format(weight_path))
            model = PPO2.load(weight_path)

         # Needed to load observations here to test this script would be using pickle here
            with open('/home/ted/raisim_workspace/raisimGym/scripts/obArray.pickle', 'rb') as f:
                obs = pickle.load(f)
         # Needed to instantiate an array to save Thrust for outputting         
            ThrustArray = ThrustAction()
            pub = rospy.Publisher('chatter', ThrustAction, queue_size=10)
            rospy.init_node('talker', anonymous=True)
            rate = rospy.Rate(100) # 10hz

            for i in range(len(obs)):

                action, _ = model.predict(obs[i])
                # print("Action: {}".format(action))

                Thrust = action2Thrust(action)
                # print("Thrust: {}".format(Thrust))

                ThrustArray = Thrust

                while not rospy.is_shutdown():
                    rospy.loginfo(ThrustArray)
                    pub.publish(ThrustArray)
                    rate.sleep()

    except rospy.ROSInterruptException:
        pass

The obs obtain a set of test data in a large array in the form of 18 by 47093, which is 18 columns and 47093 rows. The arrays are fed into a for loop generating individual thrust command of 1 by 4 which are published to the subscriber node. I have tried to replace the line:

ThrustArray = Thrust

to

ThrustArray.action = Thrust

where action is the attribute of ThrustArray.msg which is defined as a float32[]. Below is the error output:

[INFO] [1569343371.533475]: [[0.5
3.76598799 0.6819396 0.91531122]] Traceback (most recent call last):
File "/home/ted/catkin_ws/devel/lib/python2.7/dist-packages/transmit_thrust/msg/_ThrustAction.py", line 55, in serialize buff.write(struct.pack(pattern, *self.action)) struct.error: required argument is not a float

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/topics.py", line 882, in publish self.impl.publish(data) File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/topics.py", line 1066, in publish serialize_message(b, self.seq, message) File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/msg.py", line 152, in serialize_message msg.serialize(b) File ...
(more)
edit retag flag offensive close merge delete

Comments

1

Ok, so what returns model.predict(obs[i])? It seems to me it is a numpy array, as you use astype(float) laster on with it, right? And what exactly is your message definition? Since you asked, if there is something wrong with defining your custom message

LeoE gravatar imageLeoE ( 2019-09-24 12:42:04 -0600 )edit

Hi LeoE,

Yes you are right, model.predict(obs[i]) returns a 1 by 4 numpy array in the form like [1 1 -1 -1], where the numbers are in between -1 to 1. It could have many decimal places that's why I assigned ThrustAction.msg as following:

float32[] action

where action is the attribute of ThrustAction as my custom message file. I did this following this question on stackflow Publishing Array

It seemed to me the resulting output ThrustAction had two square brackets but I only needed one to be a list. I am not sure why this is. Or it could be that I needed to assign float64[] instead, but I highly doubt it.

haloted gravatar imagehaloted ( 2019-09-24 18:28:38 -0600 )edit

I think it's highly likely that I needed to numpize my array before publishing since as LeoE pointed out that my arrays are numpy arrays not lists. So I will follow the tutorial here and see if it works: Numpize Array

haloted gravatar imagehaloted ( 2019-09-24 18:45:36 -0600 )edit

1 Answer

Sort by » oldest newest most voted
1

answered 2019-09-24 19:27:59 -0600

LeoE gravatar image

All you need to do is convert your numpy array to a python list and assign it to your message.action. This means replace the line ThrustArray = Thrust with (as you tried before) ThrustArray.action = list(Thrust). This should do the trick. This works since you know, that Thrust is a 1D array making the numpy-array to list conversion rather easy.

edit flag offensive delete link more

Comments

@LeoE Thanks for the reply, at least the list error is gone but I got the following error output:

 [INFO] [1569374940.181282]: action: 
  - [0.5        3.78099775 0.5        1.07836843]
Traceback (most recent call last):
  File "/home/ted/catkin_ws/devel/lib/python2.7/dist-packages/transmit_thrust/msg/_ThrustAction.py", line 55, in serialize
    buff.write(struct.pack(pattern, *self.action))
struct.error: required argument is not a float
haloted gravatar imagehaloted ( 2019-09-24 20:35:12 -0600 )edit

Traceback (most recent call last): File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/topics.py", line 882, in publish self.impl.publish(data) File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/topics.py", line 1066, in publish serialize_message(b, self.seq, message) File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/msg.py", line 152, in serialize_message msg.serialize(b) File "/home/ted/catkin_ws/devel/lib/python2.7/dist-packages/transmit_thrust/msg/_ThrustAction.py", line 56, in serialize except struct.error as se: self._check_types(struct.error("%s: '%s' when writing '%s'" % (type(se), str(se), str(locals().get('_x', self))))) File "/opt/ros/kinetic/lib/python2.7/dist-packages/genpy/message.py", line 336, in _check_types raise SerializationError(str(exc)) genpy.message.SerializationError: <class 'struct.error'="">: 'required argument is not a float' when writing 'action: - [0.5 3.78099775 0.5 1.07836843]'

haloted gravatar imagehaloted ( 2019-09-24 20:36:57 -0600 )edit

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/ted/catkin_ws/src/transmit_thrust/scripts/transmitThrust.py", line 108, in <module>
    pub.publish(ThrustArray)
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/topics.py", line 886, in publish
    raise ROSSerializationException(str(e))
rospy.exceptions.ROSSerializationException: <class 'struct.error'>: 'required argument is not a float' when writing 'action: 
  - [0.5        3.78099775 0.5        1.07836843]'
haloted gravatar imagehaloted ( 2019-09-24 20:37:21 -0600 )edit

This is my current code for the same error:

    while not rospy.is_shutdown():

        for i in range(len(obs)):

            action, _ = model.predict(obs[i])
            # print("Action: {}".format(action))

            Thrust = action2Thrust(action)
            # print("Thrust: {}".format(Thrust))

            ThrustArray.action = list(Thrust)

            rospy.loginfo(ThrustArray)
            pub.publish(ThrustArray)
            rate.sleep()
haloted gravatar imagehaloted ( 2019-09-24 21:20:30 -0600 )edit

Here are some of the output I have for data types:

Thrust is type: <class 'numpy.ndarray'>
ThrustArray is type: <class 'transmit_thrust.msg._ThrustAction.ThrustAction'>
ThrustArray.action is type: <class 'list'>
[INFO] [1569379841.331428]: [array([0.5       , 3.83800876, 0.71245861, 0.77146018])]
Thrust is type: <class 'numpy.ndarray'>
ThrustArray is type: <class 'transmit_thrust.msg._ThrustAction.ThrustAction'>
ThrustArray.action is type: <class 'list'>
[INFO] [1569379841.341008]: [array([0.5       , 3.90113711, 0.7153132 , 0.95803189])]
haloted gravatar imagehaloted ( 2019-09-24 21:52:11 -0600 )edit

@haloted Please don't use comments to post code/terminal output, please update your question instead. It's easier to keep track of the question that way

jayess gravatar imagejayess ( 2019-09-24 23:38:48 -0600 )edit
1

This is because your numpy array is actually a ndarray. In this case use numpys tolist() function: ThrustArray.action = Thrust.tolist()

LeoE gravatar imageLeoE ( 2019-09-25 05:13:59 -0600 )edit

@LeoE: Yes it now works with tolist(). Sorry that I am kind of new to python.

haloted gravatar imagehaloted ( 2019-09-25 05:34:11 -0600 )edit

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

2 followers

Stats

Asked: 2019-09-24 12:10:17 -0600

Seen: 37 times

Last updated: Sep 24 '19