#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 conns = old_b->connections; PIFlags 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 * 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(old_b->parametersCount(), new_b->parametersCount()), ic = piMin(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 * 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 * 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((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); }