Skip to content

Commit 17ae39b

Browse files
Merge pull request #103 from Kseniya-Gonta/Gonta
Added calibration of IR sensor
2 parents be6c492 + 23eed2f commit 17ae39b

File tree

7 files changed

+110
-31
lines changed

7 files changed

+110
-31
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
*~
12
# Compiled Object files
23
*.slo
34
*.lo

trikControl/model-config.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,22 @@ Note that device, even if listed here, may fail by itself, then it also will not
4646

4747
<!-- Analog sensor ports. -->
4848
<A1>
49-
<irSensor />
49+
<sharpGP2Sensor />
5050
</A1>
5151
<A2>
52-
<irSensor />
52+
<sharpGP2Sensor />
5353
</A2>
5454
<A3>
55-
<irSensor />
55+
<sharpGP2Sensor />
5656
</A3>
5757
<A4>
58-
<irSensor />
58+
<analogSensor />
5959
</A4>
6060
<A5>
61-
<irSensor />
61+
<analogSensor />
6262
</A5>
6363
<A6>
64-
<irSensor />
64+
<analogSensor />
6565
</A6>
6666

6767
<!-- Digital sensor ports. -->

trikControl/src/analogSensor.cpp

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2013 - 2015 Nikita Batov and CyberTech Labs Ltd.
1+
/* Copyright 2013 - 2015 Nikita Batov, Kseniya Gonta and CyberTech Labs Ltd.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -26,26 +26,20 @@ AnalogSensor::AnalogSensor(const QString &port, const trikKernel::Configurer &co
2626
: mCommunicator(communicator)
2727
{
2828
mI2cCommandNumber = ConfigurerHelper::configureInt(configurer, mState, port, "i2cCommandNumber");
29-
30-
// We use linear subjection to normalize sensor values:
29+
mIRType = configurer.attributeByPort(port, "type") == "SharpGP2" ? Type::sharpGP2 : Type::analog;
30+
// We use linear subjection to normalize common analog sensor values:
3131
// normalizedValue = k * rawValue + b
3232
// To calculate k and b we need two raw values and two corresponding them normalized values.
3333

34-
const int rawValue1 = ConfigurerHelper::configureInt(configurer, mState, port, "rawValue1");
35-
const int rawValue2 = ConfigurerHelper::configureInt(configurer, mState, port, "rawValue2");
36-
const int normalizedValue1 = ConfigurerHelper::configureInt(configurer, mState, port, "normalizedValue1");
37-
const int normalizedValue2 = ConfigurerHelper::configureInt(configurer, mState, port, "normalizedValue2");
34+
// We use hyperbolical subjection to normalize SharpGP2 sensor values:
35+
// normalizedValue = s / (rawValue + l) + n
36+
// To calculate s, l and n we need sensor readings at three distances.
3837

39-
if (rawValue1 == rawValue2) {
40-
QLOG_ERROR() << "Sensor calibration error: rawValue1 = rawValue2!";
41-
mState.fail();
42-
mK = 0;
43-
mB = 0;
38+
if (mIRType == Type::sharpGP2){
39+
calculateLNS(port, configurer);
4440
} else {
45-
mK = static_cast<qreal>(normalizedValue2 - normalizedValue1) / (rawValue2 - rawValue1);
46-
mB = normalizedValue1 - mK * rawValue1;
41+
calculateKB(port, configurer);
4742
}
48-
4943
mState.ready();
5044
}
5145

@@ -56,14 +50,11 @@ AnalogSensor::Status AnalogSensor::status() const
5650

5751
int AnalogSensor::read()
5852
{
59-
if (!mState.isReady() || mCommunicator.status() != DeviceInterface::Status::ready) {
60-
return 0;
53+
const auto raw = readRawData();
54+
if (mIRType == Type::sharpGP2) {
55+
return mS /(raw + mL) + mN;
6156
}
62-
63-
QByteArray command(1, '\0');
64-
command[0] = static_cast<char>(mI2cCommandNumber & 0xFF);
65-
66-
return mK * mCommunicator.read(command) + mB;
57+
return mK * raw + mB;
6758
}
6859

6960
int AnalogSensor::readRawData()
@@ -77,3 +68,41 @@ int AnalogSensor::readRawData()
7768

7869
return mCommunicator.read(command);
7970
}
71+
72+
void AnalogSensor::calculateLNS(const QString &port, const trikKernel::Configurer &configurer)
73+
{
74+
QStringList result;
75+
for (const QString &str : configurer.attributeByPort(port, "values").split(")")) {
76+
result += str.mid(1).split(";");
77+
}
78+
79+
const int x1 = result[0].toInt();
80+
const int y1 = result[1].toInt();
81+
const int x2 = result[2].toInt();
82+
const int y2 = result[3].toInt();
83+
const int x3 = result[4].toInt();
84+
const int y3 = result[5].toInt();
85+
86+
// Counted from equations x1 = mS/(y1 + mL) + mN, x2 = mS/(y2 + mL) + mN, x3 = mS/(y3 + mL) + mN
87+
mL = (-x1 * y1 * y3 - x3 * y2 * y3 + x3 * y1 * y3 + x1 * y1 * y2 + x2 * y2 * y3 - x2 * y1 * y2) /
88+
(x1 * y3 - x2 * y3 + x2 * y1 - x1 * y2 + x3 * y2 - x3 * y1);
89+
mS = (x1 - x2) * (y1 + mL) * (y2 + mL) / (y2 - y1);
90+
mN = x1 - mS / (y1 + mL);
91+
}
92+
93+
void AnalogSensor::calculateKB(const QString &port, const trikKernel::Configurer &configurer)
94+
{
95+
const int rawValue1 = ConfigurerHelper::configureInt(configurer, mState, port, "rawValue1");
96+
const int rawValue2 = ConfigurerHelper::configureInt(configurer, mState, port, "rawValue2");
97+
const int normalizedValue1 = ConfigurerHelper::configureInt(configurer, mState, port, "normalizedValue1");
98+
const int normalizedValue2 = ConfigurerHelper::configureInt(configurer, mState, port, "normalizedValue2");
99+
if (rawValue1 == rawValue2) {
100+
QLOG_ERROR() << "Sensor calibration error: rawValue1 = rawValue2!";
101+
mState.fail();
102+
mK = 0;
103+
mB = 0;
104+
} else {
105+
mK = static_cast<qreal>(normalizedValue2 - normalizedValue1) / (rawValue2 - rawValue1);
106+
mB = normalizedValue1 - mK * rawValue1;
107+
}
108+
}

trikControl/src/analogSensor.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2013 - 2015 Nikita Batov and CyberTech Labs Ltd.
1+
/* Copyright 2013 - 2015 Nikita Batov, Kseniya Gonta and CyberTech Labs Ltd.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -50,15 +50,40 @@ public slots:
5050
int readRawData() override;
5151

5252
private:
53+
enum class Type
54+
{
55+
/// Calibrated IR sensor.
56+
sharpGP2
57+
58+
/// Normalized IR sensor.
59+
, analog
60+
};
61+
62+
void calculateLNS(const QString &port, const trikKernel::Configurer &configurer);
63+
void calculateKB(const QString &port, const trikKernel::Configurer &configurer);
64+
5365
I2cCommunicator &mCommunicator;
5466
int mI2cCommandNumber = 0;
67+
Type mIRType;
5568

5669
/// Linear approximation coefficient k. Normalized value is calculated as normalizedValue = k * rawValue + b.
5770
qreal mK = 0;
5871

5972
/// Linear approximation coefficient b. Normalized value is calculated as normalizedValue = k * rawValue + b.
6073
qreal mB = 0;
6174

75+
/// Hyperbolical approximation coefficient l.
76+
/// Normalized value is calculated as normalizedValue = s / (rawValue + l) + n.
77+
int mL = 0;
78+
79+
/// Hyperbolical approximation coefficient n.
80+
/// Normalized value is calculated as normalizedValue = s / (rawValue + l) + n.
81+
int mN = 0;
82+
83+
/// Hyperbolical approximation coefficient s.
84+
/// Normalized value is calculated as normalizedValue = s / (rawValue + l) + n.
85+
int mS = 0;
86+
6287
/// State of a device.
6388
DeviceState mState;
6489
};

trikControl/src/powerMotor.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ PowerMotor::PowerMotor(const QString &port, const trikKernel::Configurer &config
2525
: mCommunicator(communicator)
2626
, mInvert(configurer.attributeByPort(port, "invert") == "false")
2727
, mCurrentPower(0)
28+
, mCurrentPeriod(0x1000)
2829
{
2930
mI2cCommandNumber = ConfigurerHelper::configureInt(configurer, mState, port, "i2cCommandNumber");
3031
mState.ready();
@@ -66,7 +67,22 @@ int PowerMotor::power() const
6667
return mCurrentPower;
6768
}
6869

70+
int PowerMotor::period() const
71+
{
72+
return mCurrentPeriod;
73+
}
74+
6975
void PowerMotor::powerOff()
7076
{
7177
setPower(0);
7278
}
79+
80+
void PowerMotor::setPeriod(int period)
81+
{
82+
mCurrentPeriod = period;
83+
QByteArray command(3, '\0');
84+
command[0] = static_cast<char>((mI2cCommandNumber - 4) & 0xFF);
85+
command[1] = static_cast<char>(period && 0xFF);
86+
command[2] = static_cast<char>(period >> 8);
87+
mCommunicator.send(command);
88+
}

trikControl/src/powerMotor.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,24 @@ public slots:
5353
/// Returns currently set power of a motor.
5454
int power() const;
5555

56+
/// Returns currently set period of a motor.
57+
int period() const;
58+
5659
/// Turns off motor. This is not the same as setPower(0), because setPower will
5760
/// leave motor on in a break mode, and this method will turn motor off.
5861
void powerOff();
5962

63+
/// Sets current motor period.
64+
/// Period of pulses is a time interval between two characteristic points of two adjacent pulses.
65+
void setPeriod(int period);
66+
6067
private:
6168
I2cCommunicator &mCommunicator;
6269
int mI2cCommandNumber;
6370
const bool mInvert;
6471
int mCurrentPower;
6572
DeviceState mState;
73+
int mCurrentPeriod;
6674
};
6775

6876
}

trikControl/system-config.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ equal to its class name.
6464
<servoMotor period="20000000" invert="false" />
6565
<pwmCapture />
6666
<powerMotor invert="false" />
67-
<analogSensor />
67+
<analogSensor rawValue1="0" rawValue2="1024" normalizedValue1="0" normalizedValue2="100" type="Analog" />
6868
<encoder />
6969
<rangeSensor commonModule="hcsr04" />
7070
<digitalSensor />
@@ -163,7 +163,7 @@ equal to its class name.
163163
<deviceTypes>
164164
<angularServomotor class="servoMotor" min="700000" max="2300000" zero="1500000" stop="0" type="angular" />
165165
<continuousRotationServomotor class="servoMotor" min="700000" max="2300000" zero="1500000" stop="0" type="continuousRotation" />
166-
<irSensor class="analogSensor" rawValue1="0" rawValue2="1024" normalizedValue1="0" normalizedValue2="100" />
166+
<sharpGP2Sensor class="analogSensor" rawValue1="0" rawValue2="1024" normalizedValue1="0" normalizedValue2="100" type="SharpGP2" values="(25;322)(35;235)(15;511)" />
167167
<sonarSensor class="rangeSensor" rawValue1="750" rawValue2="400" normalizedValue1="10" normalizedValue2="20" />
168168
<lightSensor class="digitalSensor" min="30000" max="350000" />
169169
<volumeSensor class="digitalSensor" min="0" max="100" />

0 commit comments

Comments
 (0)