Table of Contents for amac:
Return to goby-acomms: An overview of Acoustic Communications Library.
Supported MAC schemes
The Medium Access Control schemes provided by amac
are based on Time Division Multiple Access (TDMA) where different communicators share the same bandwidth but transmit at different times to avoid conflicts. Time is divided into slots and each vehicle is given a slot to transmit on. The set of slots comprising all the vehicles is referred to here as a cycle, which repeats itself when it reaches the end. MACManager is implemented as a timer and a std::list of goby::acomms::protobuf::ModemTransmission objects. This allows you to use amac
to create a TDMA cycle for any type of transmission (data, ping, LBL, etc.) that your modem supports.
The two variations on this scheme provided by amac
are:
-
Decentralized: Each vehicle initiates its own transmission at the start of its slot. (goby::acomms::protobuf::MAC_FIXED_DECENTRALIZED): Slots are set at launch and can be updated using the std::list insert, push, pop, erase, etc. Each vehicle can have more than one slot in the cycle. The cycles must agree across all platforms; the network designer is responsible for this. Most of the time you will want to use this mode.
-
Centralized Polling (goby::acomms::protobuf::MAC_POLLED on the master, goby::acomms::protobuf::MAC_NONE on all other nodes): The TDMA cycle is set up and operated by a centralized master modem ("poller"), which is usually the modem connected to the vehicle operator's topside. The poller initiates each transmission and thus the vehicles are not required to maintain synchronous clocks. This mode requires third-party initiation of transmissions to function.
Interacting with the goby::acomms::MACManager
To use the goby::acomms::MACManager, you need to instantiate it:
Then you need to provide a callback (or "slot", not to be confused with a TDMA slot) for initiated transmissions for the signal goby::acomms::MACManager::signal_initiate_transmission. This signal will be called when the goby::acomms::MACManager determines it is time to send a message. If using modemdriver
, simply call goby::acomms::bind(goby::acomms::MACManager&, goby::acomms::ModemDriverBase&) to bind this callback to the modem driver.
Next you need to decide which type of MAC to use: decentralized fixed or centralized polling and set the type of the goby::acomms::protobuf::MACConfig with the corresponding goby::acomms::protobuf::MACType. We also need to give goby::acomms::MACManager the vehicle's modem id (like all the other components of goby-acomms):
mac_cfg.set_type(protobuf::MAC_FIXED_DECENTRALIZED);
mac_cfg.set_modem_id(1);
You can also provide a set of slots in the protobuf::MACConfig to initialize the MACManager with. Otherwise, you can add them later using the std::list calls.
The usage of the goby::acomms::MACManager depends now on the type:
-
goby::acomms::protobuf::MAC_FIXED_DECENTRALIZED: All vehicles must be running goby::acomms::protobuf::MAC_FIXED_DECENTRALIZED and share the same cycle (set of slots). Also, since each vehicle initiates its own transaction, you can use goby::acomms::QUERY_DESTINATION_ID throughout. In this example, I used the std::list push_back instead of adding the slots to the protobuf::MACConfig (see under MAC_POLLED below). Either way, you get the same result, but you can modify the std::list after startup():
slot.set_src(1);
slot.set_rate(0);
slot.set_type(goby::acomms::protobuf::SLOT_DATA);
slot.set_seconds(10);
mac.push_back(slot);
slot.set_src(3);
mac.push_back(slot);
slot.set_rate(5);
mac.push_back(slot);
slot.set_src(4);
slot.set_rate(0);
mac.push_back(slot);
-
goby::acomms::protobuf::MAC_POLLED: On the vehicles, you do not need to run the goby::acomms::MACManager at all, or simply give it the "do nothing" goby::acomms::protobuf::MAC_NONE type. All the MAC is done on the topside (the centralized poller). On the poller, you need to manually set up a list of vehicles to be polled by adding an goby::acomms::protobuf::Slot (in the initial goby::acomms::protobuf::MACConfig object or at runtime via goby::acomms::MACManager::add_slot) for each vehicle to be polled. You can poll the same vehicle multiple times, just add more goby::acomms::protobuf::Slot objects corresponding to that vehicle. Each slot has a source, destination, rate, type (data or ping [not yet implemented]), and length (in seconds). If the source is the poller, you can set the destination to goby::acomms::QUERY_DESTINATION_ID (=-1) to let
queue
determine the next destination (based on the highest priority message to send). All goby::acomms::protobuf::Slot objects for vehicles must have a specified destination (the goby::acomms::BROADCAST_ID is a good choice or the id of the poller). For example: slot.set_src(1);
slot.set_rate(0);
slot.set_type(goby::acomms::protobuf::ModemTransmission::DATA);
slot.SetExtension(goby::acomms::protobuf::slot_seconds, 10);
mac_cfg.add_slot(slot);
slot.set_src(3);
mac_cfg.add_slot(slot);
slot.set_rate(5);
mac_cfg.add_slot(slot);
slot.set_src(4);
slot.set_rate(0);
mac_cfg.add_slot(slot);
You can remove vehicles by a call to goby::acomms::MACManager::remove_slot or clear out the entire cycle and start over with goby::acomms::MACManager::clear_all_slots.
Then, for either MAC scheme, start the goby::acomms::MACManager running (goby::acomms::MACManager::startup with the goby::acomms::protobuf::MACConfig object), and call goby::acomms::MACManager::do_work() periodically (5 Hz is ok, 10 Hz is better).
You can modify the MAC scheme while MACManager is running. Simply use the std::list insert, push, pop, erase methods to changes slots (goby::acomms::protobuf::ModemTransmission objects). After any changes that invalidate std::list iterators (insert, push, pop, erase), you must call goby::acomms::MACManager::update() before the next call to goby::acomms::MACManager::do_work().
See amac_simple.cpp for a basic complete example.