Developers Manual

From Simspark
Jump to: navigation, search

We are currently working on an extensive developer's manual. If you are willing to help, please contact Markus Rollmann <rollmark at uni-koblenz dot de> or Joschka Boedecker <jboedeck at uni-koblenz dot de>.

This section is for people interested in developing the server itself. If your goal is to develop a program that connects to a running instance of a simulation, you should probably start by reading the page on Agents.

Contents

Server Overview

Block diagram showing control and data flow of the simulator

SimSpark is built upon an application framework called zeitgeist. This framework provides basic OS abstractions like file and archive support, logging, shared libraries etc.), a scripting interface to Ruby and a powerful plugin mechanism coupled with an object hierary that provides a unified namespace. This library is the backbone of the system.

Zeitgeist allows us to load new classes at runtime from plugins and install object instances in a hierarchy. We can locate these instances via path expression just like files in a file system. At various well known locations are objects called servers that provide services to other parts of the system. The script server that provides an interface to the Ruby is installed at /sys/server/script.

Built as part of this object hierarchy is a scene graph that the system uses to represent the simulated world. This scene graph and related concepts are managed within the next layer of the system, that we call oxygen. It provides classes that encapsulate concepts like transformations, basic geometric primitives, physical bodies and collision primitives. It further provides access to a rigid body physical simulation.

The oxygen library further implements basic simulation services like agent management and a monitor framework. It is responsible to keep track and to update connected agents and monitor processes. Last but not least it provides a customizable run loop service. This service is implemented as an abstract run loop that is extended with plugins as needed. In parts of the system can be replaced or left out easily as for example rendering or monitor support.

The visualization of the scene and input event processing services are provided by the kerosin library. It implements the infrastructure for rendering and device management. Concrete implementations are again provided by plugins. This allows the simulation to use different back ends or graphic engine. A default set of plugins utilizes plain OpenGL and the SDL library.

The physics simulation is performed by Open Dynamics Engine (ODE), though work in 2010 made the interface abstract enough to enable other physics simulations (such as Bullet or PhysX) to be swapped in.

Zeitgeist

The Zeitgeist library provides two major features. It implements a mechanism to work with class objects in C++. A class object is just a factory of class instances. In addition to this mechanism, it also implements an object hierarchy. This hierarchy is essentially a virtual file system, where the 'directories' and 'files' are instances of C++ classes. These two concepts are quite intertwined with each other, as class objects can also live inside the object hierarchy. Objects within the hierarchy are identified with a unique name. On top of these two features, the Zeitgeist library also provides three very important 'built-in' services. Each basic service is usually represented by a 'server' class in our terminology. An instance of such a class provides the service to other parts of the system. The three services built into the Zeitgeist library are the LogServer, the FileServer, and the ScriptServer.

Reflective Factory Pattern

The Reflective Factory Pattern is also known as Class Object Pattern. In addition to the capability of instantiating object at runtime, it provides users with the references to the meta information about the class, which distinguishes the Reflective Factory Pattern from the Abstract Factory Pattern.

Object Hierarchy

As you can see in the API, the hierarchy provided starts from a class named Object. This class is the base class of all classes living inside the Zeitgeist framework. It provides the necessary interfaces to be used by Zeitgeist, e.g. GetClass() and GetCore(). Leaf is the direct child of Object, which represents the leaf node in the hierarchy. All classes without children should derive from Leaf.

Class is an essential class for the Zeitgeist. It represents the class object of the specific object class. For example, the class Simple will have Class_Simple as its class object, which derives from Class. Through Class object, users can create the instance, access the base class, determine whether the class supports certain interfaces.

The whole hierarchy is managed by Core. Core provides users with methods to get an instance given the class name, to register new classes into the framework, to import a whole bundle of classes from an external library, to access the servers in Zeitgeist and to get the specific object given the path in the hierarchy.

There are some conventions in constructing the hierarchy:

  1. All class objects are put under /classes and organized by the module to which they belong. For example, the path to the Leaf class object is /classes/zeitgeist/Leaf.
  2. All servers are put under /sys/server. For instance, the path to LogServer is /sys/server/log.
  3. The simulation scene locates in /usr/scene. All scene nodes, which will be explained later, lives under /usr/scene.

Integrate A New Class into Zeitgeist

This topic is fundamental in the understanding of how the class object and the object hierarchy framework interact with each other. Let's say we have a simple class, which we define in simple.h:

class Simple
{
public:
  Simple();
  virtual ~Simple();
 
  void DoSomething();
  void PrintString(const std::string& s);
  void PrintInt(int i);
  void PrintFloat(float f);
  void PrintBool(bool b);
};

The first step you should do is fairly simple - just include a header file at the beginning:

#include <zeitgeist/leaf.h>

The second step is to make the Simple class inheriting Zeitgeist::Leaf class:

class Simple : public Zeitgeist::Leaf
{
  ...
}

The third step is simple too - add a MACRO right after the class definition:

DECLARE_CLASS(Simple);

These are all you have to add to the header file.

Component Communication

System components (server/agents/monitors) all communicate over TCP using the network protocol.

Where can I get the source code of the project?

SimSpark is hosted on SourceForge where you can download source code bundles or compiled binaries.

If you would like to get the latest bleeding edge version of the code, you can check out the source code via Subversion (SVN) or CVS.

In order to access a SVN repository, you must install a special piece of software called a subversion client. SVN clients are available for almost any operating system.

Personal tools