ROSbots is a ROS + OpenCV robot kit for Makers. We recently which is based off the Raspberry Pi 3. launched our ROSbots version 2.0 robot kit The kit includes a camera, wheel encoders, two rechargeable lithium battery power sources, and even an Arduino-compatible UNO board for hardware PWM, interrupt, and ADC support. Hardware is fun, but more importantly, we want to use hardware to apply robotics concepts. That requires learning software and the know-how to implement these robotics concepts with modern software tools like and . ROS OpenCV As the 1st post from a multi-part series, we plan on publishing about concepts learned from the course and applying them to the ROSbots robot using ROS. The Control of Mobile Robots course sets the foundation to understand mobile — how to control your robot predictably and how to use sensor data to estimate pose and have your robot understand its surroundings. Coursera Control of Mobile Robots robot control theory (Update 3/24/2018: — has been published.) part 2 of the series — where we talk about unicycle and differential drive robot models Upon completing our multi-part series, you will have a working understanding of robotics control theory and ROS. (Follow @rosbots for updates. Follow us on Instagram and Facebook too!) If you have your own , we welcome you to follow along. Hands-on doing with your own ROSbots kit will add that more more color to what we write than simply reading this post. ROSbots robot In this post, we’ll be prepping to implement the control models described in week 1 of Control of Mobile Robots. Specifically we’ll be doing the following in this post: Learn how the L9110 Motor Driver on the ROBbots robot works. Walk through the Arduino sketch code that implements a ROS node to drive the L9110 to spin our wheels. Compile and upload the ROS-Arduino sketch to our ROSbots’ UNO board, and run the ROS node on the ROSbots’ main brain — ie its Raspberry Pi. Give you a hands-on feel for how ROS’s messaging system works — use some built in ROS tools to control our motors. We expect you to know a bit about electronics, have played with Arduinos, have some software programming experience and be comfortable with electronics and coding lingo. If you are a good top-down learner, then it’s NOT required for you to have taken the Control of Mobile Robots course, nor is it required for you to have knowledge of ROS. But if you have done both, it will definitely be intellectually beneficial. The L9110 motor driver has 2 channels — fancy talk to say it has the ability to control 2 motors. L9110 mounted on the ROSbots robot and another one shown right side up. There are 2 input control pins per channel — IA and IB — that “drive” the 2 output pins — OA and OB connected to the ROSbots robot’s motors. Hence there are 4 input pins and 4 output pins total. There is a set of IA/IB/OA/OB pins for one channel A (which is connected to our left motor/wheel) and another for channel B (which is connected to the right motor/wheel). IA is what we PWM to modulate the motor speed. The IB pin controls motor direction. The L9110 pin table summarizes the input/output behavior: L9110 input and output pin table Want a quick show-and-tell with your ROSbots robot? Place the wire connected to A-IA, specifically G-6 on your ROSbots’ breadboard, into any hole on the top row of the breadboard (VCC). Place the wire connected to A-IB, specifically G-5, into any hole on the bottom row of the breadboard (GND). The left wheel will spin forward. Now swap the connections — G-6 into GND, and G-5 into VCC, now the left wheel will spin backwards. We will drive the L9110 with the UNO board on our ROSbots robot by writing a ROS-capable Arduino Sketch for it. The (don’t forget to star and follow!). main.cpp sketch code can be found in rosbots_driver Github repo Let’s skip over a bunch of ROS specific code and jump directly to this block around line 16 onwards. Notice that the right wheel’s IA (PWM) and IB (direction) pins are connected to the pins 5 and 4 respectively on the UNO board; left wheel’s IA and IB are connected to pins 6 and 7. Next let’s look at the block of code that actually drives the pins to turn the wheels. Ignore the debug code in the comments In the function, we clamp the input variable between -1.0 (full reverse) and 1.0 (full forward). That modulates the PWM voltages that output to the respective L9110’s IA pin (aka ) and the digital voltage output to the IB pin (aka , as in fwd-reverse). turnWheel(…) wheel_power pwm_pin fr_pin The simple math during the linearly adjusts the PWM pulse width according to the direction specified by the sign of — positive means forward, negative means reverse. analogWrite(…) wheel_power As the goes from -1.0 to 1.0, you can see the and transition from full reverse, to stop, to full forward as described by the L9110 pin table in the beginning of this post. wheel_power pwm_pin fr_pin Let’s compile and upload this sketch code to our UNO board to see it in action. ROSbots uses to compile and upload ROS-Arduino sketch codes to the UNO board. platformio We’ll assume you got your . ROSbots robot set up with these instructions SSH into your ROSbots’ Raspberry Pi — we’ll be doing the remaining steps on the RPi. Run the following in your RPi terminal (feel free to cut-n-paste directly): (all one line) ~/$ upload_firmware ~/gitspace/rosbots_driver/platformio/rosbots_firmware/examples/motor_driver Success?? On our RPi, type to get a list of ROS nodes running — you should see the following: rosnode list /rosout/uno_serial_node Type to get a list of ROS topics being published or subscribed to — you should see the following: rostopic list /diagnostics/rosout/rosout_agg/wheel_power_left/wheel_power_right What are ROS nodes and topics? What does all this mean? Inspired by the , ROS is set up as a bunch of independent processes known as ROS nodes that communicate to each other via messages. One ROS node can be running the process that reads out of the Pi camera, then subsequently publish the images as an “image” message type out on a “foo” topic channel. Another ROS node who’s responsible for detecting cats in incoming images will subscribe to the “foo” topic channel. Like the standard pub/sub model, publishers and subscribers do not care about who has subscribed or who is publishing upstream and downstream. publisher/subscriber distributed messaging architecture In summary, any ROS node can be a publisher and/or subscriber of a specific message type communicated through a named channel known as a ROS topic. In our example here, we wrote some Arduino sketch code to be a ROS node that subscribes to two topics — and . The message on these channels will be types (versus “images” in the hypothetical example above). wheel_power_right wheel_power_left Float32 Take a look at this piece of the Arduino sketch code you compiled and uploaded: You’ll notice that our UNO board subscribing to the two topic channels— and — with these 2 blocks of code. wheel_power_right wheel_power_left When we get a message on either of these topics, we call the and callback respectively. That callback, if you recall, implemented the code to drive the L9110’s input pins. rightWheelCb(…) leftWheelCb(…) If you recall typing the topic names and were listed. rostopic list wheel_power_right wheel_power_left Life is good. Right? Our sketch code lives on our UNO board. But how does our UNO board communicate to the rest of the ROS system running on the Raspberry Pi? The UNO board is connected to our RPi via the USB and communicates to it via serial port. That’s all fine and dandy except ROS does not directly talk “serial port”!? If you recall again, when you typed , you saw an listed as one of the running ROS nodes. In order for ROS to be able to talk “serial port”, we need a bridge that serializes the ROS messages into serial port packets sent to our UNO to process. This bridge application is the ROS node known as — we named the node . rosnode list /uno_serial_node rosserial /uno_serial_node The ’s job is to open a serial port connection to the UNO board and then serialize/deserialize ROS messages to and from the UNO board. /uno_serial_node Type and you’ll see as the subscriber. Why doesn’t it say our UNO code? rostopic info /wheel_power_left /uno_serial_node Well remember our UNO board cannot talk to the ROS system directly — it only can talk with the via the serial port. Our UNO code does specify to the that it wants to subscribe to the topic and the subscribes to that topic on the UNO’s behalf. You can think of the rosserial as the mediator between the ROS world and the Arduino Sketch world. /uno_serial_node /uno_serial_node /wheel_power_left /uno_serial_node /uno_serial_node OK — the UNO is a subscriber to topics and (via rosserial ) which will drive the wheels depending on the message received. But who is the publisher? /wheel_power_left /wheel_power_right /uno_serial_node Float32 No one for now. Instead we will use the ROS tool to manually publish some ROS messages on these topic channels to drive the wheels. rostopic From within your RPi bash terminal: From any directory, doesn’t matter, type (or cut-n-paste) — your left wheel should spin forward rostopic pub -1 /wheel_power_left std_msgs/Float32 '{data: 1.0}' Type (or cut-n-paste) — your left wheel should stop rostopic pub -1 /wheel_power_left std_msgs/Float32 '{data: 0.0}' Type (or cut-n-paste) — your left wheel should spin backwards rostopic pub -1 /wheel_power_left std_msgs/Float32 '{data: -1.0}' Type (or cut-n-paste) — your left wheel should spin backwards slower. rostopic pub -1 /wheel_power_left std_msgs/Float32 '{data: -0.5}' The command tells ROS we want to publish. If you type you’ll see a couple of options. The option says just publish a message once versus continuously. The next option is the topic channel name. is the message type. is the actual payload data. It’s in a JSON-like curly brace syntax because ROS generalizes messages as data structures. So the ROS message type defined from a bunch of standard (notice listed in the link). The is actually a data structure of one entity, a 32-bit float. rostopic pub rostopic pub --help -1 std_msgs/Float32 '{data: 1.0}' Float32 ROS package of std_msgs Float32 message type Float32 Congrats — you just successfully published your first set of ROS messages on a topic and wrote code to implement a ROS node that subscribes to and processes that message. Feel free to try the same exercise for the right wheel. Have Questions? If you have questions, post them on with the subject “ROSbots question: ” and tag the post with “rosbots”. We’ll be monitoring the forum and answer accordingly. answers.ros.org whatever your question is How does all this relate back to Coursera’s Control of Mobile Robots course? We are effectively building the components to turn the . Then we will add the feedback from the ROSbots’ wheel encoders to implement a PID controller for wheel velocity which will be able to allow us to estimate pose — position and orientation — of our robot. Unicycle Model described in week 1 of the course into a Differential Drive Robot Model The final post in this series will completely implement the coding project described in the course. But instead of using Matlab, we will use ROS and our ROSbots robot! Follow @rosbots on Medium for updates. Follow us on and too! Instagram Facebook Feel free to comment here. But if you have technical questions, please post them on answers.ros.org (subject “ROSbots question: ”, tag “rosbots”). blahblah Don’t hesitate to reach out with general feedback, if you want to collaborate, or just to say hello. And if you haven’t already done so, to follow along. purchase your own ROSbots robot here Thanks!Jack “the ROSbots Maker”