Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / PowerManagement / userthread.cpp @ 58fe0e0b

History | View | Annotate | Download (4.767 KB)

1
#include "userthread.h"
2

    
3
#include "global.hpp"
4
#include <array>
5

    
6
using namespace amiro;
7

    
8
extern Global global;
9

    
10
uint16_t touch;
11
std::array<uint16_t, 8> proximity;
12
std::array<float, 8> proxNormalized;
13

    
14
bool running;
15

    
16
uint16_t constexpr proxThresholdLow = 0x0000;
17
uint16_t constexpr proxThresholdHigh = 0x2000;
18
uint16_t constexpr proxRange = proxThresholdHigh - proxThresholdLow;
19

    
20
std::array< std::array<float, 2>, 8> constexpr namMatrix = {
21
    /*                              x     w_z */
22
    std::array<float, 2>/* SSW */{ 0.00f,  0.00f},
23
    std::array<float, 2>/* WSW */{ 0.25f, -0.25f},
24
    std::array<float, 2>/* WNW */{-0.75f, -0.50f},
25
    std::array<float, 2>/* NNW */{-0.75f, -1.00f},
26
    std::array<float, 2>/* NNE */{-0.75f,  1.00f},
27
    std::array<float, 2>/* ENE */{-0.75f,  0.50f},
28
    std::array<float, 2>/* ESE */{ 0.25f,  0.25f},
29
    std::array<float, 2>/* SSE */{ 0.00f,  0.00f}
30
};
31
uint32_t constexpr baseTranslation = 50e3; // 2cm/s
32
uint32_t constexpr baseRotation = 1e6; // 1rad/s
33
types::kinematic constexpr defaultKinematic = {
34
    /*  x  [µm/s]   */ baseTranslation,
35
    /*  y  [µm/s]   */ 0,
36
    /*  z  [µm/s]   */ 0,
37
    /* w_x [µrad/s] */ 0,
38
    /* w_y [µrad/s] */ 0,
39
    /* w_z [µrad/s] */ 0
40
};
41

    
42

    
43

    
44
inline uint8_t ProxId2LedId(const uint8_t proxId) {
45
    return (proxId < 4) ? proxId+4 : proxId-4;
46
}
47

    
48
Color Prox2Color(const float prox) {
49
  float p = 0.0f;
50
  if (prox < 0.5f) {
51
    p = 2.0f * prox;
52
    return Color(0x00, p*0xFF, (1.0f-p)*0xFF);
53
  } else {
54
    p = 2.0f * (prox - 0.5f);
55
    return Color(p*0xFF, (1.0f-p)*0xFF, 0x00);
56
  }
57
}
58

    
59
UserThread::UserThread() :
60
  chibios_rt::BaseStaticThread<USER_THREAD_STACK_SIZE>()
61
{
62
}
63

    
64
UserThread::~UserThread()
65
{
66
}
67

    
68
msg_t
69
UserThread::main()
70
{
71
    uint8_t sensor = 0;
72
    float factor_x = 0.0f;
73
    float factor_wz = 0.0f;
74
    types::kinematic kinematic = defaultKinematic;
75

    
76
    for (uint8_t led = 0; led < 8; ++led) {
77
      global.robot.setLightColor(led, Color(Color::BLACK));
78
    }
79
    running = false;
80

    
81
    while (!this->shouldTerminate())
82
    {
83
        /*
84
         * read touch sensor values
85
         */
86
        touch = global.mpr121.getButtonStatus();
87

    
88
        /*
89
         * evaluate touch input
90
         */
91
        if (touch == 0x0F) {
92
            if (running) {
93
                // stop the robot
94
                running = false;
95
                kinematic = {0, 0, 0, 0, 0, 0};
96
                global.robot.setTargetSpeed(kinematic);
97
            } else {
98
                // start the robot
99
                running = true;
100
            }
101

    
102
            // set all LEDs to white for one second
103
            for (uint8_t led = 0; led < 8; ++led) {
104
                global.robot.setLightColor(led, Color(Color::WHITE));
105
            }
106
            this->sleep(MS2ST(1000));
107
            for (uint8_t led = 0; led < 8; ++led) {
108
                global.robot.setLightColor(led, Color(Color::BLACK));
109
            }
110
        }
111

    
112
        if (running) {
113
            /*
114
             * read proximity values
115
             */
116
            for (sensor = 0; sensor < 8; ++sensor) {
117
                proximity[sensor] = global.vcnl4020[sensor].getProximityScaledWoOffset();
118
                //proxNormalized[sensor] += 2.0f * (proxNormalized[sensor] * (1.0f - proxNormalized[sensor])); // non linearity
119
            }
120

    
121
            /*
122
             * normalize proximity values
123
             */
124
            for (sensor = 0; sensor < 8; ++sensor) {
125
                register uint16_t prox = proximity[sensor];
126
                // limit to high treshold
127
                if (prox > proxThresholdHigh)
128
                    prox = proxThresholdHigh;
129
                // limit to low threshold
130
                else if (prox < proxThresholdLow)
131
                    prox = proxThresholdLow;
132
                // apply low threshold
133
                prox -= proxThresholdLow;
134
                // normalize to [0, 1]
135
                proxNormalized[sensor] = float(prox) / float(proxRange);
136
            }
137

    
138
            /*
139
             * map the sensor values to the top LEDs
140
             */
141
            for (sensor = 0; sensor < 8; ++sensor) {
142
                global.robot.setLightColor(ProxId2LedId(sensor), Prox2Color(proxNormalized[sensor]));
143
            }
144

    
145
            /*
146
             * evaluate NAM
147
             */
148
            factor_x = 0.0f;
149
            factor_wz = 0.0f;
150
            for (sensor = 0; sensor < 8; ++sensor) {
151
                factor_x += proxNormalized[sensor] * namMatrix[sensor][0];
152
                factor_wz += proxNormalized[sensor] * namMatrix[sensor][1];
153
            }
154

    
155
            /*
156
             * set motor commands
157
             */
158
            kinematic = defaultKinematic;
159
            kinematic.x += (factor_x * baseTranslation) + 0.5f;
160
            kinematic.w_z += (factor_wz * baseRotation) + 0.5f;
161
            global.robot.setTargetSpeed(kinematic);
162
        }
163

    
164
        this->sleep(MS2ST(100));
165
    }
166

    
167
  return RDY_OK;
168
}
169