 
 unsigned long previous_time = 0;
 
-int target_vx = 0; // command-requested velocity vector components [-127..127]
-int target_vy = 0; // where vx=-127 is left, vx=127 is right, vx=0 is straight
-
-int actual_vx = 0; // actual velocity vector components [-127..127]
-int actual_vy = 0; // i.e., calculated from encoders
+float target_vx = 0; // command-requested velocity vector components [-1..1]
+float target_vy = 0; // where vx=-1 is left, vx=1 is right, vx=0 is straight
+
+float actual_vx = 0; // actual velocity vector components [-1..1]
+float actual_vy = 0; // e.g., calculated from encoders
+
+float slip_left = 0; // traction to slip-threshold ratio
+float slip_right = 0;
+
+bool bEnableSafetyStop = true;
 
 void setup() {
   Serial.begin(115200);

    // e.g.:
    if (value < 255) {
      if (code == 'x') {
        target_vx = -127 + (int) value;
      }
      if (code == 'y') {
        target_vy = -127 + (int) value;
      }
    }
    if (code == 'p') {
      Serial.print(" < ping! > ");
    }
    if (false && code == 'Q') { // silence on the input line - no connection? suggest an emergency stop...
      Serial.print(" < stop! > ");
      target_vx = 0;
      target_vy = 0;
    }
  }

  fake_car(); // mimic a car to create a feedback loop

  previous_time = millis();
}

float byte_to_norm(unsigned long value) { // convert integer in range 0..254 to floating point number in range -1..1
  float f = 0;

  if (value < 255) {
    f = (-127.0 +(float) value) / 127.0;
  }
  return f;
}

unsigned long norm_to_byte(float value) { // convert floating point number in range -1..1 to integer in range 0..254
  int ival = 127 + (int) round(127 * value);

  return (unsigned long) ((ival < 0) ? 0 : ((ival > 254) ? 254 : ival));
}

float eff_div_v(float v) { // motor efficiency divided by velocity fraction, i.e., v in [0..1]
  float edv = 0;

  if (v <= 0.5) {
