0
$\begingroup$

Rosanswers logo

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_controller

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, in __init__
    self.max_rpm_acceleration = rospy.get_param('/vesc/max_rpm_acceleration')
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/client.py", line 465, in get_param
    return _param_server[param_name] #MasterProxy does all the magic for us
  File "/opt/ros/kinetic/lib/python2.7/dist-packages/rospy/msproxy.py", line 123, in __getitem__
    raise KeyError(key)
KeyError: '/vesc/max_rpm_acceleration'

Originally posted by renanmb on ROS Answers with karma: 33 on 2018-10-10

Post score: 0


Original comments

Comment by aPonza on 2018-10-10:
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?

Comment by renanmb on 2018-10-10:
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.

$\endgroup$

1 Answer 1

0
$\begingroup$

Rosanswers logo

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()

Originally posted by aPonza with karma: 589 on 2018-10-10

This answer was ACCEPTED on the original site

Post score: 0


Original comments

Comment by renanmb on 2018-10-10:
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.

Comment by renanmb on 2018-10-10:
I found this: http://docs.ros.org/indigo/api/rospy/html/rospy.client-pysrc.html#get_param

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

Comment by aPonza on 2018-10-11:
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

Comment by renanmb on 2018-10-11:
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/52764066/ros-kinetic-error-launching-parameters-cannot-marshal-none-unless-allow-none-is

Comment by aPonza on 2018-10-12:
I answered on stackexchange and edited this answer to provide an example that fits exactly your code.

Comment by gvdhoorn on 2018-10-12:\

I created this following question on stackoverflow as well

why?

Comment by renanmb on 2018-10-12:
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.

Comment by gvdhoorn on 2018-10-12:
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.

Comment by aPonza on 2018-10-12:
Agreed on the launch file, I arbitrarily assumed OP wanted to stay within the python code.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.