Connect with ROS

ROS 1 & 2 require zero code!

Now that you've installed the Agent, a ROS Shadow node will turn on every time you run ROS and begin uploading data to Freedom.

📘

ROS 1 and ROS 2

Freedom supports both ROS 1 and ROS 2. When you install the Agent on your device, open the ADVANCED menu and select the appropriate version of ROS before running the install script.

If you want to use a launch script, play a ROS bag, or run a ROS node, there is nothing else you need to do. Your data will start uploading to the cloud because of the shadow node! Here we walk through a minimal example to show you a bit more about how it works.

📘

Don't have ROS?

If you want to test out the ROS examples and don't have ROS installed (or are using a Mac), run the following command to access the Freedom Docker Playground: docker run -it frdmrobotics/playground bash. You'll need to apt-get install nano (or your favorite editor).

Start uploading data

Freedom automatically spins up a node (named link_ros) to introspect topics published using ROS. Launch something and start publishing to check it out - ROS bags work too!

The data will appear in the Freedom App in your STREAM dashboard.

# Launch your own nodes and the Agent will automatically
# start a node (link_ros) that listens to what is published.
# Make sure to source your ROS workspace before launching. 

roslaunch my_package my_launch.launch
# Launch your own nodes and the Agent will automatically
# start a node (link_ros) that listens to what is published.
# Make sure to source your ROS workspace before launching. 

ros2 launch my_package my_launch.launch
# Source ROS workspace
source /opt/ros/melodic/setup.bash

# Download a ROS bag to play, saving it as rosbag-example.bag
curl -L -o rosbag-example.bag https://bit.ly/freedom-rosbag-example-car

# Start roscore if it is not running already
roscore &

# Play the ROS bag and the Agent will listen to the topics it publishes
rosbag play rosbag-example.bag
# Not many good quality ROS2 bags exist yet - here we show a
# workaround with a ROS1 bag run in ROS2

# Make sure you have installed ros2 bag packages
apt-get update
sudo apt-get install ros-dashing-ros2bag-* ros-dashing-rosbag2*

# Source ROS1 workspace first
source /opt/ros/melodic/setup.bash

# Now source ROS2 workspace
source /opt/ros/dashing/setup.bash

# Download a ROS bag to play, saving it as rosbag-example.bag
curl -L -o rosbag-example.bag https://bit.ly/freedom-rosbag-example-car

# Play the ROS bag and the Agent will listen to the topics it publishes
ros2 bag play -s rosbag_v2 rosbag-example.bag

Send and receive messages

We'll walk through an example that shows how a ROS node can both send messages to Freedom and respond to a command sent from the Freedom API.

Set up a node

Create a file called demo_node.py and copy in the code below.

#!/usr/bin/env python

# Please note that there are no references to Freedom in this ROS node.
# The ROS Shadow node will automatically interact with this node and 
# stream the data.

import rospy
from std_msgs.msg import String
from sensor_msgs.msg import NavSatFix

# Create a callback to handle this topic
def callback(data):
    rospy.loginfo("I heard %s", data.data)
    if data.data == "mission":
        rospy.loginfo("Running mission...")
    elif data.data == "shutdown":
        rospy.signal_shutdown("Received shutdown command")

# There is nothing you need to do. The ROS Shadow node        
# will automatically start when this starts
if __name__ == "__main__":
    rospy.init_node('node_name')
    rospy.Subscriber("commands", String, callback)
    
    # Create our satellite GPS location topic
    pub_nav = rospy.Publisher("location", NavSatFix, queue_size=10)
    nav_msg = NavSatFix(latitude=37.778454, longitude=-122.389171)
        
    while not rospy.is_shutdown():
      	# Report location
        pub_nav.publish(nav_msg)
        rospy.sleep(1)
#!/usr/bin/env python

# Please note that there are no references to Freedom in this ROS node.
# The ROS Shadow node will automatically interact with this node and 
# stream the data.

import time
import rclpy
import rclpy.logging
from std_msgs.msg import String
from sensor_msgs.msg import NavSatFix

logger = rclpy.logging.get_logger('node_logger')

# Create a callback to handle this topic
def callback(data):
    logger.info("I heard {}".format(data.data))
    if data.data == "mission":
        logger.info("Running mission...")
    elif data.data == "shutdown":
        logger.info("Received shutdown command")
        rclpy.shutdown()
        
# There is nothing you need to do. The ROS Shadow node        
# will automatically start when this starts
if __name__ == '__main__':
    rclpy.init()

    node = rclpy.create_node('node_name')

    subscription = node.create_subscription(String, 'commands', callback, 10)

    # Create our satellite GPS location topic
    pub_nav = node.create_publisher(NavSatFix, 'location', 10)
    nav_msg = NavSatFix(latitude=37.778454, longitude=-122.389171)

    rclpy.spin(node)

    while rclpy.ok():
        pub_nav.publish(nav_msg)
        time.sleep(1)

    # Destroy the node explicitly
    # (optional - otherwise it will be done automatically
    # when the garbage collector destroys the node object)
    node.destroy_node()
    rclpy.shutdown()

Start the node with the following commands.

# Source ROS1 workspace
source /opt/ros/melodic/setup.bash

# Start rosmaster if not started yet
roscore &

# Execute created script
python demo_node.py
# Source ROS2 workspace
source /opt/ros/dashing/setup.bash

# Execute created script with python3 (mandatory for ROS2)
python3 demo_node.py

Your robot is now reporting its location while waiting patiently for a remote command! You can view its location on a map in your STREAM dashboard.

This example is written to show you the basics of connecting with Freedom using ROS. In general, you should build a ROS package, compile with Catkin or Colcon and use rosrun or roslaunch, rather than running a ROS node in isolation as shown above.

Test the callback

To check that the callback works, we'll send a command to your device using Freedom's REST API.

First, select your device in the Freedom App and navigate to SETTINGS → DEVICE. In the INTERFACE section, select either ROS (for ROS1) or ROS2.

Next, if you haven't already, click Log In in the top right corner of this page so we can populate the values for your token, secret, account, and device for this example. Once you've logged in, run the following command:

TOKEN="<<USER_TOKEN>>"
SECRET="<<USER_SECRET>>"
ACCOUNT="<<ACCOUNT>>"
DEVICE="<<DEVICE>>"
HEADERS="-H content-type:application/json -H mc_token:$TOKEN -H mc_secret:$SECRET"
DATA="[{
    \"platform\": \"ros\", 
    \"utc_time\": `date +%s`,
    \"topic\": \"/commands\",
    \"type\": \"std_msgs/String\",
    \"expiration_secs\": 10,
    \"message\": {\"data\":\"mission\"}
}]"

curl -v $HEADERS -d "$DATA" -X PUT "<<API_URL>>accounts/$ACCOUNT/devices/$DEVICE/commands"
TOKEN="<<USER_TOKEN>>"
SECRET="<<USER_SECRET>>"
ACCOUNT="<<ACCOUNT>>"
DEVICE="<<DEVICE>>"
HEADERS="-H content-type:application/json -H mc_token:$TOKEN -H mc_secret:$SECRET"
DATA="[{
    \"platform\": \"ros\", 
    \"utc_time\": `date +%s`,
    \"topic\": \"/commands\",
    \"type\": \"std_msgs/msg/String\",
    \"expiration_secs\": 10,
    \"message\": {\"data\":\"mission\"}
}]"

curl -v $HEADERS -d "$DATA" -X PUT "<<API_URL>>accounts/$ACCOUNT/devices/$DEVICE/commands"

The message will be received in the callback you set up. Once your robot receives the command, it will log Running mission....

Change mission to shutdown and send a new command. Your application will now shut down remotely.

Success! You now know how to use Freedom to upload data and communicate with your robot through the cloud.

What's next?

If you would like to read walkthroughs of usage for key aspects of the system, the guides for Monitoring, Alerts and Integrations, and The Pilot Tab are a great place to start.

If you prefer reviewing detailed API specs and references, you can do that also.

If you like to poke around applications, go to the Freedom App and explore!