git-svn-id: svn://db.shs.com.ru/libs@2 a8b55f48-bf90-11e4-a774-851b48703e85
322 lines
7.9 KiB
C++
322 lines
7.9 KiB
C++
#include "brick_manager.h"
|
|
#include "brick_composite.h"
|
|
|
|
|
|
BrickManager::BrickManager(double frequency, double time_step) {
|
|
timer = new PITimer(run, this, PITimer::ThreadRT);
|
|
setFrequency(frequency, time_step);
|
|
ctime = 0.;
|
|
paused = false;
|
|
wasReset = true;
|
|
mode_ = BrickBase::Asynchronous;
|
|
BrickComposite::fillBaseBricks();
|
|
}
|
|
|
|
|
|
void BrickManager::setFrequency(double frequency, double time_step) {
|
|
freq = frequency;
|
|
tstep = (time_step == 0.) ? 1. / frequency : time_step;
|
|
if (!isRunning()) return;
|
|
stop();
|
|
start();
|
|
}
|
|
|
|
|
|
void BrickManager::addBrick(BrickBase * brick, bool uniqueName) {
|
|
//lock();
|
|
pause();
|
|
brick->saveInputsToDefault();
|
|
if (uniqueName) brick->setName(getUniqueName(brick->name()));
|
|
brick->setManager(this);
|
|
bricks.push_back(brick);
|
|
if (mode_ == BrickBase::Asynchronous) buildSchemeTree();
|
|
resume();
|
|
//unlock();
|
|
}
|
|
|
|
|
|
void BrickManager::removeBrick(BrickBase * brick) {
|
|
for (uint i = 0; i < bricks.size(); ++i) {
|
|
if (bricks[i] == brick) {
|
|
disconnectBrick(brick);
|
|
bricks.remove(i);
|
|
buildSchemeTree();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void BrickManager::replaceBrick(BrickBase * old_b, BrickBase * new_b) {
|
|
PIVector<BrickBase::Connection> conns = old_b->connections;
|
|
PIFlags<BrickBase::IOType> ion = new_b->io_Type;
|
|
BrickBase * cb;
|
|
new_b->setName(getUniqueName(new_b->name()));
|
|
new_b->freqDivider_ = old_b->freqDivider_;
|
|
new_b->manager_ = old_b->manager_;
|
|
if (ion[BrickBase::VariableInputs])
|
|
new_b->setInputsCount(old_b->inputsCount());
|
|
if (ion[BrickBase::VariableOutputs])
|
|
new_b->setOutputsCount(old_b->outputsCount());
|
|
for (uint i = 0; i < bricks.size(); ++i) {
|
|
cb = bricks[i];
|
|
if (cb == old_b) {
|
|
bricks[i] = new_b;
|
|
for (uint j = 0; j < conns.size(); ++j) {
|
|
if (conns[j].out_num > new_b->outputsCount()) continue;
|
|
new_b->addConnection(conns[j]);
|
|
}
|
|
continue;
|
|
}
|
|
for (int j = 0; j < cb->connectionsCount(); ++j) {
|
|
if (cb->connections[j].brick_to != old_b) continue;
|
|
if (cb->connections[j].out_num > new_b->inputsCount())
|
|
cb->removeConnection(j);
|
|
else
|
|
cb->connections[j].brick_to = new_b;
|
|
}
|
|
}
|
|
PIVector<BrickBase * > * tl;
|
|
for (uint i = 0; i < tree.size(); ++i) {
|
|
tl = &tree[i];
|
|
for (uint j = 0; j < tl->size(); ++j) {
|
|
if (tl->at(j) != old_b) continue;
|
|
(*tl)[j] = new_b;
|
|
}
|
|
}
|
|
int pc = piMin<int>(old_b->parametersCount(), new_b->parametersCount()), ic = piMin<int>(old_b->inputsCount(), new_b->inputsCount());
|
|
for (int i = 0; i < pc; ++i)
|
|
new_b->setParameterValueOnly(i, old_b->parameter(i).toString());
|
|
for (int i = 0; i < ic; ++i)
|
|
new_b->setInputValue(i, old_b->input(i));
|
|
//delete old_b;
|
|
}
|
|
|
|
|
|
void BrickManager::tick(bool realTime) {
|
|
//cout << "tick\n";
|
|
if (paused) return;
|
|
wasReset = false;
|
|
if (realTime) {
|
|
//lock();
|
|
switch (mode_) {
|
|
case BrickBase::Synchronous:
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
bricks[i]->tick(ctime);
|
|
proceedConnections();
|
|
break;
|
|
case BrickBase::Asynchronous:
|
|
PIVector<BrickBase * > * tl;
|
|
for (uint i = 0; i < tree.size(); ++i) {
|
|
tl = &tree[i];
|
|
for (uint j = 0; j < tl->size(); ++j)
|
|
(*tl)[j]->tick(ctime);
|
|
for (uint j = 0; j < tl->size(); ++j)
|
|
(*tl)[j]->proceedConnections();
|
|
}
|
|
break;
|
|
}
|
|
ctime += tstep;
|
|
//unlock();
|
|
} else {
|
|
switch (mode_) {
|
|
case BrickBase::Synchronous:
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
if (!bricks[i]->isRealTimeOnly())
|
|
bricks[i]->tick(ctime);
|
|
proceedConnections();
|
|
break;
|
|
case BrickBase::Asynchronous:
|
|
PIVector<BrickBase * > * tl;
|
|
for (uint i = 0; i < tree.size(); ++i) {
|
|
tl = &tree[i];
|
|
for (uint j = 0; j < tl->size(); ++j)
|
|
if (!(*tl)[j]->isRealTimeOnly())
|
|
(*tl)[j]->tick(ctime);
|
|
for (uint j = 0; j < tl->size(); ++j)
|
|
(*tl)[j]->proceedConnections();
|
|
}
|
|
break;
|
|
}
|
|
ctime += tstep;
|
|
}
|
|
//cout << bricks[0]->output() << endl;
|
|
}
|
|
|
|
|
|
void BrickManager::proceedConnections(bool compositeToo) {
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
bricks[i]->proceedConnections(compositeToo);
|
|
}
|
|
|
|
|
|
void BrickManager::start() {
|
|
paused = false;
|
|
startBricks();
|
|
timer->stop();
|
|
#ifdef WINDOWS
|
|
timer->waitForFinish();
|
|
#endif
|
|
timer->start(1000. / freq);
|
|
}
|
|
|
|
|
|
void BrickManager::stop() {
|
|
paused = false;
|
|
timer->stop();
|
|
stopBricks();
|
|
}
|
|
|
|
|
|
void BrickManager::reset() {
|
|
paused = false;
|
|
wasReset = true;
|
|
if (isRunning()) lock();
|
|
for (int i = 0; i < 3; ++i) {
|
|
resetOutputs();
|
|
proceedConnections(true);
|
|
}
|
|
saveInputsToDefault();
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
bricks[i]->reset();
|
|
ctime = 0.;
|
|
if (isRunning()) unlock();
|
|
}
|
|
|
|
|
|
void BrickManager::resetOutputs() {
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
bricks[i]->resetOutputs();
|
|
}
|
|
|
|
|
|
void BrickManager:: resetScheme() {
|
|
stop();
|
|
paused = false;
|
|
tree.clear();
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
delete bricks[i];
|
|
bricks.clear();
|
|
}
|
|
|
|
|
|
bool BrickManager::loadScheme(const PIString & file) {
|
|
PIConfig sr(file);
|
|
if (!sr.isOpened()) return false;
|
|
resetScheme();
|
|
|
|
setFrequency(sr.getValue("Real-time Frequency", 100), sr.getValue("Real-time Step", 0.));
|
|
setMode((BrickBase::Mode)(int)sr.getValue("Mode", 1));
|
|
PIMathSolver::method_global = static_cast<PIMathSolver::Method>((int)sr.getValue("PIMathSolver", 0));
|
|
|
|
PIStringList names = sr.getValue("Bricks", PIStringList());
|
|
PIString prefix, cname;
|
|
BrickBase * b, * bf, * bt;
|
|
if (BrickComposite::baseBricks.size() == 0)
|
|
BrickComposite::fillBaseBricks();
|
|
for (int i = 0; i < names.size_s(); ++i) {
|
|
prefix = names[i] + " ";
|
|
cname = sr.getValue(prefix + "codeName", "");
|
|
b = BrickComposite::findBaseBrick(cname);
|
|
if (b == 0) {
|
|
piCout << "Error while loading scheme: can`t find brick \"" << cname << "\"";
|
|
continue;
|
|
} else
|
|
b = b->copy();
|
|
loadBrick(sr, prefix, b);
|
|
bricks.push_back(b);
|
|
}
|
|
int cnt = sr.getValue("Connections count", 0);
|
|
for (int i = 0; i < cnt; ++i) {
|
|
prefix = "Connection " + PIString::fromNumber(i) + " ";
|
|
bf = findBrick(sr.getValue(prefix + "from Name", "").value().stdString());
|
|
bt = findBrick(sr.getValue(prefix + "to Name", "").value().stdString());
|
|
if (bf == 0 || bt == 0) {
|
|
piCout << "Error while loading scheme: can`t create connection " << i;
|
|
continue;
|
|
}
|
|
BrickBase::connect(bf, sr.getValue(prefix + "from Port", 0), bt, sr.getValue(prefix + "to Port", 0));
|
|
}
|
|
buildSchemeTree();
|
|
startBricks();
|
|
return true;
|
|
}
|
|
|
|
|
|
void BrickManager::disconnectBrick(BrickBase * brick) {
|
|
for (uint i = 0; i < bricks.size(); ++i) {
|
|
for (int j = 0; j < bricks[i]->connectionsCount(); ++j) {
|
|
if (bricks[i]->connection(j).brick_to == brick)
|
|
bricks[i]->removeConnection(j);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void BrickManager::loadBrick(PIConfig & sr, const PIString & prefix, BrickBase * b) {
|
|
BrickComposite::loadBrick(sr, prefix, b, this);
|
|
}
|
|
|
|
|
|
void BrickManager::saveInputsToDefault() {
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
bricks[i]->saveInputsToDefault();
|
|
}
|
|
|
|
|
|
bool BrickManager::checkUniqueName(const PIString & name, BrickBase * brick) {
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
if ((bricks[i]->name() == name) && (bricks[i] != brick))
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
|
|
PIString BrickManager::getUniqueName(const PIString & name) {
|
|
int cind = 0, di = 0;
|
|
if (name.size() > 0) {
|
|
di = name.size_s() - 1;
|
|
while (name[di].isDigit()) --di;
|
|
di = name.size_s() - di - 1;
|
|
}
|
|
PIString cname, bname;
|
|
if (di > 0) bname = PIString(name).cutRight(di);
|
|
else bname = name + "_";
|
|
cname = bname + PIString::fromNumber(cind);
|
|
bool ok = false;
|
|
while (!ok) {
|
|
ok = true;
|
|
for (uint i = 0; i < bricks.size(); ++i) {
|
|
if (bricks[i]->name() == cname) {
|
|
cind++;
|
|
ok = false;
|
|
break;
|
|
}
|
|
}
|
|
cname = bname + PIString::fromNumber(cind);
|
|
}
|
|
return cname;
|
|
}
|
|
|
|
|
|
BrickBase* BrickManager::findBrick(const PIString & name) {
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
if (bricks[i]->name() == name)
|
|
return bricks[i];
|
|
return 0;
|
|
}
|
|
|
|
|
|
void BrickManager::setMode(BrickBase::Mode m) {
|
|
mode_ = m;
|
|
if (mode_ == BrickBase::Asynchronous) buildSchemeTree();
|
|
else
|
|
for (uint i = 0; i < bricks.size(); ++i)
|
|
bricks[i]->level_ = -666;
|
|
}
|
|
|
|
|
|
void BrickManager::buildSchemeTree() {
|
|
buildTree(bricks, tree);
|
|
}
|