ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

trajectory_msgs/JointTrajectory Exception :AttributeError: 'str' object has no attribute 'positions'

asked 2020-06-17 06:47:31 -0500

GUENNI gravatar image

updated 2020-06-20 10:42:48 -0500

I wrote a python script to publish a JointTrajectory message. It results in an Exception: AttributeError: 'str' object has no attribute 'positions'.

The python script:

#!/usr/bin/env python3

import rospy
import numpy
from trajectory_msgs.msg import JointTrajectory

rospy.init_node('topic_publisher')

pub= rospy.Publisher('Command',JointTrajectory,queue_size=2)
rate = rospy.Rate(2)

msg=JointTrajectory()
#msg.points=dict()
pos=[1.0,1.1,1.2,1.3]
velo=[0.0,0.0,0.0,0.0]
time=[2.0,0.0]
msg.joint_names=["hip","shoulder","elbow","wrist"]
msg.points=dict([('positions', pos), ('velocities', velo), ('time_from_start', time)])
#msg.points={'position':pos,'velocities':velo,'time_from_start':time}
print (msg)
while not rospy.is_shutdown():
    pub.publish(msg)
    rate.sleep()

I added a print to show the message.

Result:


header: 
  seq: 0
  stamp: 
    secs: 0
    nsecs:         0
  frame_id: ''
joint_names: 
  - hip
  - shoulder
  - elbow
  - wrist
points: {'positions': [1.0, 1.1, 1.2, 1.3], 'velocities': [0.0, 0.0, 0.0, 0.0], 'time_from_start': [2.0, 0.0]}
Traceback (most recent call last):
  File "/KubuntuDaten/myrobot_ws/src/myrobot/topic_publisher.py", line 23, in <module>
    pub.publish(msg)
  File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 882, in publish
    self.impl.publish(data)
  File "/opt/ros/noetic/lib/python3/dist-packages/rospy/topics.py", line 1066, in publish
    serialize_message(b, self.seq, message)
  File "/opt/ros/noetic/lib/python3/dist-packages/rospy/msg.py", line 152, in serialize_message
    msg.serialize(b)
  File "/opt/ros/noetic/lib/python3/dist-packages/trajectory_msgs/msg/_JointTrajectory.py", line 110, in serialize
    length = len(val1.positions)
AttributeError: 'str' object has no attribute 'positions'

Now I am a bit confused of which type the data element points should be. Is it a list, a dict or a string? I tried several variations of the message format, always with the same result.

ROS noetic runs on Ubuntu focal.

This is my testcoding:

import rospy import numpy from trajectory_msgs.msg import JointTrajectory from trajectory_msgs.msg import JointTrajectoryPoint

rospy.init_node('topic_publisher')

pub= rospy.Publisher('arm_controller/command',JointTrajectory,queue_size=2) rate = rospy.Rate(30)

r0=0.0 r1=0.5 r3=0.0 r4=0.0 t=20.0 msg=JointTrajectory() point=JointTrajectoryPoint() point.positions=[r0,r1,r3,r4] point.velocities=[0.0,0.0,0.0,0.0] point.time_from_start=rospy.Duration(t) msg.joint_names=["hip","shoulder","elbow","wrist"] msg.points.append(point) while not rospy.is_shutdown():

pub.publish(msg) if point.positions[0] >= 2numpy.pi : point.positions[0] = 0.0 point.positions[0]+=0.78542

rate.sleep()

edit retag flag offensive close merge delete

2 Answers

Sort by ยป oldest newest most voted
0

answered 2020-06-23 02:07:04 -0500

GUENNI gravatar image

Now I got my robot arm to work. I switched from the python interface to c++. The central aspect for my problem with the jointTrajectory structure was, that I had to resize the arrays for joint_names, points, positions etc. to the desired number of elements.

Here my example code:


#include "ros/ros.h"
#include "std_msgs/String.h"
#include "trajectory_msgs/JointTrajectory.h"
#include "trajectory_msgs/JointTrajectoryPoint.h"

#define PI 3.141592653589793

int main(int argc, char **argv)
{
  ros::init(argc, argv, "topic_publisher");

  ros::NodeHandle n;

  ros::Publisher chatter_pub = n.advertise<trajectory_msgs::jointtrajectory>("arm_controller/command", 10);

  ros::Rate loop_rate(0.5);

 trajectory_msgs::JointTrajectory msg;
        msg.joint_names.resize(4);
        msg.joint_names[0] = "hip";
        msg.joint_names[1] = "shoulder";
        msg.joint_names[2] = "elbow";
        msg.joint_names[3] = "wrist";
        msg.points.resize(1);
        msg.points[0].positions.resize(4);
        msg.points[0].positions[0] = 1.5;
        msg.points[0].positions[1] = 0.5;
        msg.points[0].positions[2] = 0.6;
        msg.points[0].positions[3] = 0.6;

        msg.points[0].velocities.resize(4);
        msg.points[0].velocities[0] = 0.0;
        msg.points[0].velocities[1] = 0.0;
        msg.points[0].velocities[2] = 0.0;
        msg.points[0].velocities[3] = 0.0;

        msg.points[0].time_from_start=ros::Duration(2);
  while (ros::ok())
  {
          if (msg.points[0].positions[0] >= 2*PI)
                  msg.points[0].positions[0] = 0.0;
          else
                msg.points[0].positions[0] += 0.7;
//      ROS_INFO("%f:%f", msg.points[0].positions[0],msg.points[0].positions[0]);
    chatter_pub.publish(msg);

    ros::spinOnce();

    loop_rate.sleep();
  }


  return 0;
}
edit flag offensive delete link more

Comments

1

Great! seems a very clear code! The line:

ros::Publisher chatter_pub = n.advertise<trajectory_msgs::jointtrajectory>("arm_controller/command", 10);

i think the message type sould be changed to trajectory_msgs::JointTrajectory (if not, i do not know how that's gonna work, but you know, is something minimal!

Personally i prefer to use C++ and this resize. It could seem annoying but actually you are controlling better the code! :)

Solrac3589 gravatar image Solrac3589  ( 2020-06-25 01:25:27 -0500 )edit

Thank you for your good ideas. The misspelled jointtrajectory must be an error on copying the source code. I agree with you concerning coding in C++. It makes it also more clear to me.

GUENNI gravatar image GUENNI  ( 2020-06-26 13:38:32 -0500 )edit
1

answered 2020-06-17 07:32:30 -0500

Solrac3589 gravatar image

updated 2020-06-17 07:34:35 -0500

I don' t usually use rospy, but i think you should declare first a JointTrajectoryPoint and then add this as vector element inside JointTrajectory element

maybe something like:

point=JointTrajectoryPoint()
point.positions = [1.0,1.1,1.2,1.3]
point.velocities = [0.0,0.0,0.0,0.0]
point.time_from_start = [2.0,0.0]

then:

msg.points.append(point)

Hope this helps. I'm not sure if the error is around here or if this is correct, but at least, while nobody answers...

remember to add this import at beggining:

from trajectory_msgs.msg import JointTrajectoryPoint
edit flag offensive delete link more

Comments

btw maybe you should check to use numpy also, haha http://wiki.ros.org/rospy_tutorials/T...

Solrac3589 gravatar image Solrac3589  ( 2020-06-17 07:46:05 -0500 )edit

This was a good idea. In addition I had to change the entry for time_from_start to point.time_from_start=rospy.Duration(2). Thank you.

GUENNI gravatar image GUENNI  ( 2020-06-17 08:40:33 -0500 )edit

The solutution from Solrac3589 worked.

GUENNI gravatar image GUENNI  ( 2020-06-17 09:16:37 -0500 )edit

Was something i also wanted to comment (the duration).

In order to not have this mistake again, check the message documentation (for example http://docs.ros.org/melodic/api/traje...) here you can se clearly the structure

Solrac3589 gravatar image Solrac3589  ( 2020-06-18 00:35:11 -0500 )edit

Another thing, what I do not understand is, I can make a message structure and publish it. But when I try to modify values in the structure, adding a value to x-position or to time_from_start for example, this is not possible.

GUENNI gravatar image GUENNI  ( 2020-06-20 06:35:08 -0500 )edit

I am not properly understanding what you want. Do you want to change the value of an already sended message? i think its kinda strange. If you want to send another message for the same channel,, it's not okay to change msg and then publish again?

Solrac3589 gravatar image Solrac3589  ( 2020-06-20 06:49:40 -0500 )edit

My understanding is, that the message structure is a datastructure in my program and I am giving a pointer to the message publisher. Then it must be possible to change a value to create a new message, for example in a loop. Anotheri Idea is to construct a message with several waypoints and read the value from the previous index and add something to it for the next index. I can use the append method to add the point structure to the message, so it must be possible to modify values in the point structure and add it repeatedly to the message. Then publish one message with several waypoints.

GUENNI gravatar image GUENNI  ( 2020-06-20 07:09:53 -0500 )edit

If I am not wrong it's true that the publisher is a pointer, but is a pointer of a copy of the message (that's one of the biggest differences between nodes and Nodelets) so, when you publish a message, I think there is no way to change the value sended.

Checking what you want, yes, i think the better approach is to send a trajectory with several points, but the hard part will be to define the acceleration and velocity of each internal point. However, it also exist the possibility to send several trajectories with one point and they will be executed as a pipeline (i use that in a project!) the bad part of that is you are gonna see that for each point it will be a acceleration an deceleration. Hope i am understanding well the issue and I cleared a little your mind! if not ...(more)

Solrac3589 gravatar image Solrac3589  ( 2020-06-20 07:26:33 -0500 )edit

Question Tools

1 follower

Stats

Asked: 2020-06-17 06:47:31 -0500

Seen: 1,609 times

Last updated: Jun 23 '20