Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / DiWheelDrive / amiro_map.cpp @ bdac5bec

History | View | Annotate | Download (5.111 KB)

1
#include "amiro_map.hpp"
2

    
3
uint8_t AmiroMap::initialize(){
4

    
5
  // Clear old values in case the map is initialized again
6
  this->state.current = 0;
7
  this->state.next = 0;
8
  this->state.valid = false;
9
  this->nodeCount = 0;
10
  this->state.strategy = 0x1;
11

    
12
  // convert proto map to internal representation
13
  for (int i=0; i<MAX_NODES; i++){
14
    if(global->testmap[i][2] == 0xff && i != 0){
15
      break;
16
    } else if (global->testmap[i][2] == 0xff && i == 0) {
17
      this->state.valid = false;
18
      return 255;
19
    }
20

    
21
    //look for start node (default is Node 0)
22
    if (global->testmap[i][2] == 1 ) {
23
      this->state.current = i;
24
    }
25

    
26
    this->nodeList[i].id = i;
27
    this->nodeList[i].left = global->testmap[i][0];
28
    this->nodeList[i].right = global->testmap[i][1];
29
    this->nodeList[i].flag = global->testmap[i][2];
30
    this->nodeCount++;
31
  }
32
  this->state.next = this->nodeList[this->state.current].right;
33

    
34
  // TODO make validity check
35

    
36
  for (int j=0; j<nodeCount; j++) {
37
    this->nodeList[j].visited = 0;
38
    visitNode(j);
39
    for (int k = 0; k < nodeCount; k++) {
40
      if (this->nodeList[k].visited == 1) {
41
        this->nodeList[k].visited = 0;
42
      } else {
43
        this->state.valid = false;
44
        return k;
45
      }
46
    }
47
  }
48

    
49
  this->state.valid = true;
50
  return 42;
51
}
52

    
53
void AmiroMap::visitNode(uint8_t id){
54
  if (this->nodeList[id].visited == 1){
55
    return;
56
  }else{
57
    nodeList[id].visited = 1;
58
    visitNode(this->nodeList[id].left);
59
    visitNode(this->nodeList[id].right);
60
  }
61
}
62

    
63
uint8_t AmiroMap::update(uint16_t WL, uint16_t WR, LineFollowStrategy strategy) {
64
  // Called each time at the end of the user thread state machine
65
  // The bottom sensors will be checked for black ground which is interpreted as
66
  // filxpoint
67

    
68
  // set the strategy directly, actually there is no need to store that variable in the class
69
  // but we will go with it for now to initialize everything properly.
70
  uint8_t flag = 0;
71
  this->lfStrategy = strategy;
72
  // uint16_t WL = global->vcnl4020[constants::DiWheelDrive::PROX_WHEEL_LEFT].getProximityScaledWoOffset();
73
  // uint16_t WR = global->vcnl4020[constants::DiWheelDrive::PROX_WHEEL_RIGHT].getProximityScaledWoOffset();
74

    
75
  // Check the wheel sensors
76
  bool left = global->linePID.BThresh >= WL;
77
  bool right = global->linePID.BThresh >= WR;
78
  types::position currentPos = global->odometry.getPosition();
79

    
80
  if (left && right) {
81
    // TODO A dangerous case -> amiro could be lifted
82
    flag |= 255;
83
  }
84
  else if (left && !leftDetected) {
85
    // The sensor on the left side of the Amiro is driving on black
86
    // To prevent continous fixpoint detection a point needs to be marked as currently detected
87
    // and released.
88
    leftDetected = true;
89
    nodeList[state.next].pR.f_x = currentPos.f_x;
90
    nodeList[state.next].pR.f_y = currentPos.f_y;
91
    nodeList[state.next].pR.f_z = currentPos.f_z;
92
    nodeList[state.next].pR.x = currentPos.x;
93
    nodeList[state.next].pR.y = currentPos.y;
94
    nodeList[state.next].pR.z = currentPos.z;
95
    nodeList[state.next].visited |= 0x01;
96
    state.current = state.next;
97
    state.next = nodeList[state.current].right;
98
    state.strategy = 0x01;
99
    state.eLength = 0; // Reset length to get recalculated after fixpoint
100
    flag |= 0x1;
101
  }
102
  else if (right && !rightDetected) {
103
    // Same as left only for the right sensor.
104
    rightDetected = true;
105
    nodeList[state.next].pL.f_x = currentPos.f_x;
106
    nodeList[state.next].pL.f_y = currentPos.f_y;
107
    nodeList[state.next].pL.f_z = currentPos.f_z;
108
    nodeList[state.next].pL.x = currentPos.x;
109
    nodeList[state.next].pL.y = currentPos.y;
110
    nodeList[state.next].pL.z = currentPos.z;
111
    nodeList[state.next].visited |= 0x02;
112
    state.current = state.next;
113
    state.next = nodeList[state.current].left;
114
    state.strategy = 0x2;
115
    state.eLength = 0; // Reset length to get recalculated after fixpoint
116
    flag |= 0x2;
117
  }
118
  else if (!left && !right) {
119
    // in case the fixpoint is not detected anymore
120
    leftDetected = false;
121
    rightDetected = false;
122
    flag |= 0x4;
123
  }
124

    
125

    
126
  // update internal map_state
127
  // Update travel distance
128
  // check if the nodes of the specific strategy where visited
129
  if (state.strategy
130
      == (nodeList[state.current].visited & nodeList[state.next].visited)) {
131
    flag |= 0x8;
132
    // only update distance if both nodes were visited
133
    // Calculate estimated length of the edge
134
    if (state.strategy == 0x01) {
135
      // Amiro is driving on the right edge
136
      if (state.eLength == 0) {
137
        state.eLength = calculateDist(&nodeList[state.next].pR,
138
                                      &nodeList[state.current].pR);
139
      }
140
      state.dist = calculateDist(&nodeList[state.next].pR, &currentPos) * 100 /
141
                   state.eLength;
142
    } else {
143
      // Driving on the left edge
144
      if (state.eLength == 0) {
145
        state.eLength =
146
            calculateDist(&nodeList[state.next].pL, &nodeList[state.current].pL);
147
      }
148
      state.dist = calculateDist(&nodeList[state.next].pL, &currentPos) * 100 / state.eLength;
149

    
150
    }
151
  }
152
  return flag;
153
}
154

    
155
uint32_t AmiroMap::calculateDist(types::position *p1, types::position *p2) {
156
  return (uint32_t)  sqrt(pow(p2->x - p1->x, 2) +
157
              pow(p2->y - p1->y, 2));
158
}