Skip to content

Commit 7934ece

Browse files
Merge branch 'stopping' of https://github.com/trikset/trikRuntime
2 parents 8616301 + 8420af6 commit 7934ece

File tree

11 files changed

+93
-77
lines changed

11 files changed

+93
-77
lines changed

trikControl/src/led.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ Led::Led(const trikKernel::Configurer &configurer, const trikHal::HardwareAbstra
3939

4040
Led::~Led()
4141
{
42-
red();
43-
4442
mRedDeviceFile->close();
4543
mGreenDeviceFile->close();
4644
}

trikControl/src/powerMotor.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,6 @@ PowerMotor::PowerMotor(const QString &port, const trikKernel::Configurer &config
3535

3636
PowerMotor::~PowerMotor()
3737
{
38-
if (mState.isReady()) {
39-
powerOff();
40-
}
4138
}
4239

4340
PowerMotor::Status PowerMotor::status() const

trikGui/controller.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,16 @@ void Controller::scriptExecutionCompleted(const QString &error, int scriptId)
143143
mCommunicator->sendMessage("error: " + error);
144144
emit showError(error, scriptId);
145145
}
146+
147+
mBrick->reset();
148+
149+
if (mMailbox) {
150+
mMailbox->clearQueue();
151+
}
152+
153+
if (mGamepad) {
154+
mGamepad->reset();
155+
}
146156
}
147157

148158
void Controller::scriptExecutionFromFileStarted(const QString &fileName, int scriptId)

trikNetwork/include/trikNetwork/mailboxInterface.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,11 @@ class TRIKNETWORK_EXPORT MailboxInterface : public QObject
4545
/// Returns our IP address, or empty QHostAddress if we are not connected.
4646
virtual QHostAddress myIp() const = 0;
4747

48-
/// Stops waiting for messages, clears message queue.
49-
virtual void reset() = 0;
48+
/// Clears message queue.
49+
virtual void clearQueue() = 0;
50+
51+
/// Stops waiting for messages.
52+
virtual void stopWaiting() = 0;
5053

5154
/// Returns true if mailbox is enabled in current configuration.
5255
virtual bool isEnabled() = 0;

trikNetwork/src/mailbox.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,18 @@ QHostAddress Mailbox::myIp() const
7373
return mWorker->myIp();
7474
}
7575

76-
void Mailbox::reset()
76+
void Mailbox::clearQueue()
7777
{
78-
emit stopWaiting();
7978
while (mWorker->hasMessages()) {
8079
mWorker->receive();
8180
}
8281
}
8382

83+
void Mailbox::stopWaiting()
84+
{
85+
emit stopWaitingSignal();
86+
}
87+
8488
bool Mailbox::isEnabled()
8589
{
8690
return !mWorker.isNull();
@@ -116,7 +120,7 @@ QString Mailbox::receive(bool wait)
116120
QString result;
117121

118122
QEventLoop loop;
119-
QObject::connect(this, SIGNAL(stopWaiting()), &loop, SLOT(quit()));
123+
QObject::connect(this, SIGNAL(stopWaitingSignal()), &loop, SLOT(quit()));
120124
if (!mWorker->hasMessages() && wait) {
121125
loop.exec();
122126
}
@@ -132,7 +136,7 @@ void Mailbox::init(int port)
132136
{
133137
mWorker.reset(new MailboxServer(port));
134138
QObject::connect(mWorker.data(), SIGNAL(newMessage(int, QString)), this, SIGNAL(newMessage(int, QString)));
135-
QObject::connect(mWorker.data(), SIGNAL(newMessage(int, QString)), this, SIGNAL(stopWaiting()));
139+
QObject::connect(mWorker.data(), SIGNAL(newMessage(int, QString)), this, SIGNAL(stopWaitingSignal()));
136140
QObject::connect(mWorker.data(), SIGNAL(connected()), this, SLOT(updateConnectionStatus()));
137141
QObject::connect(mWorker.data(), SIGNAL(disconnected()), this, SLOT(updateConnectionStatus()));
138142

trikNetwork/src/mailbox.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,12 @@ class Mailbox : public MailboxInterface
5555

5656
QHostAddress myIp() const override;
5757

58-
void reset() override;
58+
void clearQueue() override;
5959

6060
bool isEnabled() override;
6161

62+
void stopWaiting() override;
63+
6264
public slots:
6365
void connect(const QString &ip, int port) override;
6466

@@ -76,7 +78,7 @@ public slots:
7678

7779
signals:
7880
/// Used to interrupt waiting for new message.
79-
void stopWaiting();
81+
void stopWaitingSignal();
8082

8183
private slots:
8284
void updateConnectionStatus();

trikScriptRunner/include/trikScriptRunner/trikScriptRunner.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ class TrikScriptRunner : public QObject
5555

5656
public slots:
5757
/// Executes given script asynchronously. If some script is already executing, it will be aborted.
58-
/// Execution state will be reset (and robot fully stopped) before and
59-
/// after script execution. For event-driven mode (where script has brick.run() command) script counts as finished
58+
/// For event-driven mode (where script has brick.run() command) script counts as finished
6059
/// when it requests to quit by itself or was aborted. When script is finished, completed() signal will be emitted.
6160
/// @param script - script in Qt Script language to be executed.
6261
/// @param fileName - name of a file from which the script was loaded.

trikScriptRunner/src/scriptEngineWorker.cpp

Lines changed: 50 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ ScriptEngineWorker::ScriptEngineWorker(trikControl::BrickInterface &brick
8787
, mMailbox(mailbox)
8888
, mGamepad(gamepad)
8989
, mScriptControl(scriptControl)
90-
, mThreadingVariable(this, scriptControl)
90+
, mThreading(this, scriptControl)
9191
, mDirectScriptsEngine(nullptr)
9292
, mScriptId(0)
9393
, mState(ready)
@@ -102,48 +102,65 @@ void ScriptEngineWorker::brickBeep()
102102
mBrick.playSound(trikKernel::Paths::mediaPath() + "media/beep_soft.wav");
103103
}
104104

105-
void ScriptEngineWorker::reset()
105+
void ScriptEngineWorker::stopScript()
106106
{
107-
if (mState == resetting) {
107+
if (mState == stopping) {
108+
// Already stopping, so we can do nothing.
108109
return;
109110
}
110111

111-
while (mState == starting) {
112-
QThread::yieldCurrentThread();
113-
}
114-
115112
if (mState == ready) {
116-
/// Engine is ready for execution, but we need to clear brick state before we go.
117-
QLOG_INFO() << "ScriptEngineWorker: 'soft' reset";
118-
mState = resetting;
119-
clearMailboxAndGamepadState();
120-
clearBrickState();
121-
mState = ready;
113+
// Engine is ready for execution.
122114
return;
123115
}
124116

125-
QLOG_INFO() << "ScriptEngineWorker: reset started";
117+
while (mState == starting) {
118+
// Some script is starting right now, so we are in inconsistent state. Let it start, then stop it.
119+
QThread::yieldCurrentThread();
120+
}
121+
122+
QLOG_INFO() << "ScriptEngineWorker: stopping script";
126123

127-
mState = resetting;
124+
mState = stopping;
128125

129126
mScriptControl.reset();
130127

131-
mThreadingVariable.reset();
132-
clearMailboxAndGamepadState();
128+
mThreading.reset();
129+
mMailbox->stopWaiting();
133130

134131
if (mDirectScriptsEngine) {
135132
mDirectScriptsEngine->abortEvaluation();
136133
QLOG_INFO() << "ScriptEngineWorker : ending interpretation";
137134
emit completed(mDirectScriptsEngine->hasUncaughtException()
138-
? mDirectScriptsEngine->uncaughtException().toString()
139-
: "", mScriptId);
135+
? mDirectScriptsEngine->uncaughtException().toString()
136+
: ""
137+
, mScriptId);
138+
140139
mDirectScriptsEngine->deleteLater();
141140
mDirectScriptsEngine = nullptr;
142141
}
143142

144-
clearBrickState();
145143
mState = ready;
146-
QLOG_INFO() << "ScriptEngineWorker: reset complete";
144+
145+
/// @todo: is it actually stopped?
146+
147+
QLOG_INFO() << "ScriptEngineWorker: stopping complete";
148+
}
149+
150+
void ScriptEngineWorker::resetBrick()
151+
{
152+
QLOG_INFO() << "Stopping robot";
153+
154+
if (mMailbox) {
155+
mMailbox->stopWaiting();
156+
mMailbox->clearQueue();
157+
}
158+
159+
if (mGamepad) {
160+
mGamepad->reset();
161+
}
162+
163+
mBrick.reset();
147164
}
148165

149166
void ScriptEngineWorker::run(const QString &script, int scriptId)
@@ -154,11 +171,10 @@ void ScriptEngineWorker::run(const QString &script, int scriptId)
154171

155172
void ScriptEngineWorker::doRun(const QString &script)
156173
{
157-
mThreadingVariable.startMainThread(script);
174+
mThreading.startMainThread(script);
158175
mState = running;
159-
mThreadingVariable.waitForAll();
160-
const QString error = mThreadingVariable.errorMessage();
161-
reset();
176+
mThreading.waitForAll();
177+
const QString error = mThreading.errorMessage();
162178
QLOG_INFO() << "ScriptEngineWorker: evaluation ended with message" << error;
163179
emit completed(error, mScriptId);
164180
}
@@ -167,7 +183,7 @@ void ScriptEngineWorker::runDirect(const QString &command, int scriptId)
167183
{
168184
if (!mScriptControl.isInEventDrivenMode()) {
169185
QLOG_INFO() << "ScriptEngineWorker: starting interpretation";
170-
reset();
186+
stopScript();
171187
startScriptEvaluation(scriptId);
172188
mDirectScriptsEngine = createScriptEngine(false);
173189
mScriptControl.run();
@@ -182,7 +198,12 @@ void ScriptEngineWorker::doRunDirect(const QString &command)
182198
if (mDirectScriptsEngine) {
183199
mDirectScriptsEngine->evaluate(command);
184200
if (mDirectScriptsEngine->hasUncaughtException()) {
185-
reset();
201+
QLOG_INFO() << "ScriptEngineWorker : ending interpretation of direct script";
202+
emit completed(mDirectScriptsEngine->hasUncaughtException()
203+
? mDirectScriptsEngine->uncaughtException().toString()
204+
: "", mScriptId);
205+
mDirectScriptsEngine->deleteLater();
206+
mDirectScriptsEngine = nullptr;
186207
}
187208
}
188209
}
@@ -203,7 +224,7 @@ void ScriptEngineWorker::onScriptRequestingToQuit()
203224
mScriptControl.run();
204225
}
205226

206-
reset();
227+
stopScript();
207228
}
208229

209230
QScriptEngine * ScriptEngineWorker::createScriptEngine(bool supportThreads)
@@ -242,7 +263,7 @@ QScriptEngine * ScriptEngineWorker::createScriptEngine(bool supportThreads)
242263
}
243264

244265
if (supportThreads) {
245-
engine->globalObject().setProperty("Threading", engine->newQObject(&mThreadingVariable));
266+
engine->globalObject().setProperty("Threading", engine->newQObject(&mThreading));
246267
}
247268

248269
evalSystemJs(engine);
@@ -290,20 +311,3 @@ void ScriptEngineWorker::evalSystemJs(QScriptEngine * const engine) const
290311
engine->globalObject().setProperty(functionName, functionValue);
291312
}
292313
}
293-
294-
void ScriptEngineWorker::clearBrickState()
295-
{
296-
mBrick.reset();
297-
}
298-
299-
void ScriptEngineWorker::clearMailboxAndGamepadState()
300-
{
301-
if (mMailbox) {
302-
mMailbox->reset();
303-
}
304-
305-
if (mGamepad) {
306-
mGamepad->reset();
307-
}
308-
}
309-

trikScriptRunner/src/scriptEngineWorker.h

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ class ScriptEngineWorker : public QObject
5959
/// Registers given C++ function as callable from script, with given name.
6060
void registerUserFunction(const QString &name, QScriptEngine::FunctionSignature function);
6161

62+
/// Clears execution state and stops robot.
63+
void resetBrick();
64+
65+
/// Stops script execution and resets script engine. Can be called from another thread. By the end of call the
66+
/// worker would be in a ready state.
67+
void stopScript();
68+
6269
signals:
6370
/// Emitted when current script execution is completed or is aborted by reset() call.
6471
/// @param error - localized error message or empty string.
@@ -70,10 +77,6 @@ class ScriptEngineWorker : public QObject
7077
void startedScript(int scriptId);
7178

7279
public slots:
73-
/// Stops script execution and resets execution state (including script engine and trikControl itself). Can be
74-
/// called from another thread. By the end of call to reset() the worker would be in a ready state.
75-
void reset();
76-
7780
/// Starts script evaluation, emits startedScript() signal and returns. Script will be executed asynchronously.
7881
/// completed() signal is emitted upon script abortion or completion.
7982
/// It is a caller's responsibility to ensure that ScriptEngineWorker is in ready state before a call to run()
@@ -110,7 +113,7 @@ private slots:
110113
enum State {
111114
ready
112115
, starting
113-
, resetting
116+
, stopping
114117
, running
115118
};
116119

@@ -120,17 +123,11 @@ private slots:
120123
/// Evaluates "system.js" file in given engine.
121124
void evalSystemJs(QScriptEngine * const engine) const;
122125

123-
/// Part of reset procedure, clears state of brick.
124-
void clearBrickState();
125-
126-
/// Part of reset procedure, clears state of mailbox and gamepad.
127-
void clearMailboxAndGamepadState();
128-
129126
trikControl::BrickInterface &mBrick;
130127
trikNetwork::MailboxInterface * const mMailbox; // Does not have ownership.
131128
trikNetwork::GamepadInterface * const mGamepad; // Does not have ownership.
132129
ScriptExecutionControl &mScriptControl;
133-
Threading mThreadingVariable;
130+
Threading mThreading;
134131
QScriptEngine *mDirectScriptsEngine; // Has ownership.
135132
int mScriptId;
136133
State mState;

trikScriptRunner/src/threading.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class Threading : public QObject
3838
public:
3939
/// Constructs a Threading object with given script worker as a parent.
4040
explicit Threading(ScriptEngineWorker *scriptWorker, ScriptExecutionControl &scriptControl);
41-
~Threading();
41+
~Threading() override;
4242

4343
/// Starts the main thread of a script
4444
void startMainThread(const QString &script);

0 commit comments

Comments
 (0)