0
$\begingroup$

This encoder reader and publisher node needs to access another class (Rotary) to get the encoder ticks. The printer on line 11 works fine, but publishing on line 39 doesn't get the data; it only publishes zeros. What is missing here? This code runs on a Raspberry Pi with Ubuntu server 22.04 and Ros Humble. Thanks

'''

import rclpy
from rclpy.node import Node
    
from std_msgs.msg import String
from std_msgs.msg import Int32
from pigpio_encoder.rotary import Rotary
    
    
def rotary_callback(counter):
    MinimalPublisher.ticks = counter
    print(counter)

class MinimalPublisher(Node):

    def __init__(self):
        super().__init__('minimal_publisher')

        self.ticks = 0
        self.publisher_ = self.create_publisher(Int32, 'right_ticks', 10)
        timer_period = 0.05  # seconds
        
        my_rotary = Rotary(clk_gpio=22, dt_gpio=23, sw_gpio=5)
        my_rotary.setup_rotary(
            rotary_callback=rotary_callback,
            # up_callback=up_callback,
            # down_callback=down_callback,
            min=-2147483647,
            max=2147483647,
            debounce=10
        )        
        self.timer = self.create_timer(timer_period, self.timer_callback)


    def timer_callback(self):
        
        msg = Int32()
        msg.data = self.ticks
        self.publisher_.publish(msg)
        # self.get_logger().info('Publishing: "%s"' % msg.data)


def main(args=None):
    rclpy.init(args=args)

    minimal_publisher = MinimalPublisher()

    rclpy.spin(minimal_publisher)

    minimal_publisher.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

'''

$\endgroup$
1
  • $\begingroup$ I edited this post to make the code block cleaner since I misread the post initially. $\endgroup$
    – billy
    Nov 12, 2023 at 4:18

2 Answers 2

1
$\begingroup$

EDIT after seeing the formatted code:

In MinimalPublisher.ticks = counter you are referencing a Class variable. So to make it work you can make 'ticks' a Class variable instead of a instance variable.

Change

class MinimalPublisher(Node):

    def __init__(self):
        super().__init__('minimal_publisher')

        self.ticks = 0

to

class MinimalPublisher(Node):
    ticks = 0
    def __init__(self):
        super().__init__('minimal_publisher')

I loaded your code and I had same issue you did. For some reason referencing the instance variable

minimal_publisher.ticks = counter

wasn't working for me. I think ROS is doing something funny but I don't know what.

IGNORE EVERYTHING BELOW THIS LINE

You are correct this code will only publish 0s.

In the constructor you set self.ticks = 0 and then in each timer callback you publish that 0 as

msg.data = self.ticks
self.publisher_.publish(msg)

It seems like if the rotary_callback was supposed to update 'ticks' that you would need to include that bit when you call the setup function in the constructor. Given you don't, I would expect there to be a line where a variable associated with the rotary callback would be used to update ticks.

If there is supposed to be some call to 'rotary_callback' that should update 'ticks' you didn't include that callback in the question and make no attempt to call it from within the timer callback. I can't tell you how to fix it because I can't tell what you intended the code to do. If there is more code to this you should include it in the question.

Does the 'rotary' class include a method for getting the encoder count? If so, the call to that method is what is missing.

Have you read the documentation for 'rotary'?

$\endgroup$
2
  • $\begingroup$ Yes, the rotary_callback is called from the Rotary program, that updates its "counter." That is before the "minimal_publisher" node, and wasn't formatted properly here for some reason. It is printing properly, but the value doesn't get transferred into the other class here. I am updating ticks with that callback function but that doesn't work, either. I read the documentation for Rotary but the program isn't meant for ROS. I found that it worked perfectly in Python for two motors at full speed. $\endgroup$
    – Russ76
    Nov 11, 2023 at 22:39
  • $\begingroup$ github.com/vash3d/pigpio_encoder $\endgroup$
    – Russ76
    Nov 11, 2023 at 22:40
0
$\begingroup$
import rclpy

from std_msgs.msg import Int32 from pigpio_encoder.rotary import Rotary

def main(args=None): rclpy.init(args=args)

node = rclpy.create_node('minimal_publisher')
publisher = node.create_publisher(Int32, 'right_ticks', 10)

def rotary_callback(counter):
    print(counter)
    msg = Int32()
    msg.data = counter
    publisher.publish(msg)

my_rotary = Rotary(clk_gpio=22, dt_gpio=23, sw_gpio=5)
my_rotary.setup_rotary(
    rotary_callback=rotary_callback,
    # up_callback=up_callback,
    # down_callback=down_callback,
    min=-2147483647,
    max=2147483647,
    debounce=10
)
i = 0

def timer_callback():
    nonlocal i
    msg = Int32()
    i += 1
    # node.get_logger().info('Publishing: "%s"' % msg.data)
    # publisher.publish(msg)

timer_period = 0.5  # seconds
timer = node.create_timer(timer_period, timer_callback)

rclpy.spin(node)

node.destroy_timer(timer)
node.destroy_node()
rclpy.shutdown()

if name == 'main': main()

This code actually works OK! It's not elegant or the best, I know. It publishes when the encoder works only, but for now it will serve to get the data over to another node that will publish the proper ROS odom message, which is what we're after. I'll have to make another set to do the other side, as this does just one side of the robot. But it is fast, and goes negative or positive as far as Int(32) will go. I'm sure it can be improved...

$\endgroup$
3
  • $\begingroup$ I provided additional answer within my first response explaining issue. $\endgroup$
    – billy
    Nov 12, 2023 at 4:20
  • $\begingroup$ Thank you, Billy! $\endgroup$
    – Russ76
    Nov 12, 2023 at 13:54
  • $\begingroup$ I have shortened the "rotary" library somewhat, taking out code meant for the switch on a handheld encoder. With two sides of the robot working at once, publishing the ROS topics, it works perfectly. And this is with IMU publishing and cmd_vel subscribing at the same time. $\endgroup$
    – Russ76
    Nov 12, 2023 at 13:58

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.