Index: code/branches/network/src/core/ConfigValueContainer.cc
===================================================================
--- code/branches/network/src/core/ConfigValueContainer.cc	(revision 1443)
+++ code/branches/network/src/core/ConfigValueContainer.cc	(revision 1444)
@@ -139,5 +139,5 @@
     /**
         @brief Assigns a new value to the config-value of all objects and writes the change into the config-file.
-        @param input The new value
+        @param input The new value. If bIsVector_ then write "index value"
         @return True if the new value was successfully assigned
     */
Index: code/branches/network/src/core/ConfigValueIncludes.h
===================================================================
--- code/branches/network/src/core/ConfigValueIncludes.h	(revision 1443)
+++ code/branches/network/src/core/ConfigValueIncludes.h	(revision 1444)
@@ -121,16 +121,3 @@
     }
 
-/**
-    @brief Assigns the command, defined in the keybind-file, to the key-variable (or an empty string, if there is no entry in the file).
-    @param varname The name of the key-variable
-*/
-#define SetKeybind(keyname) \
-    orxonox::ConfigValueContainer* container##keyname = this->getIdentifier()->getConfigValueContainer(#keyname); \
-    if (!container##keyname) \
-    { \
-        container##keyname = new orxonox::ConfigValueContainer(CFT_Keybindings, this->getIdentifier(), #keyname, keyname = ""); \
-        this->getIdentifier()->addConfigValueContainer(#keyname, container##keyname); \
-    } \
-    container##keyname->getValue(&varname)
-
 #endif /* _ConfigValueIncludes_H__ */
Index: code/branches/network/src/core/CorePrereqs.h
===================================================================
--- code/branches/network/src/core/CorePrereqs.h	(revision 1443)
+++ code/branches/network/src/core/CorePrereqs.h	(revision 1444)
@@ -156,4 +156,6 @@
   // input
   //class GUIInputHandler;
+  class Calibrator;
+  class CalibratorCallback;
   class InputBuffer;
   class InputBufferListener;
Index: code/branches/network/src/core/InputInterfaces.h
===================================================================
--- code/branches/network/src/core/InputInterfaces.h	(revision 1443)
+++ code/branches/network/src/core/InputInterfaces.h	(revision 1444)
@@ -313,5 +313,5 @@
     virtual void joyStickButtonReleased(int joyStickID, int button) = 0;
     virtual void joyStickButtonHeld    (int joyStickID, int button) = 0;
-    virtual void joyStickAxisMoved     (int joyStickID, int axis, int value) = 0;
+    virtual void joyStickAxisMoved     (int joyStickID, int axis, float value) = 0;
     //virtual bool joyStickVector3Moved  (int joyStickID, int index /*, fill list*/) {return true;}
     //virtual void tickJoyStick          (float dt) { }
Index: code/branches/network/src/core/InputManager.cc
===================================================================
--- code/branches/network/src/core/InputManager.cc	(revision 1443)
+++ code/branches/network/src/core/InputManager.cc	(revision 1444)
@@ -34,5 +34,7 @@
 
 #include "InputManager.h"
+#include "util/Convert.h"
 #include "CoreIncludes.h"
+#include "ConfigValueIncludes.h"
 #include "Debug.h"
 #include "InputBuffer.h"
@@ -45,4 +47,5 @@
   ConsoleCommandShortcut(InputManager, keyBind, AccessLevel::User);
   ConsoleCommandShortcut(InputManager, storeKeyStroke, AccessLevel::Offline);
+  ConsoleCommandShortcut(InputManager, calibrate, AccessLevel::User);
 
   // ###############################
@@ -58,5 +61,5 @@
       inputSystem_(0), keyboard_(0), mouse_(0),
       joySticksSize_(0),
-      keyBinder_(0), buffer_(0), keyDetector_(0),
+      keyBinder_(0), keyDetector_(0), buffer_(0), calibratorCallback_(0),
       state_(IS_UNINIT), stateRequest_(IS_UNINIT), savedState_(IS_UNINIT),
       keyboardModifiers_(0)
@@ -143,4 +146,27 @@
       state_ = IS_NONE;
       CCOUT(ORX_DEBUG) << "Initialising OIS components done." << std::endl;
+
+      // InputManager holds the input buffer --> create one and add it.
+      buffer_ = new InputBuffer();
+      addKeyHandler(buffer_, "buffer");
+
+      keyBinder_ = new KeyBinder();
+      keyBinder_->loadBindings();
+      addKeyHandler(keyBinder_, "keybinder");
+      addMouseHandler(keyBinder_, "keybinder");
+      addJoyStickHandler(keyBinder_, "keybinder");
+
+      keyDetector_ = new KeyDetector();
+      keyDetector_->loadBindings();
+      addKeyHandler(keyDetector_, "keydetector");
+      addMouseHandler(keyDetector_, "keydetector");
+      addJoyStickHandler(keyDetector_, "keydetector");
+
+      calibratorCallback_ = new CalibratorCallback();
+      addKeyHandler(calibratorCallback_, "calibratorcallback");
+
+      setConfigValues();
+
+      CCOUT(ORX_DEBUG) << "Initialising complete." << std::endl;
     }
     else
@@ -148,22 +174,4 @@
       CCOUT(ORX_WARNING) << "Warning: OIS compoments already initialised, skipping" << std::endl;
     }
-
-    // InputManager holds the input buffer --> create one and add it.
-    buffer_ = new InputBuffer();
-    addKeyHandler(buffer_, "buffer");
-
-    keyBinder_ = new KeyBinder();
-    keyBinder_->loadBindings();
-    addKeyHandler(keyBinder_, "keybinder");
-    addMouseHandler(keyBinder_, "keybinder");
-    addJoyStickHandler(keyBinder_, "keybinder");
-
-    keyDetector_ = new KeyDetector();
-    keyDetector_->loadBindings();
-    addKeyHandler(keyDetector_, "keydetector");
-    addMouseHandler(keyDetector_, "keydetector");
-    addJoyStickHandler(keyDetector_, "keydetector");
-
-    CCOUT(ORX_DEBUG) << "Initialising complete." << std::endl;
     return true;
   }
@@ -285,5 +293,70 @@
     povStates_.resize(joySticksSize_);
     sliderStates_.resize(joySticksSize_);
+    joySticksCalibration_.resize(joySticksSize_);
+    for (unsigned int iJoyStick = 0; iJoyStick < joySticksSize_; iJoyStick++)
+    {
+      // reset the calibration with default values
+      for (unsigned int i = 0; i < 24; i++)
+      {
+        joySticksCalibration_[iJoyStick].negativeCoeff[i] = 1.0f/32767.0f;
+        joySticksCalibration_[iJoyStick].positiveCoeff[i] = 1.0f/32768.0f;
+        joySticksCalibration_[iJoyStick].zeroStates[i] = 0;
+      }
+    }
     return success;
+  }
+
+  /**
+    @brief Sets the configurable values. Use keybindings.ini as file..
+  */
+  void InputManager::setConfigValues()
+  {
+    if (joySticksSize_)
+    {
+      std::vector<MultiTypeMath> coeffPos;
+      std::vector<MultiTypeMath> coeffNeg;
+      std::vector<MultiTypeMath> zero;
+      coeffPos.resize(24);
+      coeffNeg.resize(24);
+      zero.resize(24);
+      for (unsigned int i = 0; i < 24; i++)
+      {
+        coeffPos[i] =  1.0f/32767.0f;
+        coeffNeg[i] =  1.0f/32768.0f;
+        zero[i]     =  0;
+      }
+
+      ConfigValueContainer* cont = getIdentifier()->getConfigValueContainer("CoeffPos");
+      if (!cont)
+      {
+          cont = new ConfigValueContainer(CFT_Keybindings, getIdentifier(), "CoeffPos", coeffPos);
+          getIdentifier()->addConfigValueContainer("CoeffPos", cont);
+      }
+      cont->getValue(&coeffPos);
+
+      cont = getIdentifier()->getConfigValueContainer("CoeffNeg");
+      if (!cont)
+      {
+          cont = new ConfigValueContainer(CFT_Keybindings, getIdentifier(), "CoeffNeg", coeffNeg);
+          getIdentifier()->addConfigValueContainer("CoeffNeg", cont);
+      }
+      cont->getValue(&coeffNeg);
+
+      cont = getIdentifier()->getConfigValueContainer("Zero");
+      if (!cont)
+      {
+          cont = new ConfigValueContainer(CFT_Keybindings, getIdentifier(), "Zero", zero);
+          getIdentifier()->addConfigValueContainer("Zero", cont);
+      }
+      cont->getValue(&zero);
+
+      // copy values to our own variables
+      for (unsigned int i = 0; i < 24; i++)
+      {
+        joySticksCalibration_[0].positiveCoeff[i] = coeffPos[i];
+        joySticksCalibration_[0].negativeCoeff[i] = coeffNeg[i];
+        joySticksCalibration_[0].zeroStates[i]    = zero[i];
+      }
+    }
   }
 
@@ -305,4 +378,7 @@
       if (keyDetector_)
         delete keyDetector_;
+
+      if (calibratorCallback_)
+        delete calibratorCallback_;
 
       keyHandlers_.clear();
@@ -313,4 +389,6 @@
       _destroyMouse();
       _destroyJoySticks();
+
+      activeHandlers_.clear();
 
       // inputSystem_ can never be 0, or else the code is mistaken
@@ -367,4 +445,7 @@
       activeJoyStickHandlers_.clear();
       joyStickButtonsDown_.clear();
+      povStates_.clear();
+      sliderStates_.clear();
+      joySticksCalibration_.clear();
     }
     CCOUT(ORX_DEBUG) << "Joy sticks destroyed." << std::endl;
@@ -423,59 +504,109 @@
     if (state_ != stateRequest_)
     {
-      if (stateRequest_ != IS_CUSTOM)
-      {
-        if (stateRequest_ != IS_DETECT)
+      InputState sr = stateRequest_;
+      switch (sr)
+      {
+      case IS_NORMAL:
+        activeKeyHandlers_.clear();
+        activeMouseHandlers_.clear();
+        for (unsigned int i = 0; i < joySticksSize_; i++)
+          activeJoyStickHandlers_[i].clear();
+
+        // normal play mode
+        // note: we assume that the handlers exist since otherwise, something's wrong anyway.
+        enableKeyHandler("keybinder");
+        enableMouseHandler("keybinder");
+        enableJoyStickHandler("keybinder", 0);
+        stateRequest_ = IS_NORMAL;
+        state_ = IS_NORMAL;
+        break;
+
+      case IS_GUI:
+        state_ = IS_GUI;
+        break;
+
+      case IS_CONSOLE:
+        activeKeyHandlers_.clear();
+        activeMouseHandlers_.clear();
+        for (unsigned int i = 0; i < joySticksSize_; i++)
+          activeJoyStickHandlers_[i].clear();
+
+        enableMouseHandler("keybinder");
+        enableJoyStickHandler("keybinder", 0);
+        enableKeyHandler("buffer");
+        stateRequest_ = IS_CONSOLE;
+        state_ = IS_CONSOLE;
+        break;
+
+      case IS_DETECT:
+        savedState_ = state_;
+        _saveState();
+
+        activeKeyHandlers_.clear();
+        activeMouseHandlers_.clear();
+        for (unsigned int i = 0; i < joySticksSize_; i++)
+          activeJoyStickHandlers_[i].clear();
+
+        enableKeyHandler("keydetector");
+        enableMouseHandler("keydetector");
+        enableJoyStickHandler("keydetector", 0);
+
+        stateRequest_ = IS_DETECT;
+        state_ = IS_DETECT;
+        break;
+
+      case IS_NODETECT:
+        _restoreState();
+        state_ = IS_NODETECT;
+        stateRequest_ = savedState_;
+        break;
+
+      case IS_CALIBRATE:
+        if (joySticksSize_)
         {
+          savedState_ = _getSingleton().state_;
+          for (unsigned int i = 0; i < 24; i++)
+          {
+            marginalsMax_[i] = INT_MIN;
+            marginalsMin_[i] = INT_MAX;
+          }
+          COUT(3) << "Move all joy stick axes in all directions a few times. "
+            << "Then put all axes in zero state and hit enter." << std::endl;
+
+          savedState_ = state_;
+          _saveState();
+
           activeKeyHandlers_.clear();
           activeMouseHandlers_.clear();
           for (unsigned int i = 0; i < joySticksSize_; i++)
             activeJoyStickHandlers_[i].clear();
+
+          enableKeyHandler("calibratorcallback");
+          stateRequest_ = IS_CALIBRATE;
+          state_ = IS_CALIBRATE;
         }
-
-        switch (stateRequest_)
+        else
         {
-        case IS_NORMAL:
-          // normal play mode
-          // note: we assume that the handlers exist since otherwise, something's wrong anyway.
-          enableKeyHandler("keybinder");
-          enableMouseHandler("keybinder");
-          enableJoyStickHandler("keybinder", 0);
-          break;
-
-        case IS_GUI:
-          break;
-
-        case IS_CONSOLE:
-          enableMouseHandler("keybinder");
-          enableJoyStickHandler("keybinder", 0);
-          enableKeyHandler("buffer");
-          break;
-
-        case IS_DETECT:
-          savedState_ = state_;
-          _saveState();
-
-          activeKeyHandlers_.clear();
-          activeMouseHandlers_.clear();
-          for (unsigned int i = 0; i < joySticksSize_; i++)
-            activeJoyStickHandlers_[i].clear();
-
-          enableKeyHandler("keydetector");
-          enableMouseHandler("keydetector");
-          enableJoyStickHandler("keydetector", 0);
-          break;
-
-        case IS_NODETECT:
-          _restoreState();
-          break;
-
-        default:
-          break;
+          COUT(3) << "Connot calibrate, no joy stick found!" << std::endl;
+          stateRequest_ = state_;
         }
-
-        if (stateRequest_ == IS_NODETECT)
-          state_ = savedState_;
-        else
-          state_ = stateRequest_;
+        break;
+
+      case IS_NOCALIBRATE:
+        _completeCalibration();
+        _restoreState();
+        state_ = IS_NOCALIBRATE;
+        stateRequest_ = savedState_;
+        break;
+
+      case IS_NONE:
+        activeKeyHandlers_.clear();
+        activeMouseHandlers_.clear();
+        for (unsigned int i = 0; i < joySticksSize_; i++)
+          activeJoyStickHandlers_[i].clear();
+        state_ = IS_NONE;
+
+      default:
+        break;
       }
     }
@@ -489,33 +620,82 @@
       joySticks_[i]->capture();
 
-
-    // call all the handlers for the held key events
-    for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
-      for (unsigned int iHandler = 0; iHandler < activeKeyHandlers_.size(); iHandler++)
-        activeKeyHandlers_[iHandler]->keyHeld(KeyEvent(keysDown_[iKey], keyboardModifiers_));
-
-    // call all the handlers for the held mouse button events
-    for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
-      for (unsigned int iHandler = 0; iHandler < activeMouseHandlers_.size(); iHandler++)
-        activeMouseHandlers_[iHandler]->mouseButtonHeld(mouseButtonsDown_[iButton]);
-
-    // call all the handlers for the held joy stick button events
-    for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
-      for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
-        for (unsigned int iHandler = 0; iHandler  < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-          activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
-
+    if (state_ != IS_CALIBRATE)
+    {
+      // call all the handlers for the held key events
+      for (unsigned int iKey = 0; iKey < keysDown_.size(); iKey++)
+        for (unsigned int iHandler = 0; iHandler < activeKeyHandlers_.size(); iHandler++)
+          activeKeyHandlers_[iHandler]->keyHeld(KeyEvent(keysDown_[iKey], keyboardModifiers_));
+
+      // call all the handlers for the held mouse button events
+      for (unsigned int iButton = 0; iButton < mouseButtonsDown_.size(); iButton++)
+        for (unsigned int iHandler = 0; iHandler < activeMouseHandlers_.size(); iHandler++)
+          activeMouseHandlers_[iHandler]->mouseButtonHeld(mouseButtonsDown_[iButton]);
+
+      // call all the handlers for the held joy stick button events
+      for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
+        for (unsigned int iButton   = 0; iButton   < joyStickButtonsDown_[iJoyStick].size(); iButton++)
+          for (unsigned int iHandler = 0; iHandler  < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
+            activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickButtonHeld(iJoyStick, joyStickButtonsDown_[iJoyStick][iButton]);
+    }
 
     // call the ticks for the handlers (need to be treated specially)
     for (unsigned int iHandler = 0; iHandler < activeHandlers_.size(); iHandler++)
       activeHandlers_[iHandler].first->tickInput(dt, activeHandlers_[iHandler].second);
-
-    /*for (unsigned int iHandler = 0; iHandler < activeKeyHandlers_.size(); iHandler++)
-      activeKeyHandlers_[iHandler]->tickKey(dt);
-    for (unsigned int iHandler = 0; iHandler < activeMouseHandlers_.size(); iHandler++)
-      activeMouseHandlers_[iHandler]->tickMouse(dt);
-    for (unsigned int iJoyStick  = 0; iJoyStick < joySticksSize_; iJoyStick++)
-      for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-        activeJoyStickHandlers_[iJoyStick][iHandler]->tickJoyStick(dt);*/
+  }
+
+  void InputManager::_completeCalibration()
+  {
+    for (unsigned int i = 0; i < 24; i++)
+    {
+      // positive coefficient
+      if (marginalsMax_[i] == INT_MIN)
+        marginalsMax_[i] =  32767;
+      // coefficients
+      if (marginalsMax_[i] - joySticksCalibration_[0].zeroStates[i])
+        joySticksCalibration_[0].positiveCoeff[i] =  1.0f/(marginalsMax_[i] - joySticksCalibration_[0].zeroStates[i]);
+      else
+        joySticksCalibration_[0].positiveCoeff[i] =  1.0f;
+
+      // config value
+      ConfigValueContainer* cont = getIdentifier()->getConfigValueContainer("CoeffPos");
+      assert(cont);
+      cont->set(getConvertedValue<int, std::string>(i) + " "
+        + getConvertedValue<float, std::string>(joySticksCalibration_[0].positiveCoeff[i]));
+
+      // negative coefficient
+      if (marginalsMin_[i] == INT_MAX)
+        marginalsMin_[i] = -32768;
+      // coefficients
+      if (marginalsMin_[i] - joySticksCalibration_[0].zeroStates[i])
+        joySticksCalibration_[0].negativeCoeff[i] = -1.0f/(marginalsMin_[i] - joySticksCalibration_[0].zeroStates[i]);
+      else
+        joySticksCalibration_[0].negativeCoeff[i] =  1.0f;
+      // config value
+      cont = getIdentifier()->getConfigValueContainer("CoeffNeg");
+      assert(cont);
+      cont->set(getConvertedValue<int, std::string>(i) + " "
+        + getConvertedValue<float, std::string>(joySticksCalibration_[0].negativeCoeff[i]));
+
+      // zero states
+      if (i < 8)
+      {
+        if (!(i & 1))
+          joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mSliders[i/2].abX;
+        else
+          joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mSliders[i/2].abY;
+      }
+      else
+      {
+        if (i - 8 < joySticks_[0]->getJoyStickState().mAxes.size())
+          joySticksCalibration_[0].zeroStates[i] = joySticks_[0]->getJoyStickState().mAxes[i - 8].abs;
+        else
+          joySticksCalibration_[0].zeroStates[i] = 0;
+      }
+      // config value
+      cont = getIdentifier()->getConfigValueContainer("Zero");
+      assert(cont);
+      cont->set(getConvertedValue<int, std::string>(i) + " "
+        + getConvertedValue<int, std::string>(joySticksCalibration_[0].zeroStates[i]));
+    }
   }
 
@@ -652,5 +832,5 @@
   // ###### Joy Stick Events ######
 
-  bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
+  inline unsigned int InputManager::_getJoystick(const OIS::JoyStickEvent& arg)
   {
     // use the device to identify which one called the method
@@ -658,5 +838,18 @@
     unsigned int iJoyStick = 0;
     while (joySticks_[iJoyStick] != joyStick)
+    {
       iJoyStick++;
+      if (iJoyStick == joySticksSize_)
+      {
+        CCOUT(3) << "Unknown joystick fired an event. This means there is a bug somewhere! Aborting." << std::endl;
+        abort();
+      }
+    }
+    return iJoyStick;
+  }
+
+  bool InputManager::buttonPressed(const OIS::JoyStickEvent &arg, int button)
+  {
+    unsigned int iJoyStick = _getJoystick(arg);
 
     // check whether the button already is in the list (can happen when focus was lost)
@@ -676,9 +869,5 @@
   bool InputManager::buttonReleased(const OIS::JoyStickEvent &arg, int button)
   {
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+    unsigned int iJoyStick = _getJoystick(arg);
 
     // remove the button from the joyStickButtonsDown_ list
@@ -699,17 +888,35 @@
   }
 
+  void InputManager::_fireAxis(unsigned int iJoyStick, int axis, int value)
+  {
+    if (state_ == IS_CALIBRATE)
+    {
+      if (value > marginalsMax_[axis])
+        marginalsMax_[axis] = value;
+      if (value < marginalsMin_[axis])
+        marginalsMin_[axis] = value;
+    }
+    else
+    {
+      float fValue = value - joySticksCalibration_[iJoyStick].zeroStates[axis];
+      if (fValue > 0.0f)
+        fValue *= joySticksCalibration_[iJoyStick].positiveCoeff[axis];
+      else
+        fValue *= joySticksCalibration_[iJoyStick].negativeCoeff[axis];
+
+      for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
+        activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, axis, fValue);
+    }    
+  }
+
   bool InputManager::axisMoved(const OIS::JoyStickEvent &arg, int axis)
   {
     //if (arg.state.mAxes[axis].abs > 10000 || arg.state.mAxes[axis].abs < -10000)
     //{ CCOUT(3) << "axis " << axis << " moved" << arg.state.mAxes[axis].abs << std::endl;}
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+
+    unsigned int iJoyStick = _getJoystick(arg);
 
     // keep in mind that the first 8 axes are reserved for the sliders
-    for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-      activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, axis + 8, arg.state.mAxes[axis].abs);
+    _fireAxis(iJoyStick, axis + 8, arg.state.mAxes[axis].abs);
 
     return true;
@@ -721,24 +928,11 @@
     //{CCOUT(3) << "slider " << id << " moved" << arg.state.mSliders[id].abX << std::endl;}
     //CCOUT(3) << arg.state.mSliders[id].abX << "\t |" << arg.state.mSliders[id].abY << std::endl;
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+
+    unsigned int iJoyStick = _getJoystick(arg);
 
     if (sliderStates_[iJoyStick].sliderStates[id].x != arg.state.mSliders[id].abX)
-    {
-      // slider X axis changed
-      sliderStates_[iJoyStick].sliderStates[id].x = arg.state.mSliders[id].abX;
-      for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-        activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, id * 2, arg.state.mSliders[id].abX);
-    }
+      _fireAxis(iJoyStick, id * 2, arg.state.mSliders[id].abX);
     else if (sliderStates_[iJoyStick].sliderStates[id].y != arg.state.mSliders[id].abY)
-    {
-      // slider Y axis changed
-      sliderStates_[iJoyStick].sliderStates[id].y = arg.state.mSliders[id].abY;
-      for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
-        activeJoyStickHandlers_[iJoyStick][iHandler]->joyStickAxisMoved(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
-    }
+      _fireAxis(iJoyStick, id * 2 + 1, arg.state.mSliders[id].abY);
 
     return true;
@@ -747,9 +941,5 @@
   bool InputManager::povMoved(const OIS::JoyStickEvent &arg, int id)
   {
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+    unsigned int iJoyStick = _getJoystick(arg);
 
     // translate the POV into 8 simple buttons
@@ -765,4 +955,5 @@
     
     povStates_[iJoyStick].povStates[id] = arg.state.mPOV[id].direction;
+
     int currentState = povStates_[iJoyStick][id];
     if (currentState & OIS::Pov::North)
@@ -780,9 +971,5 @@
   /*bool InputManager::vector3Moved(const OIS::JoyStickEvent &arg, int id)
   {
-    // use the device to identify which one called the method
-    OIS::JoyStick* joyStick = (OIS::JoyStick*)arg.device;
-    unsigned int iJoyStick = 0;
-    while (joySticks_[iJoyStick] != joyStick)
-      iJoyStick++;
+    unsigned int iJoyStick = _getJoystick(arg);
 
     for (unsigned int iHandler = 0; iHandler < activeJoyStickHandlers_[iJoyStick].size(); iHandler++)
@@ -943,4 +1130,10 @@
     bindingCommmandString_s = command;
     setInputState(IS_DETECT);
+    COUT(3) << "Press any button/key or move a mouse/joystick axis" << std::endl;
+  }
+
+  void InputManager::calibrate()
+  {
+    _getSingleton().setInputState(IS_CALIBRATE);
   }
 
Index: code/branches/network/src/core/InputManager.h
===================================================================
--- code/branches/network/src/core/InputManager.h	(revision 1443)
+++ code/branches/network/src/core/InputManager.h	(revision 1444)
@@ -76,4 +76,11 @@
     std::vector<std::vector<JoyStickHandler*> > activeJoyStickHandlers_;
     std::vector<std::pair<InputTickable*, HandlerState> > activeHandlers_;
+  };
+
+  struct JoyStickCalibration
+  {
+    int zeroStates[24];
+    float positiveCoeff[24];
+    float negativeCoeff[24];
   };
 
@@ -98,6 +105,11 @@
       IS_DETECT,    //!< All the input additionally goes to the KeyDetector
       IS_NODETECT,  //!< remove KeyDetector
+      IS_NOCALIBRATE,
+      IS_CALIBRATE,
       IS_CUSTOM     //!< Any possible configuration.
     };
+
+  public: // member functions
+    void setConfigValues();
 
   public: // static functions
@@ -129,4 +141,6 @@
     static void keyBind(const std::string& command);
 
+    static void calibrate();
+
     static bool addKeyHandler                 (KeyHandler* handler, const std::string& name);
     static bool removeKeyHandler              (const std::string& name);
@@ -171,4 +185,9 @@
     void _saveState();
     void _restoreState();
+
+    void _completeCalibration();
+
+    void _fireAxis(unsigned int iJoyStick, int axis, int value);
+    unsigned int _getJoystick(const OIS::JoyStickEvent& arg);
 
     void tick(float dt);
@@ -200,10 +219,18 @@
     KeyDetector*                                keyDetector_;     //!< KeyDetector instance
     InputBuffer*                                buffer_;          //!< InputBuffer instance
+    CalibratorCallback*                         calibratorCallback_;
 
     InputState state_;
     InputState stateRequest_;
+    InputState savedState_;
     unsigned int keyboardModifiers_;
-    InputState savedState_;
     StoredState savedHandlers_;
+
+    // joystick calibration
+    //std::vector<int> marginalsMaxConfig_;
+    //std::vector<int> marginalsMinConfig_;
+    int marginalsMax_[24];
+    int marginalsMin_[24];
+    bool bCalibrated_;
 
     //! Keeps track of the joy stick POV states
@@ -211,4 +238,5 @@
     //! Keeps track of the possibly two slider axes
     std::vector<SliderStates>                   sliderStates_;
+    std::vector<JoyStickCalibration>            joySticksCalibration_;
 
     std::map<std::string, KeyHandler*>          keyHandlers_;
Index: code/branches/network/src/core/KeyBinder.cc
===================================================================
--- code/branches/network/src/core/KeyBinder.cc	(revision 1443)
+++ code/branches/network/src/core/KeyBinder.cc	(revision 1444)
@@ -34,4 +34,5 @@
 #include "KeyBinder.h"
 #include <fstream>
+#include <limits.h>
 #include "util/Convert.h"
 #include "util/SubString.h"
@@ -42,4 +43,6 @@
 #include "CommandExecutor.h"
 #include "Executor.h"
+// TODO: only needed by the CalibratorCallback class; move to new file
+#include "InputManager.h"
 
 namespace orxonox
@@ -805,5 +808,5 @@
   }
 
-  void KeyBinder::joyStickAxisMoved(int joyStickID, int axis, int value)
+  void KeyBinder::joyStickAxisMoved(int joyStickID, int axis, float value)
   {
     // TODO: Use proper calibration values instead of generally 16-bit integer
@@ -814,8 +817,8 @@
       //{ CCOUT(3) << halfAxes_[i].name_ << std::endl; }
 
-      halfAxes_[i].absVal_ = ((float)value)/0x8000;
-      halfAxes_[i].relVal_ = ((float)value)/0x8000;
+      halfAxes_[i].absVal_ = value;
+      halfAxes_[i].relVal_ = value;
       halfAxes_[i].hasChanged_ = true;
-      if (halfAxes_[i + 1].absVal_ > 0)
+      if (halfAxes_[i + 1].absVal_ > 0.0f)
       {
         halfAxes_[i + 1].absVal_ = -0.0f;
@@ -829,8 +832,8 @@
       //{ CCOUT(3) << halfAxes_[i + 1].name_ << std::endl; }
 
-      halfAxes_[i + 1].absVal_ = -((float)value)/0x8000;
-      halfAxes_[i + 1].relVal_ = -((float)value)/0x8000;
+      halfAxes_[i + 1].absVal_ = -value;
+      halfAxes_[i + 1].relVal_ = -value;
       halfAxes_[i + 1].hasChanged_ = true;
-      if (halfAxes_[i].absVal_ > 0)
+      if (halfAxes_[i].absVal_ > 0.0f)
       {
         halfAxes_[i].absVal_ = -0.0f;
@@ -879,4 +882,16 @@
     button.nCommands_[KeybindMode::OnPress] = 1;
   }
-  
+
+
+  // ###############################
+  // ##### CalibratorCallback  #####
+  // ###############################
+
+  void CalibratorCallback::keyPressed(const orxonox::KeyEvent &evt)
+  {
+    if (evt.key == KeyCode::Return)
+    {
+      InputManager::setInputState(InputManager::IS_NOCALIBRATE);
+    }
+  }
 }
Index: code/branches/network/src/core/KeyBinder.h
===================================================================
--- code/branches/network/src/core/KeyBinder.h	(revision 1443)
+++ code/branches/network/src/core/KeyBinder.h	(revision 1444)
@@ -165,5 +165,5 @@
     void joyStickButtonReleased(int joyStickID, int button);
     void joyStickButtonHeld    (int joyStickID, int button);
-    void joyStickAxisMoved     (int joyStickID, int axis, int value);
+    void joyStickAxisMoved     (int joyStickID, int axis, float value);
 
   protected: // variables
@@ -192,5 +192,5 @@
     *  0 -  3: Mouse x and y
     *  4 -  7: empty
-    *  8 - 23: joy stick (slider) axes 1 to 8
+    *  8 - 23: joy stick slider axes 1 to 8
     * 24 - 55: joy stick axes 1 - 16
     */
@@ -237,4 +237,18 @@
     void readTrigger(Button& button);
   };
+
+  class _CoreExport CalibratorCallback : public KeyHandler
+  {
+  public:
+    CalibratorCallback() {}
+    ~CalibratorCallback() {}
+
+  private:
+    void keyPressed (const KeyEvent& evt);
+    void keyReleased(const KeyEvent& evt) {}
+    void keyHeld    (const KeyEvent& evt) {}
+
+    void tickInput(float dt, const HandlerState &state) { }
+  };
 }
 
Index: code/branches/network/src/orxonox/hud/Navigation.cc
===================================================================
--- code/branches/network/src/orxonox/hud/Navigation.cc	(revision 1443)
+++ code/branches/network/src/orxonox/hud/Navigation.cc	(revision 1444)
@@ -125,5 +125,5 @@
                 // top right quadrant
                 if(-phiNav<phiUpperCorner){
-                    COUT(3) << "arrow up\n";
+                    //COUT(3) << "arrow up\n";
                     navMarker_->setPosition(-tan(phiNav)*windowH_/2+windowW_/2, 0);
                     navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
@@ -132,5 +132,5 @@
                 }
                 else {
-                    COUT(3) << "arrow right\n";
+                    //COUT(3) << "arrow right\n";
                     navMarker_->setPosition(windowW_-16, tan((3.14-2*phiNav)/2)*windowW_/2+windowH_/2);
                     navMarker_->setUV(0.5, 0.5, 1.0, 1.0);
@@ -142,5 +142,5 @@
                 // bottom right quadrant
                 if(phiNav<phiUpperCorner) {
-                    COUT(3) << "arrow down\n";
+                    //COUT(3) << "arrow down\n";
                     navMarker_->setPosition(tan(phiNav)*windowH_/2+windowW_/2, windowH_-16);
                     navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
@@ -149,5 +149,5 @@
                 }
                 else {
-                    COUT(3) << "arrow right\n";
+                    //COUT(3) << "arrow right\n";
                     navMarker_->setPosition(windowW_-16, tan((3.14-2*phiNav)/2)*windowW_/2+windowH_/2);
                     navMarker_->setUV(0.5, 0.5, 1.0, 1.0);
@@ -159,5 +159,5 @@
                 // top left quadrant
                 if(phiNav<phiUpperCorner){
-                    COUT(3) << "arrow up\n";
+                    //COUT(3) << "arrow up\n";
                     navMarker_->setPosition(-tan(phiNav)*windowH_/2+windowW_/2, 0);
                     navMarker_->setUV(0.5, 0.0, 1.0, 0.5);
@@ -166,5 +166,5 @@
                 }
                 else {
-                    COUT(3) << "arrow left\n";
+                    //COUT(3) << "arrow left\n";
                     navMarker_->setPosition(0, -tan((3.14-2*phiNav)/2)*windowW_/2+windowH_/2);
                     navMarker_->setUV(0.0, 0.0, 0.5, 0.5);
@@ -176,5 +176,5 @@
                 // bottom left quadrant
                 if(phiNav>-phiUpperCorner) {
-                    COUT(3) << "arrow down\n";
+                    //COUT(3) << "arrow down\n";
                     navMarker_->setPosition(tan(phiNav)*windowH_/2+windowW_/2, windowH_-16);
                     navMarker_->setUV(0.0, 0.5, 0.5, 1.0);
@@ -183,5 +183,5 @@
                 }
                 else {
-                    COUT(3) << "arrow left\n";
+                    //COUT(3) << "arrow left\n";
                     navMarker_->setPosition(0, -tan((3.14-2*phiNav)/2)*windowW_/2+windowH_/2);
                     navMarker_->setUV(0.0, 0.0, 0.5, 0.5);
