Robotics StackExchange | Archived questions

How to print variables on ROS using python?

I am fairly new to ROS and I am working on a program that controls a robot arm. I am getting several errors related to various variables used in my nodes. I have been trying to find a way to print these variables like you do in python so that I can debug them, but I haven’t found a way to do so. I tried setting up a topic with the variables as the messages and a subscriber. I tried using rospy.loginfo and the console. I tried using plain print(). But none of these worked. I searched the ROS wiki tutorials but didn’t find anything. The code in question is supposed to control a robotic arm. Although the launch file runs a couple of other programs, I specifically want to print from one program called command_arm.py. The code for this program is:

(edit:) I created a node called printer which should print a simple string and then added it to the code. It still does not work. I ran a program with this same coding outside of ROS on my regular raspberry pi and it did work.

      #!/usr/bin/env python
    import rospy
    import traceback 
    import numpy as np
    # IMPORT the messages: 
    from sensor_msgs.msg import JointState
    from Adafruit_PWM_Servo_Driver import PWM
    #from std_msgs.msg import Float
    from std_msgs.msg import String

    #pins order is [base0 yaw, shoulder1 pitch, elbow2 pitch (relative to base), forearm3 roll, wrist4 pitch, finger5 roll]


    # PWM Controller set-up
    servo_pulse_frequency = 50
    servo_pulse_duration_us = 1.0e6/servo_pulse_frequency   # microseconds for each pulse
    servo_pulse_width_to_count_multiplier = 1./servo_pulse_duration_us*4095.0   # Counter is 12-bit, so 4096 levels (0-4095)

    # Initialise the PWM device using the default address
    pwm = PWM(0x40)   # Note if you'd like more debug output you can instead run:  pwm = PWM(0x40, debug=True)
    # Set the Frequency of all servo outputs
    pwm.setPWMFreq(servo_pulse_frequency)

    # Load parameters from rosparam to keep handy for the functions below: 
    # Matched lists of angles and microsecond commands
    map_angles_01 = np.radians(np.array(rospy.get_param('/rotational_angles_for_mapping_joint_01')))
    map_cmd_us_01 = np.array(rospy.get_param('/servo_cmd_us_for_mapping_joint_01'))
    map_angles_12 = np.radians(np.array(rospy.get_param('/rotational_angles_for_mapping_joint_12')))
    map_cmd_us_12 = np.array(rospy.get_param('/servo_cmd_us_for_mapping_joint_12'))
    map_angles_23 = np.radians(np.array(rospy.get_param('/rotational_angles_for_mapping_joint_23')))
    map_cmd_us_23 = np.array(rospy.get_param('/servo_cmd_us_for_mapping_joint_23'))
    map_angles_34 = np.radians(np.array(rospy.get_param('/rotational_angles_for_mapping_joint_34')))
    map_cmd_us_34 = np.array(rospy.get_param('/servo_cmd_us_for_mapping_joint_34'))
    map_angles_45 = np.radians(np.array(rospy.get_param('/rotational_angles_for_mapping_joint_45')))
    map_cmd_us_45 = np.array(rospy.get_param('/servo_cmd_us_for_mapping_joint_45'))
    map_angles_56 = np.radians(np.array(rospy.get_param('/rotational_angles_for_mapping_joint_56')))
    map_cmd_us_56 = np.array(rospy.get_param('/servo_cmd_us_for_mapping_joint_56'))


    # =============================================================================
    #   # No Publishers Needed 
    # =============================================================================

    def main(): 
        # =============================================================================
        #     # Launch a node called "command_arm"
        # =============================================================================
        rospy.init_node('command_arm', anonymous=False)
        rospy.init_node('printer', anonymous=False)
        # Set up subscriber that listens to "joint_states"
        sub_joint_states = rospy.Subscriber('/joint_states', JointState, command_arm)

        rospy.spin()

   def printer():
        print("something printed!!!!!!") 

    def command_arm(msg_in): 
        # unpack joint angle settings
        alpha0 = msg_in.position[0]
        beta1 = msg_in.position[1]
        beta2 = msg_in.position[2]
        beta2WORLD = beta1 + beta2
        gamma3 = msg_in.position[3]
        beta4 = msg_in.position[4]
        gamma5 = msg_in.position[5]    

        # Interpolate to find servo commands and send them
        cmd0 = interp_servo(map_angles_01, map_cmd_us_01, alpha0)
        command_servo(0,np.int(cmd0))

        cmd1 = interp_servo(map_angles_12, map_cmd_us_12, beta1)
        #rospy.loginfo("this is it:", cmd1)

        command_servo(1,np.int(cmd1))    

        cmd2 = interp_servo(map_angles_23, map_cmd_us_23, beta2WORLD)
        command_servo(2,np.int(cmd2))    

        cmd3 = interp_servo(map_angles_34, map_cmd_us_34, gamma3)
        command_servo(3,np.int(cmd3))    

        cmd4 = interp_servo(map_angles_45, map_cmd_us_45, beta4)
        command_servo(4,np.int(cmd4))    

        cmd5 = interp_servo(map_angles_56, map_cmd_us_56, gamma5)
        command_servo(5,np.int(cmd5))    


    # Function to interpolate using calibrated angle-to-servo-command mappings
    def interp_servo(angle_range,us_range,angle):
        # just use the same function arguments to call an Interpolation function np.interp
        return np.interp(angle,angle_range,us_range)


    # Function to command any servo with a given pulse width in microseconds
    def command_servo(servo_number, pulse_width_us):
        pulse_width_count = int(round(pulse_width_us*servo_pulse_width_to_count_multiplier))
        pwm.setPWM(servo_number, 0, pulse_width_count)


    # Function to shut down all the servos by sending them zero pulse width (same as no command)
    def shutdown_servos():
        for ii in range(16):
            command_servo(ii, 0)


    if __name__ == '__main__':
        try: 
            main()
        except: 
            traceback.print_exc()
            shutdown_servos()
            pass

When the launch file runs, the output is:

pi@Expt2019_A:~ $ roslaunch /home/pi/catkin_ws/me439robotarm/src/robot_operate.launch
... logging to /home/pi/.ros/log/9ac03a82-b3a3-11e9-b8de-b827eb90a835/roslaunch-Expt2019_A-1328.log
Checking log directory for disk usage. This may take awhile.
Press Ctrl-C to interrupt
Done checking log file disk usage. Usage is <1GB.

xacro: Traditional processing is deprecated. Switch to --inorder processing!
To check for compatibility of your document, use option --check-order.
For more infos, see http://wiki.ros.org/xacro#Processing_Order
xacro.py is deprecated; please use xacro instead
started roslaunch server http://Expt2019_A:43895/

SUMMARY
========

PARAMETERS
 * /command_frequency: 50
 * /endpoint_offset_in_frame_6: [0.037, 0.0, -0.035]
 * /endpoint_speed: 0.05
 * /frame_offset_01: [0.0, 0.0, 0.1026]
 * /frame_offset_12: [0.031, 0.0, 0.0]
 * /frame_offset_23: [0.118, 0.0, 0.0]
 * /frame_offset_34: [0.1335, 0.0, 0.02]
 * /frame_offset_45: [0.0, 0.0, 0.0]
 * /frame_offset_56: [0.0, 0.0, 0.0]
 * /path_svg_file: /home/pi/catkin_w...
 * /robot_description: <?xml version="1....
 * /rosdistro: kinetic
 * /rosversion: 1.12.14
 * /rotational_angles_for_mapping_joint_01: [-114.0, 0.0, 60]
 * /rotational_angles_for_mapping_joint_12: [-169.0, -90.0, -...
 * /rotational_angles_for_mapping_joint_23: [-11.0, 0.0, 129.0]
 * /rotational_angles_for_mapping_joint_34: [-112.0, 0.0, 82.0]
 * /rotational_angles_for_mapping_joint_45: [-85.0, 0.0, 90.0]
 * /rotational_angles_for_mapping_joint_56: [-116.0, 0.0, 72.0]
 * /rotational_limits_joint_01: [-90, 90]
 * /rotational_limits_joint_12: [-160, -24]
 * /rotational_limits_joint_23: [0, 136]
 * /rotational_limits_joint_34: [-84, 110]
 * /rotational_limits_joint_45: [-85, 85]
 * /rotational_limits_joint_56: [-87, 96]
 * /servo_cmd_us_for_mapping_joint_01: [600, 1616, 2281]
 * /servo_cmd_us_for_mapping_joint_12: [2483, 1657, 1020]
 * /servo_cmd_us_for_mapping_joint_23: [649, 744, 1656]
 * /servo_cmd_us_for_mapping_joint_34: [601, 1620, 2500]
 * /servo_cmd_us_for_mapping_joint_45: [2500, 1620, 715]
 * /servo_cmd_us_for_mapping_joint_56: [540, 1622, 2380]
 * /use_gui: True
 * /vertical_offset: 0.02
 * /y_rotation_sign: 1

NODES
  /robot_simulate/
    forward_kinematics (me439robotarm/forward_kinematics.py)
    robot_arm_animator (me439robotarm/robot_arm_animator.py)
  /
    robot_state_publisher (robot_state_publisher/state_publisher)
    rviz (rviz/rviz)
  /robot_control/
    command_arm (me439robotarm/command_arm.py)
    inverse_kinematics (me439robotarm/inverse_kinematics.py)
    printer (me439robotarm/printer.py)
    set_waypoints_from_svg (me439robotarm/set_waypoints_from_svg.py)
    smooth_waypoint_seeker (me439robotarm/smooth_waypoint_seeker.py)

ROS_MASTER_URI=http://localhost:11311

process[robot_state_publisher-1]: started with pid [1348]
process[rviz-2]: started with pid [1349]
process[robot_simulate/forward_kinematics-3]: started with pid [1350]
process[robot_simulate/robot_arm_animator-4]: started with pid [1351]
process[robot_control/inverse_kinematics-5]: started with pid [1352]
process[robot_control/smooth_waypoint_seeker-6]: started with pid [1353]
process[robot_control/set_waypoints_from_svg-7]: started with pid [1354]
process[robot_control/command_arm-8]: started with pid [1364]
ERROR: cannot launch node of type [me439robotarm/printer.py]: can't locate node [printer.py] in package [me439robotarm]
libEGL warning: DRI2: failed to authenticate
qt5ct: using qt5ct plugin
/home/pi/catkin_ws/src/me439robotarm/src/inverse_kinematics.py:109: RuntimeWarning: invalid value encountered in arccos
  phi = np.arccos( (L2**2 - L1**2 - H**2)/(-2*L1*H) )  # arccos will always return a positive value.
/home/pi/catkin_ws/src/me439robotarm/src/smooth_waypoint_seeker.py:73: RuntimeWarning: invalid value encountered in divide
  drhat = dr/drlength
libpng warning: iCCP: known incorrect sRGB profile
libpng warning: iCCP: known incorrect sRGB profile
inotify_add_watch("/home/pi/.config/qt5ct") failed: "No such file or directory"
qt5ct: D-Bus global menu: no
libpng warning: iCCP: known incorrect sRGB profile
Traceback (most recent call last):
  File "/home/pi/catkin_ws/src/me439robotarm/src/set_waypoints_from_svg.py", line 75, in talker
    msg_waypoint.xyz = waypoints[waypoint_number]
IndexError: index 43 is out of bounds for axis 0 with size 43
[robot_control/set_waypoints_from_svg-7] process has finished cleanly
log file: /home/pi/.ros/log/9ac03a82-b3a3-11e9-b8de-b827eb90a835/robot_control-set_waypoints_from_svg-7*.log
================================================================================REQUIRED process [rviz-2] has died!
process has finished cleanly
log file: /home/pi/.ros/log/9ac03a82-b3a3-11e9-b8de-b827eb90a835/rviz-2*.log
Initiating shutdown!
================================================================================
[robot_control/command_arm-8] killing on exit
[robot_control/smooth_waypoint_seeker-6] killing on exit
[robot_control/inverse_kinematics-5] killing on exit
[robot_simulate/robot_arm_animator-4] killing on exit
[robot_simulate/forward_kinematics-3] killing on exit
[rviz-2] killing on exit
[robot_state_publisher-1] killing on exit
Traceback (most recent call last):
  File "/home/pi/catkin_ws/src/me439robotarm/src/robot_arm_animator.py", line 82, in <module>
    listener()
  File "/home/pi/catkin_ws/src/me439robotarm/src/robot_arm_animator.py", line 31, in listener
    animate_robot_arm()
  File "/home/pi/catkin_ws/src/me439robotarm/src/robot_arm_animator.py", line 59, in animate_robot_arm
    plt.show()
  File "/usr/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 253, in show
    return _show(*args, **kw)
  File "/usr/lib/python2.7/dist-packages/matplotlib/backend_bases.py", line 163, in __call__
    manager.show()
  File "/usr/lib/python2.7/dist-packages/matplotlib/backends/backend_tkagg.py", line 610, in show
    self.canvas.manager.window.attributes('-topmost', 1)
AttributeError: 'NoneType' object has no attribute 'attributes'
shutting down processing monitor...
... shutting down processing monitor complete
done

Any suggestions on strategies I could try or perhaps tutorials that could help?

Asked by Amjanis on 2019-07-26 11:09:50 UTC

Comments

Ideally simple python print statements and rospy.loginfo(x) should work. Can you upload your code too as well as the commands you are using to run it and their output?

Asked by nkhedekar on 2019-07-27 06:34:44 UTC

I uploaded the code, the commands, and the output

Asked by Amjanis on 2019-07-31 10:01:36 UTC

The traceback says that there's an error in the listener function, yet there's no listener function listed.

Asked by jayess on 2019-07-31 10:09:03 UTC

How do I get print statements to work? When I include them in the code, they do not work. ie:

cmd0 = interp_servo(map_angles_01, map_cmd_us_01, alpha0)
print("wow: 0")
command_servo(0,np.int(cmd0))

Does not print anything to the terminal.

Asked by Amjanis on 2019-07-31 10:54:42 UTC

The print statements most likely aren't the problem. You don't have to do anything special to use a print statement. Besides, the code that you posted has no print statements. I suggest that you create a minimal script that demonstrates the problem that you're having. You may find that it was something else unrelated to printing

Asked by jayess on 2019-07-31 14:04:39 UTC

You set up a subscriber and then spin. That's fine. But if the subscriber doesn't get a message, nothing else will happen. How confident are you that /joint_states topic is getting published to?

Asked by billy on 2019-07-31 20:37:14 UTC

the /joint_states topic is getting published to because when I run rostopic echo on it while the program is running, lots of data appears. ex:

   header: 
      seq: 1944
      stamp: 
        secs: 1564669298
        nsecs: 494210004
      frame_id: ''
    name: [base_joint, shoulder_joint, elbow_joint, forearm_joint, wrist_joint, fingers_joint]
    position: [-0.07059167068719688, -1.1265526268264099, 2.1564758335387584, 0.0, -1.0299232067123485, 0.0]
    velocity: []
    effort: []
    ---
    header: 
      seq: 1945
      stamp: 
        secs: 1564669298
        nsecs: 514286994
      frame_id: ''
    name: [base_joint, shoulder_joint, elbow_joint, forearm_joint, wrist_joint, fingers_joint]
    position: [-0.07059167068719688, -1.1265526268264099, 2.1564758335387584, 0.0, -1.0299232067123485, 0.0]
    velocity: []
    effort: []

Asked by Amjanis on 2019-08-01 09:22:43 UTC

Also have you tried following tutorial just as a sanity check as http://wiki.ros.org/ROS/Tutorials/WritingPublisherSubscriber%28python%29

Asked by npscars on 2019-08-02 12:02:32 UTC

yes, I have tried following that tutorial, I could not get it to work either.

Asked by Amjanis on 2019-08-06 10:31:02 UTC

Answers