Ask Your Question
0

Rospy Parameter KeyError

asked 2018-10-10 10:17:44 -0500

renanmb gravatar image

updated 2018-10-10 11:43:33 -0500

jayess gravatar image

I cannot get my code to get the parameters on my config file. I just do like it is on the tutorials but it does not work and I do not understand why. I believe it might be a namespace problem with rospy. I have never had this problem with C++.

My Github with the whole code: https://github.com/renanmb/boat_pid_c...

throttle_interpolator.py

#!/usr/bin/env python
import rospy

from std_msgs.msg import Float64
from boat_controller.msg import Drive

# import some utils.
import numpy as np
import copy as copy

class InterpolateThrottle:
    def __init__(self):
        self.rpm_input_topic   = rospy.get_param('~rpm_input_topic', '/vesc/commands/motor/unsmoothed_speed')
        self.rpm_output_left_topic  = rospy.get_param('~rpm_output_left_topic', '/vesc/commands/motor/speed_left')
        self.rpm_output_right_topic  = rospy.get_param('~rpm_output_right_topic', '/vesc/commands/motor/speed_right')

        self.servo_input_topic   = rospy.get_param('~servo_input_topic', '/vesc/commands/servo/unsmoothed_position')
        self.servo_output_topic  = rospy.get_param('~servo_output_topic', '/vesc/commands/servo/position')

        self.max_rpm_acceleration = rospy.get_param('/vesc/max_rpm_acceleration')
        self.max_rpm = rospy.get_param('/vesc/vesc_driver/speed_max')
        self.min_rpm = rospy.get_param('/vesc/vesc_driver/speed_min')
        self.throttle_smoother_rate = rospy.get_param('/vesc/throttle_smoother_rate')
        self.rpm_to_erpm_gain = rospy.get_param('/vesc/rpm_to_erpm_gain')

        self.max_servo_speed = rospy.get_param('/vesc/max_servo_speed')
        self.steering_angle_to_servo_gain = rospy.get_param('/vesc/steering_angle_to_servo_gain')
        self.servo_smoother_rate = rospy.get_param('/vesc/servo_smoother_rate')
        self.max_servo = rospy.get_param('/vesc/vesc_driver/servo_max')
        self.min_servo = rospy.get_param('/vesc/vesc_driver/servo_min')

        self.last_rpm = 0
        self.desired_rpm = self.last_rpm

        self.last_servo = rospy.get_param('/vesc/steering_angle_to_servo_offset')
        self.desired_servo_position = self.last_servo

        self.rpm_output_left = rospy.Publisher(self.rpm_output_left_topic, Float64,queue_size=1)
        self.rpm_output_right = rospy.Publisher(self.rpm_output_right_topic, Float64,queue_size=1)
        self.servo_output = rospy.Publisher(self.servo_output_topic, Float64,queue_size=1)

        rospy.Subscriber(self.rpm_input_topic, Drive, self._process_throttle_command)
        rospy.Subscriber(self.servo_input_topic, Float64, self._process_servo_command)

        self.max_delta_servo = abs(self.steering_angle_to_servo_gain * self.max_servo_speed / self.servo_smoother_rate)
        rospy.Timer(rospy.Duration(1.0/self.servo_smoother_rate), self._publish_servo_command)

        self.max_delta_rpm = abs(self.rpm_to_erpm_gain * self.max_rpm_acceleration / self.throttle_smoother_rate) 

        rospy.Timer(rospy.Duration(1.0/self.max_delta_rpm), self._publish_throttle_left_command)
        rospy.Timer(rospy.Duration(1.0/self.max_delta_rpm), self._publish_throttle_right_command)

        self._run()

    def _run(self):
        rospy.spin()

    def _publish_throttle_left_command(self, evt):
        desired_delta = self.desired_rpm_left-self.last_rpm_left
        clipped_delta = max(min(desired_delta, self.max_delta_rpm), -self.max_delta_rpm)
        smoothed_rpm = self.last_rpm_left + clipped_delta
        self.last_rpm_left = smoothed_rpm
        self.rpm_output_left.publish(Float64(smoothed_rpm))

    def _publish_throttle_right_command(self, evt):
        desired_delta = self.desired_rpm_right-self.last_rpm_right
        clipped_delta = max(min(desired_delta, self.max_delta_rpm), -self.max_delta_rpm)
        smoothed_rpm = self.last_rpm_right + clipped_delta
        self.last_rpm_right = smoothed_rpm
        self.rpm_output_right.publish(Float64(smoothed_rpm))

    def _process_throttle_command(self,msg):
        input_rpm_left = msg.data
        input_rpm_right = msg.data
        input_rpm_left = min(max(input_rpm_left, self.min_rpm), self.max_rpm)
        input_rpm_right = min(max(input_rpm_right, self.min_rpm), self.max_rpm)
        self.desired_rpm_left = input_rpm_left
        self.desired_rpm_right = input_rpm_right

    def _publish_servo_command(self, evt):
        desired_delta = self.desired_servo_position-self.last_servo
        clipped_delta = max(min(desired_delta, self.max_delta_servo), -self.max_delta_servo)
        smoothed_servo = self.last_servo + clipped_delta
        self.last_servo = smoothed_servo         
        self.servo_output.publish(Float64(smoothed_servo))

    def _process_servo_command(self,msg):
        input_servo = msg.data
        input_servo = min(max(input_servo, self.min_servo), self.max_servo)
        self.desired_servo_position = input_servo


if __name__ == '__main__':
    try:
        rospy.init_node('Throttle_Interpolator')
            p = InterpolateThrottle()
        rospy.spin()
    except rospy.ROSInterruptException:
        pass

Error message:

Traceback (most recent call last):
  File "/home/renan/rostest_ws/src/boat_controller/src/throttle_interpolator.py", line 136, in <module>
    p = InterpolateThrottle()
  File "/home/renan/rostest_ws/src/boat_controller/src/throttle_interpolator.py", line 28 ...
(more)
edit retag flag offensive close merge delete

Comments

Is anybody actually loading the parameters from the yaml in the parameter server? Do you have other nodes not in the repo setting them?

If not, you could read them in?

aPonza gravatar image aPonza  ( 2018-10-10 10:46:49 -0500 )edit

My other nodes loads its parameters just fine. I tried the command rosparam load and it does not work. It says the file does not exist.

renanmb gravatar image renanmb  ( 2018-10-10 10:57:59 -0500 )edit

1 Answer

Sort by ยป oldest newest most voted
0

answered 2018-10-10 11:11:35 -0500

aPonza gravatar image

updated 2018-10-12 02:42:41 -0500

Looking at the repo and your own comment it seems you might not be loading the parameters in this node / not running both nodes at the same time?

Given the file a_location.yaml containing:

foo:
  bar: [0.194717, -0.592676, 0.042564]

The python code to set a generic parameter in rospy should be:

#! /usr/bin/env python

import yaml
import rospy
import rospkg


def load_parameters():
    rospack = rospkg.RosPack()
    path_loc = rospack.get_path("a_pkg") + "/config/a_location.yaml"
    with open(path_loc, 'r') as doc:
        loc = yaml.load(doc)

    x_foo_bar = loc["foo"]["bar"][0]
    y_foo_bar = loc["foo"]["bar"][1]
    z_foo_bar = loc["foo"]["bar"][2]

    rospy.set_param("location", {'x': x_foo_bar, 'y': y_foo_bar, 'z': z_foo_bar})

    # do something


if __name__ == '__main__':
    rospy.init_node('my_node', anonymous=True)
    load_parameters()

EDIT: let's redo the example for vesc.yaml

vesc:
  max_rpm_acceleration: 0.123
#! /usr/bin/env python

import yaml
import rospy
import rospkg


def load_parameters():
    rospack = rospkg.RosPack()
    path_loc = rospack.get_path("boat_pid_controller") + "/config/vesc.yaml"
    with open(path_loc, 'r') as doc:
        parameters_vesc = yaml.load(doc)

    max_rpm_accel = parameters_vesc["vesc"]["max_rpm_acceleration"]

    rospy.set_param("max_rpm_acceleration", max_rpm_accel)


if __name__ == '__main__':
    rospy.init_node('my_node', anonymous=True)
    load_parameters()

    # now that the parameters are loaded you can use them
    p = InterpolateThrottle()
    rospy.spin()
edit flag offensive delete link more

Comments

please, I would appreciate if you could provide the source of this information, so I can study it more. To be honest I did not understand anything.

renanmb gravatar image renanmb  ( 2018-10-10 11:16:52 -0500 )edit

I found this: http://docs.ros.org/indigo/api/rospy/...

But it is pretty much what I was trying to do.

renanmb gravatar image renanmb  ( 2018-10-10 13:22:53 -0500 )edit

I don't understand if I answered your question. You're using kinetic, so use those docs. My source is ROS projects on github, e.g. github dot com /Salman-H/pick-place-robot/kuka_arm/scripts/target_spawn.py

aPonza gravatar image aPonza  ( 2018-10-11 02:06:33 -0500 )edit

You did not answer my question, because it still does not work.

I tried to use roslaunch to set all parameter and I created this following question on stackoverflow as well: https://stackoverflow.com/questions/5...

renanmb gravatar image renanmb  ( 2018-10-11 10:54:25 -0500 )edit

I answered on stackexchange and edited this answer to provide an example that fits exactly your code.

aPonza gravatar image aPonza  ( 2018-10-12 02:42:01 -0500 )edit

I created this following question on stackoverflow as well

why?

gvdhoorn gravatar image gvdhoorn  ( 2018-10-12 04:47:02 -0500 )edit

It was about the launch file, this forum was giving a server error to post another question. I also tried to use the roslaunch to avoid the KeyError. Thanks for the answer. They do not cite it anywhere on the wiki. So in python I basically have to make that for every parameter.

renanmb gravatar image renanmb  ( 2018-10-12 05:47:14 -0500 )edit
1

What @aPonza shows is one particular way to load parameters using the Python API.

But I would just use a launch file if I were you. That is much more common, better understood and more scalable.

gvdhoorn gravatar image gvdhoorn  ( 2018-10-12 05:50:20 -0500 )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

1 follower

Stats

Asked: 2018-10-10 10:17:44 -0500

Seen: 1,018 times

Last updated: Oct 12 '18