Skip to content

Architecture

Nathan Collins edited this page Apr 27, 2018 · 3 revisions

ROS

This program is built on ROS ("Robot Operating System"), a massive library for working with robotics in C++, Python, and Lisp (plus experimental implementations in Java and Lua). Many of the core concepts of ROS are described below.

Nodes

A node is basically a single executable. ROS manages running and communicating between the different nodes. The nodes make up the bulk of the code we write. Following is a list of nodes in this application:

Master GUI

This is the primary user interface for the program. It shows a map of the current location along with the current position, and allows the user to specify where to go on the map. This is currently the only node written in Python. All the others are written in C++.

State Machine Node

This is the node that does the real work. It uses the sensors to determine where to go and uses the actuators to go there.

Actuator and Sensor nodes

There is a node for each actuator (i.e. Relay Board, Motor Controller, etc.) and each sensor (i.e. GPS, Compass, etc.). The actuator nodes primarily receive messages from the State Machine for what to do (i.e. set a relay). The sensor nodes primarily send messages to the state machine with information about current status (i.e. current location, direction, obstacles, etc.).

Other nodes

There are probably other nodes that I haven't listed. Sorry.

Message passing

One of the primary features of ROS is its method of IPC (inter-process communication), handled through message passing between nodes. There are a few major concepts needed for this message passing:

Messages

You can define various types of messages in the program in .msg files. For example, you could define a GPS message that contains a floating-point latitude and longitude.

Topics

Messages are passed in various topics. For example there is a GPS topic that the GPS node sends messages on and the state machine listens on.

Publishers

An ROS Publisher is the code mechanism for sending messages. A publisher can be defined with the following code in C++:

// this can be declared as a global variable, but it must be reassigned before it can be used
ros::Publisher pub; 

// must be declared after ros::init has been called. You can't have this as a global variable
ros::NodeHandle handle;
// the 1 is the queue size. This determines how long message can queue up. Probably best to set this higher than actually needed
// the true determines whether new subscribers will receive messages that have already been published
pub = handle.advertise<MessageType>("Topic-name", 1, true);

Subscribers

An ROS Subscriber defines a subscription to a topic, which responds to messages in a topic. You can either listen for a single message with:

// waits for up to 5 seconds for a message on this topic
auto msg = ros::topic::waitForMessage<MessageType> ("Topic-name", ros::Duration(5));
// wait for the message
ros::spinOnce();
if (relay_msg == NULL) {
    // no message
} else {
    // get one of the attributes of the message, defined in the .msg file
    string state = msg->state;
}

Or you can subscribe permanently and be called whenever a message comes in:

// must be declared after ros::init has been called. You can't have this as a global variable
ros::NodeHandle handle;

// need to assign this to a variable, and when the variable goes out of scope, we unsubscribe
auto subscriber = handle.subscribe("Topic-name", queueSize, callback);
// just sit in a loop until the program exits.
ros::spin();

State Machine

The state machine contains the primary code that we've written, and it decides how to drive based on what state it's in. It still needs a lot of work, and perhaps a full rewrite. We also need good documentation about how it works.

Clone this wiki locally