Robochameleon
v1.0
|
Introduction to framework
Robochameleon is a coding framework and component library for simulation and experimental analysis of optical communication systems. This is a quick start guide to using the framework; descriptions of components can be found in the corresponding class definitions.
We use classes to ensure standardization for both signal representation and functions. This guide has a brief introduction to classes, but if you are familiar with object oriented programming, you should skip it.
The Robochameleon project is stored in multiple folders, which all must be in Matlab's search path for the code to run. The script robochameleon.m will automatically add these to the path.
There are also some toolbox dependencies, as well as some function calls to relatively new features in Matlab. When possible, we have added alternatives in the compatibility folder. The initialization script does some automatic detection of what features the user has, but is not perfect, and in some cases it might be necessary to add these folders manually. In particular, [module] uses the bioinformatics toolbox, so the folder \compatibility\bioinfolite should be in the path if the user does not have a license.
Classes ensure standardization for a large function library. They facilitate block data processing and internal state saving. For a complete introduction to classes using Matlab, there are some useful tutorials on Matlab Central.
Here is a very simple (and totally useless) example of a class that adds two numbers together:
A class basically consists of two things:
All classes must have a method (called the constructor) that creates an object of that class. In the above example, that was:
In the above example, there is an additional method called plus
that contains the main function. To use this class, one would first make an adder using the constructor:
Note the addition has not been performed yet. Then to perform the pre-defined operation:
Note all other operations are prohibited:
In Robochameleon, there are four basic classes:
Clicking the above links will take you to the full reference pages for each class with documentation of all properties and methods. Below, we have a more general introduction to the most important properties and methods, as well as descriptions of how these are meant to interact.
Signals are described using two classes, pwr, and signal_interface. Each signal_interface object has a property (signal_interface::PCol) that is an array of pwr objects. An array is used so that one pwr object describes the power contained in each each component (polarization) of the waveform.
Typically signal power is represented as an object of type pwr. The two main properties are
Note that the SNR is not always well-defined (e.g. this value doesn't mean much after propagation through a nonlinear channel). The primary purpose of tracking SNR is to help understand what limits performance of a simulated system, but sometimes some discretion in interpreting this value is required.
The signal power and noise powers are defined as the total powers in the bandwidth of the signal waveform (i.e. the sampling rate Fs). Thus if a large oversampling ratio (e.g. 16 samples per symbol) is used, then the SNR of the signal will be much worse than the SNR of an equivalent signal in a real system.
There are a number of useful methods in the pwr class, including addition, scalar multiplication, and several display and unit conversion functions. These are documented in the class itself. For an example of how to use pwr objects, consult run_Testpwr.m in \Setups\Demo.
All signals must be represented as objects of type signal_interface. They have the following user-specified properties:
These quantites are also not always well-defined (e.g. the output of a laser has no symbol rate), but are nonetheless required. signal_interface objects also have some derived properties:
which can be read and used but not modified.
Here is a very simple example of how to construct a signal interface object and what the display function looks like:
There are a number of useful methods in signal_interface that are documented there. Most notably, there are methods to apply functions to signals and add signals to each other such that power and SNR are tracked automatically.
Note that the waveform amplitude (signal_interface::PCol) is specified separately from the waveform shape (signal_interface::E). This can lead to un-intended results when the two are in conflict. It is important to always use the appropriate get and set-like (signal_interface::fun1, signal_interface::plus, signal_interface::mtimes) methods when manipulating waveforms.
For an extended example, see run_TestSignalInterface.m and run_TestSignalInterfaceAdvanced.m in \Setups\Demo
Every function that can be applied to a signal_interface object is encapsulated in a unit. Multiple units can be collected into a super-unit, which is called a module.
Everything that operates on a signal_interface object should be defined as a class that inherits certain properties from [unit]. For example:
All units must have the following properties:
Units must also have the following method (in addition to the constructor):
Traverse acts like main in c programs. It defines what function the unit performs on the signal. The only allowable inputs and outputs of traverse are of type signal_interface. This is necessary to ensure cross- compatibility between units written by different people, as well as module construction. Everything else should be an object property.
There are a number of properties automatically included in all units. The ones relevant to the user are:
A module is a collection of connected units. Modules can contain other modules.
A module definition will only have a constructor. The constructor has three parts:
For example:
creates a module with the following connection diagram:
A module is itself a unit. Enabling unit::draw for a module will plot a system diagram (biograph) when the constructor is called. These do not close with close all
, but can be removed with close_biographs
.
There is an additional class in base called const where physical constants in standard SI units are stored.
For example, to use the speed of light, enter const.c
.
Here is a partial list of generally useful functions:
For creating & programming new units and modules:
Name | Description |
---|---|
createRoboUnit.m | Create a unit using template |
increaseClassVersion.m | Create new version of a unit |
unit::setparams | Set default parameters in class constructor (replaces paramdefault.m) |
robolog.m | Robochameleon log utility (for errors, warnings, etc.) |
For running scripts and browsing results
Name | Description |
---|---|
robochameleon.m | Add all robochameleon directories to path |
clearall.m | Clear workspace variables preserving breakpoints |
close_biographs.m | Close biographs (module diagrams) |
findUnit.m | Find a unit within a module (requires full unit name, recursive search) |
compileMex.m | Compile all MEX files in project |
There are a number of examples in the folder. These are organized in order of increasing complexity in numbered sub-folders.
For a general overview of the physical layer, the following references may be useful:
For a general overview of the DSP, we recommend the following papers: