Skip to content

Commit b6e4ed8

Browse files
Merge pull request #80 from trikset/range-sensor
Range sensor
2 parents cfddf4f + 54f8fc8 commit b6e4ed8

File tree

12 files changed

+413
-4
lines changed

12 files changed

+413
-4
lines changed

trikControl/config.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ Use it if JCx ports are configured to work as PWM signal generators.
161161
<!-- Digital sensors configuration, maps logical port to digital sensor device file and digital sensor type used by default
162162
(if not configured programmatically). -->
163163
<digitalSensors>
164-
<digitalSensor port="D1" deviceFile="/sys/devices/platform/da850_trik/sensor_d1" defaultType="rangeSensor" />
165-
<digitalSensor port="D2" deviceFile="/sys/devices/platform/da850_trik/sensor_d2" defaultType="rangeSensor" />
164+
<rangeSensor port="D1" eventFile="/dev/input/by-path/platform-trik_jd1-event"/>
165+
<rangeSensor port="D2" eventFile="/dev/input/by-path/platform-trik_jd2-event"/>
166166
<digitalSensor port="F1" deviceFile="/sys/devices/platform/da850_trik/sensor_dc" defaultType="volumeSensor" />
167167
<accelerometer min="-32767" max="32767" deviceFile="/dev/input/event1" disabled="false" />
168168
<gyroscope min="-32767" max="32767" deviceFile="/dev/input/by-path/platform-spi_davinci.1-event" disabled="false" />

trikControl/include/trikControl/brick.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
#include "analogSensor.h"
2929
#include "battery.h"
3030
#include "colorSensor.h"
31-
#include "digitalSensor.h"
3231
#include "display.h"
3332
#include "encoder.h"
3433
#include "gamepad.h"
@@ -48,6 +47,8 @@ class Configurer;
4847
class I2cCommunicator;
4948
class PowerMotor;
5049
class ServoMotor;
50+
class DigitalSensor;
51+
class RangeSensor;
5152

5253
/// Class representing TRIK controller board and devices installed on it, also provides access
5354
/// to peripherals like motors and sensors.
@@ -186,6 +187,7 @@ public slots:
186187
QHash<QString, AnalogSensor *> mAnalogSensors; // Has ownership.
187188
QHash<QString, Encoder *> mEncoders; // Has ownership.
188189
QHash<QString, DigitalSensor *> mDigitalSensors; // Has ownership.
190+
QHash<QString, RangeSensor *> mRangeSensors; // Has ownership.
189191
QList<QTimer *> mTimers; // Has ownership.
190192

191193
Configurer const * const mConfigurer; // Has ownership.

trikControl/include/trikControl/digitalSensor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
namespace trikControl {
2626

2727
/// Generic TRIK sensor.
28+
/// @todo Why it is in /include?
2829
class TRIKCONTROL_EXPORT DigitalSensor : public Sensor
2930
{
3031
Q_OBJECT

trikControl/src/brick.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#include "angularServoMotor.h"
2424
#include "continiousRotationServoMotor.h"
2525
#include "powerMotor.h"
26+
#include "digitalSensor.h"
27+
#include "rangeSensor.h"
2628

2729
#include "configurer.h"
2830
#include "i2cCommunicator.h"
@@ -124,6 +126,12 @@ Brick::Brick(QThread &guiThread, QString const &configFilePath, const QString &s
124126
mDigitalSensors.insert(port, digitalSensor);
125127
}
126128

129+
for (QString const &port : mConfigurer->rangeSensorPorts()) {
130+
RangeSensor *rangeSensor = new RangeSensor(mConfigurer->rangeSensorEventFile(port));
131+
rangeSensor->init();
132+
mRangeSensors.insert(port, rangeSensor);
133+
}
134+
127135
for (QString const &port : mConfigurer->encoderPorts()) {
128136
QString const encoderType = mConfigurer->encoderDefaultType(port);
129137

@@ -211,6 +219,7 @@ Brick::~Brick()
211219
qDeleteAll(mEncoders);
212220
qDeleteAll(mAnalogSensors);
213221
qDeleteAll(mDigitalSensors);
222+
qDeleteAll(mRangeSensors);
214223
qDeleteAll(mTimers);
215224
delete mAccelerometer;
216225
delete mGyroscope;
@@ -230,6 +239,11 @@ void Brick::reset()
230239
mKeys->reset();
231240
mDisplay.clear();
232241
mInEventDrivenMode = false;
242+
243+
/// @todo Temporary, we need more carefully init/deinit range sensors.
244+
for (RangeSensor * const rangeSensor : mRangeSensors.values()) {
245+
rangeSensor->init();
246+
}
233247
}
234248

235249
void Brick::playSound(QString const &soundFileName)
@@ -286,6 +300,10 @@ void Brick::stop()
286300
if (mObjectSensor) {
287301
mObjectSensor->stop();
288302
}
303+
304+
for (RangeSensor * const rangeSensor : mRangeSensors.values()) {
305+
rangeSensor->stop();
306+
}
289307
}
290308

291309
Motor *Brick::motor(QString const &port)
@@ -310,6 +328,8 @@ Sensor *Brick::sensor(QString const &port)
310328
return mAnalogSensors[port];
311329
} else if (mDigitalSensors.contains(port)) {
312330
return mDigitalSensors[port];
331+
} else if (mRangeSensors.contains(port)) {
332+
return mRangeSensors[port];
313333
} else {
314334
return nullptr;
315335
}
@@ -341,7 +361,7 @@ QStringList Brick::sensorPorts(Sensor::Type type) const
341361
return mAnalogSensors.keys();
342362
}
343363
case Sensor::digitalSensor: {
344-
return mDigitalSensors.keys();
364+
return mDigitalSensors.keys() + mRangeSensors.keys();
345365
}
346366
case Sensor::specialSensor: {
347367
// Special sensors can not be connected to standard ports, they have their own methods to access them.

trikControl/src/configurer.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ Configurer::Configurer(QString const &configFilePath)
5656
loadAnalogSensors(root);
5757
loadEncoders(root);
5858
loadDigitalSensors(root);
59+
loadRangeSensors(root);
5960
loadServoMotorTypes(root);
6061
loadAnalogSensorTypes(root);
6162
loadDigitalSensorTypes(root);
@@ -260,6 +261,16 @@ QString Configurer::digitalSensorDefaultType(QString const &port) const
260261
return mDigitalSensorMappings[port].defaultType;
261262
}
262263

264+
QStringList Configurer::rangeSensorPorts() const
265+
{
266+
return mRangeSensorMappings.keys();
267+
}
268+
269+
QString Configurer::rangeSensorEventFile(QString const &port) const
270+
{
271+
return mRangeSensorMappings[port].eventFile;
272+
}
273+
263274
QString Configurer::playWavFileCommand() const
264275
{
265276
return mPlayWavFileCommand;
@@ -656,6 +667,36 @@ void Configurer::loadDigitalSensors(QDomElement const &root)
656667
}
657668
}
658669

670+
void Configurer::loadRangeSensors(QDomElement const &root)
671+
{
672+
if (root.elementsByTagName("digitalSensors").isEmpty()) {
673+
QLOG_FATAL() << "config.xml does not have <digitalSensors> tag";
674+
qDebug() << "config.xml does not have <digitalSensors> tag";
675+
throw errorMessage;
676+
}
677+
678+
QDomElement const digitalSensors = root.elementsByTagName("digitalSensors").at(0).toElement();
679+
for (QDomNode child = digitalSensors.firstChild()
680+
; !child.isNull()
681+
; child = child.nextSibling())
682+
{
683+
if (!child.isElement()) {
684+
continue;
685+
}
686+
687+
QDomElement const childElement = child.toElement();
688+
if (childElement.nodeName() != "rangeSensor") {
689+
continue;
690+
}
691+
692+
RangeSensorMapping mapping;
693+
mapping.port = childElement.attribute("port");
694+
mapping.eventFile = childElement.attribute("eventFile");
695+
696+
mRangeSensorMappings.insert(mapping.port, mapping);
697+
}
698+
}
699+
659700
void Configurer::loadServoMotorTypes(QDomElement const &root)
660701
{
661702
if (root.elementsByTagName("servoMotorTypes").isEmpty()) {

trikControl/src/configurer.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ class Configurer {
113113

114114
QString digitalSensorDefaultType(QString const &port) const;
115115

116+
QStringList rangeSensorPorts() const;
117+
118+
QString rangeSensorEventFile(QString const &port) const;
119+
116120
QString playWavFileCommand() const;
117121

118122
QString playMp3FileCommand() const;
@@ -256,6 +260,11 @@ class Configurer {
256260
QString defaultType;
257261
};
258262

263+
struct RangeSensorMapping {
264+
QString port;
265+
QString eventFile;
266+
};
267+
259268
struct OnBoardSensor {
260269
int min = 0;
261270
int max = 0;
@@ -278,6 +287,7 @@ class Configurer {
278287
void loadAnalogSensors(QDomElement const &root);
279288
void loadEncoders(QDomElement const &root);
280289
void loadDigitalSensors(QDomElement const &root);
290+
void loadRangeSensors(QDomElement const &root);
281291
void loadServoMotorTypes(QDomElement const &root);
282292
void loadAnalogSensorTypes(QDomElement const &root);
283293
void loadDigitalSensorTypes(QDomElement const &root);
@@ -303,6 +313,7 @@ class Configurer {
303313
QHash<QString, AnalogSensorMapping> mAnalogSensorMappings;
304314
QHash<QString, EncoderMapping> mEncoderMappings;
305315
QHash<QString, DigitalSensorMapping> mDigitalSensorMappings;
316+
QHash<QString, RangeSensorMapping> mRangeSensorMappings;
306317

307318
OnBoardSensor mAccelerometer;
308319
OnBoardSensor mGyroscope;
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/* Copyright 2014 CyberTech Labs Ltd.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License. */
14+
15+
#include "src/rangeSensorWorker.h"
16+
17+
#include <QtCore/QDebug>
18+
#include <QtCore/QFileInfo>
19+
#include <QtCore/QStringList>
20+
21+
#include <unistd.h>
22+
#include <fcntl.h>
23+
#include <errno.h>
24+
#include <linux/input.h>
25+
26+
#include <QsLog.h>
27+
28+
using namespace trikControl;
29+
30+
RangeSensorWorker::RangeSensorWorker(QString const &eventFile)
31+
: mEventFile(eventFile)
32+
{
33+
}
34+
35+
RangeSensorWorker::~RangeSensorWorker()
36+
{
37+
stop();
38+
}
39+
40+
void RangeSensorWorker::stop()
41+
{
42+
if (mSocketNotifier) {
43+
disconnect(mSocketNotifier.data(), SIGNAL(activated(int)), this, SLOT(readFile()));
44+
mSocketNotifier->setEnabled(false);
45+
}
46+
47+
if (::close(mEventFileDescriptor) != 0) {
48+
QString const message = QString("%1: close failed: %2").arg(mEventFile.fileName()).arg(errno);
49+
QLOG_ERROR() << message;
50+
qDebug() << message;
51+
}
52+
53+
mEventFileDescriptor = -1;
54+
}
55+
56+
void RangeSensorWorker::init()
57+
{
58+
QLOG_INFO() << "Opening" << mEventFile.fileName();
59+
qDebug() << "Opening" << mEventFile.fileName();
60+
61+
/// @todo Is it possible to use QFile (and QFile::handle()) here?
62+
mEventFileDescriptor = open(mEventFile.fileName().toStdString().c_str(), O_SYNC | O_NONBLOCK, O_RDONLY);
63+
64+
if (mEventFileDescriptor == -1) {
65+
QLOG_ERROR() << "Cannot open range sensor output file" << mEventFile.fileName();
66+
qDebug() << "Cannot open range sensor output file" << mEventFile.fileName();
67+
return;
68+
}
69+
70+
mSocketNotifier.reset(new QSocketNotifier(mEventFileDescriptor, QSocketNotifier::Read));
71+
72+
connect(mSocketNotifier.data(), SIGNAL(activated(int)), this, SLOT(readFile()));
73+
mSocketNotifier->setEnabled(true);
74+
}
75+
76+
void RangeSensorWorker::readFile()
77+
{
78+
struct input_event event;
79+
int size = 0;
80+
81+
mSocketNotifier->setEnabled(false);
82+
83+
while ((size = ::read(mEventFileDescriptor, reinterpret_cast<char *>(&event), sizeof(event)))
84+
== static_cast<int>(sizeof(event)))
85+
{
86+
switch (event.type) {
87+
case EV_ABS:
88+
switch (event.code) {
89+
case ABS_DISTANCE:
90+
mLock.lockForWrite();
91+
mDistance = event.value;
92+
mLock.unlock();
93+
break;
94+
case ABS_MISC:
95+
mLock.lockForWrite();
96+
mRawDistance = event.value;
97+
mLock.unlock();
98+
break;
99+
}
100+
break;
101+
case EV_SYN:
102+
mLock.lockForRead();
103+
emit newData(mDistance, mRawDistance);
104+
mLock.unlock();
105+
break;
106+
}
107+
}
108+
109+
if (0 <= size && size < static_cast<int>(sizeof(event))) {
110+
QLOG_ERROR() << "incomplete data read";
111+
qDebug() << "incomplete data read";
112+
}
113+
114+
mSocketNotifier->setEnabled(true);
115+
}
116+
117+
int RangeSensorWorker::read()
118+
{
119+
mLock.lockForRead();
120+
int const result = mDistance;
121+
mLock.unlock();
122+
return result;
123+
}
124+
125+
int RangeSensorWorker::readRawData()
126+
{
127+
mLock.lockForRead();
128+
int const result = mRawDistance;
129+
mLock.unlock();
130+
return result;
131+
}

0 commit comments

Comments
 (0)