Reading Sensors through ROS and RaspberryPi

Writing The Node:
Nodes are executable pieces of code that run in ROS. This is an example of writing a node for ROS on RaspberryPi (RPi) which continuously reads data from an Input pin on the RPi. In this case the Data is a push button signal.

The first step in writing a ROS Node is a declaration which tells the system to run the script in Python:

#!/usr/bin/env python
 
Then importing the necessary libraries that are required to call certain functions:

import rospy
from std_msgs.msg import String
import RPi.GPIO as GPIO 

Rospy libraries give access to ROS python functions. The "std_msgs.msg" is a library which defines message types which are used in ROS. RPi.GPIO are functions for input/output access on the RaspberryPi.

pub = rospy.Publisher('Pin4Data', String, queue_size=10)
rospy.init_node('Pin4DataReader', anonymous=True)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

The first line defines the topic name of the node "Pin4Data" which can be subscribed to.
Next the node is initiated with the name "Pin4DataReader".
GPIO.setup sets up reading the button at pin number 4.
The pull_up_down argument controls the state of the internal pull-up/down resistors.

rate = rospy.Rate(10) # 10hz

With the help of the method rate.sleep(), setting up the rate helps defining how fast the node will loop

while not rospy.is_shutdown():
   button_state = "Button State = %s" % GPIO.input(4)
   rospy.loginfo(button_state)
   pub.publish(button_state)
   rate.sleep() 

This loop is the main part of the ROS node, the first while checks if the program should be shutting down (E.G: if Crtl-C is pressed in the command window). While the program shouldn't shut down, it runs the written commands.
The defined string button_state is what we want to publish.
The loop calls pub.publish(String(str)), which publishes the string to the Pin4Data topic.
The loop calls rospy.loginfo(str), which performs triple-duty: the messages get printed to screen, it gets written to the Node's log file, and it gets written to rosout.
The loop calls rate.sleep(), which sleeps long enough to loop the node at the designed rate.

try:
   Pin4DataReader()
except rospy.ROSInterruptException:
   pass

This last bit of code catches a rospy.ROSInterruptException exception, which can be thrown by rospy.sleep() and rospy.Rate.sleep() methods when Ctrl-C is pressed or the node is shutdown. The reason this exception is raised is so that it doesn't accidentally continue executing code after the sleep() function.

The entire code:

#!/usr/bin/env python
 
import rospy
from std_msgs.msg import String
import RPi.GPIO as GPIO
 
pub = rospy.Publisher('Pin4Data', String, queue_size=10)
rospy.init_node('Pin4DataReader', anonymous=True)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)

rate = rospy.Rate(10) # 10hz
while not rospy.is_shutdown():
   button_state = "Button State = %s" % GPIO.input(4)
   rospy.loginfo(button_state)
   pub.publish(button_state)
   rate.sleep() 

try:
   Pin4DataReader()
except rospy.ROSInterruptException:
   pass

------------------------------------------------------------------------------------------------