map-line

amperka/octoliner/map-line

Converts the IR sensors data into a line tracking value that determines the Octoliner board position relative to the line.
map-line
@/map-line
Converts the IR sensors data into a line tracking value that determines the Octoliner board position relative to the line.
CH0number
CH1number
CH2number
CH3number
CH4number
CH5number
CH6number
CH7number
map-line
CH0
CH1
CH2
CH3
CH4
CH5
CH6
CH7
LINE
LINEnumber
Last calculated line tracking value in the range [-1,1]. The 0 value shows that line is at the center position relative to the sensors. The -1 value corresponds to the extreme left position while the 1 to the extreme right.
To use the node in your project you should have the amperka/octoliner library installed. Use the “File → Add Library” menu item in XOD IDE if you don’t have it yet. See Using libraries for more info.

C++ implementation

struct State {
  float line;
  const uint8_t ADCResolution = 10;
};

// clang-format off
{{ GENERATED_CODE }}
// clang-format on

void evaluate(Context ctx) {
  auto state = getState(ctx);

  int16_t min = 32767;
  int16_t max = 0;

  int16_t binaryLine[8] =
  { getValue<input_CH0>(ctx) * pow(2,state->ADCResolution),
    getValue<input_CH1>(ctx) * pow(2,state->ADCResolution),
    getValue<input_CH2>(ctx) * pow(2,state->ADCResolution),
    getValue<input_CH3>(ctx) * pow(2,state->ADCResolution),
    getValue<input_CH4>(ctx) * pow(2,state->ADCResolution),
    getValue<input_CH5>(ctx) * pow(2,state->ADCResolution),
    getValue<input_CH6>(ctx) * pow(2,state->ADCResolution),
    getValue<input_CH7>(ctx) * pow(2,state->ADCResolution)};

  uint8_t pattern = 0b00000000;

  for (uint8_t i = 0; i < 8; i++) {
    if (binaryLine[i] < min)
      min = binaryLine[i];
    if (binaryLine[i] > max)
      max = binaryLine[i];
  }

  // calculate border level
  int16_t threshold = min + (max - min) / 2;
  // create bit pattern
  for (uint8_t i = 0; i < 8; i++) {
    pattern = (pattern << 1) + ((binaryLine[i] < threshold) ? 0 : 1);
  }

  switch (pattern) {
    case 0b00011000:
      state->line = 0;
      break;
    case 0b00010000:
      state->line = 0.25;
      break;
    case 0b00111000:
      state->line = 0.25;
      break;
    case 0b00001000:
      state->line = -0.25;
      break;
    case 0b00011100:
      state->line = -0.25;
      break;
    case 0b00110000:
      state->line = 0.375;
      break;
    case 0b00001100:
      state->line = -0.375;
      break;
    case 0b00100000:
      state->line = 0.5;
      break;
    case 0b01110000:
      state->line = 0.5;
      break;
    case 0b00000100:
      state->line = -0.5;
      break;
    case 0b00001110:
      state->line = -0.5;
      break;
    case 0b01100000:
      state->line = 0.625;
      break;
    case 0b11100000:
      state->line = 0.625;
      break;
    case 0b00000110:
      state->line = -0.625;
      break;
    case 0b00000111:
      state->line = -0.625;
      break;
    case 0b01000000:
      state->line = 0.75;
      break;
    case 0b11110000:
      state->line = 0.75;
      break;
    case 0b00000010:
      state->line = -0.75;
      break;
    case 0b00001111:
      state->line = -0.75;
      break;
    case 0b11000000:
      state->line = 0.875;
      break;
    case 0b00000011:
      state->line = -0.875;
      break;
    case 0b10000000:
      state->line = 1.0;
      break;
    case 0b00000001:
      state->line = -1.0;
      break;

    default:
      break;  // for other patterns return previous value
  }

  emitValue<output_LINE>(ctx, state->line);
}