blob: f8f431a9486aca93656c197e760967686678724a [file] [log] [blame]
#include <BaSyx/controlcomponent/map/ControlComponent.h>
#include <BaSyx/controlcomponent/enumerations/ControlComponentConstants.h>
namespace basyx {
namespace controlcomponent {
namespace map {
using constants = basyx::controlcomponent::ControlComponentConstants;
using constants_ = basyx::controlcomponent::ControlComponentConstants_;
ControlComponent::ControlComponent()
: vab::ElementMap {}, savedOccupierId {""}, status_map {object::make_map()}, operations {object::make_map()}
{
this->map.insertKey(constants_::to_string(constants::orderList), std::vector<std::string>{});
//initialize status map
this->map.insertKey(constants_::to_string(constants::status), this->status_map);
this->insert_status(constants::occupationState, (int) OccupationState::free);
this->insert_status(constants::occupier, "");
this->insert_status(constants::lastOccupier, "");
this->insert_status(constants::exMode, (int) ExecutionMode::Auto);
this->insert_status(constants::exState, ExecutionState_::to_string(ExecutionState::idle));
this->insert_status(constants::opMode, "");
this->insert_status(constants::workState, "");
this->insert_status(constants::errorState, "");
this->insert_status(constants::prevError, "");
//initialize input signals
this->map.insertKey(constants_::to_string(constants::cmd), "");
this->map.insertKey(constants_::to_string(constants::localOverwrite), "");
this->map.insertKey(constants_::to_string(constants::localOverwriteFree), "");
// Add operations map
this->map.insertKey(constants_::to_string(constants::operations), this->operations);
this->operations.insertKey(constants_::to_string(constants::service), init_service_operations());
}
void ControlComponent::addControlComponentChangeListener(const std::shared_ptr<IControlComponentChangeListener> listener)
{
this->componentChangeListeners.emplace(listener->getUniqueID(), listener);
}
void ControlComponent::removeControlComponentChangeListener(const std::shared_ptr<IControlComponentChangeListener> listener)
{
this->componentChangeListeners.erase(listener->getUniqueID());
}
const basyx::object ControlComponent::getServiceOperationMap()
{
return this->map.getProperty(constants_::to_string(constants::operations)).getProperty(constants_::to_string(constants::service));
}
void ControlComponent::put(const std::string &key, object value)
{
this->map.insertKey(key, value);
// Indicate value change
for (auto listener : componentChangeListeners)
{
listener.second->onVariableChange(key, value);
}
// Process variable changes
switch (constants_::from_string(key))
{
case constants::cmd:
{
this->changeExecutionState(ExecutionOrder_::from_string(value.Get<std::string>()));
break;
}
case constants::localOverwrite:
{
this->invokeLocalOverwrite();
break;
}
case constants::localOverwriteFree:
{
this->clearLocalOverwrite();
break;
}
}
}
void ControlComponent::finishState()
{
switch (this->getExecutionState())
{
case ExecutionState::starting:
{
this->setExecutionState(ExecutionState::execute);
return;
}
case ExecutionState::execute:
{
this->setExecutionState(ExecutionState::completing);
return;
}
case ExecutionState::completing:
{
this->setExecutionState(ExecutionState::complete);
return;
}
case ExecutionState::resetting:
{
this->setExecutionState(ExecutionState::idle);
return;
}
case ExecutionState::holding:
{
this->setExecutionState(ExecutionState::held);
return;
}
case ExecutionState::unholding:
{
this->setExecutionState(ExecutionState::execute);
return;
}
case ExecutionState::suspending:
{
this->setExecutionState(ExecutionState::suspended);
return;
}
case ExecutionState::unsuspending:
{
this->setExecutionState(ExecutionState::execute);
return;
}
case ExecutionState::stopping:
{
this->setExecutionState(ExecutionState::stopped);
return;
}
case ExecutionState::stopped:
{
this->setExecutionState(ExecutionState::idle);
return;
}
case ExecutionState::aborting:
{
this->setExecutionState(ExecutionState::aborted);
return;
}
case ExecutionState::clearing:
{
this->setExecutionState(ExecutionState::stopped);
return;
}
}
}
const std::vector<std::string> & ControlComponent::getOrderList()
{
return *this->map.getProperty(constants_::to_string(constants::orderList)).GetPtr<std::vector<std::string>>();
}
void ControlComponent::addOrder(const std::string &newOrder)
{
this->map.getProperty(constants_::to_string(constants::orderList)).GetPtr<std::vector<std::string>>()->push_back(newOrder);
}
void ControlComponent::clearOrder()
{
this->map.getProperty(constants_::to_string(constants::orderList)).GetPtr<object::list_t<std::string>>()->clear();
}
OccupationState ControlComponent::getOccupationState()
{
return static_cast<OccupationState>(this->status_map.getProperty(constants_::to_string(constants::occupationState)).Get<int>());
}
void ControlComponent::setOccupationState(const OccupationState &occState)
{
this->insert_status(constants::occupationState, (int) occState);
for (auto listener : this->componentChangeListeners)
{
listener.second->onNewOccupationState(occState);
}
}
std::string ControlComponent::getOccupierID()
{
return this->get_status<std::string>(constants::occupier);
}
void ControlComponent::setOccupierID(const std::string &occId)
{
this->insert_status(constants::occupier, occId);
for (auto listener : this->componentChangeListeners)
{
listener.second->onNewOccupier(occId);
}
}
std::string ControlComponent::getLastOccupierID()
{
return this->get_status<std::string>(constants::lastOccupier);
}
void ControlComponent::setLastOccupierID(const std::string &occId)
{
this->insert_status(constants::lastOccupier, occId);
for (auto listener : this->componentChangeListeners)
{
listener.second->onLastOccupier(occId);
}
}
ExecutionMode ControlComponent::getExecutionMode()
{
return (ExecutionMode) this->get_status<int>(constants::exMode);
}
void ControlComponent::setExecutionMode(const ExecutionMode &exMode)
{
this->insert_status(constants::exMode, (int) exMode);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedExecutionMode(exMode);
}
}
ExecutionState ControlComponent::getExecutionState()
{
return ExecutionState_::from_string(this->get_status<std::string>(constants::exState));
}
void ControlComponent::setExecutionState(const ExecutionState &newSt)
{
this->insert_status(constants::exState, ExecutionState_::to_string(newSt));
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedExecutionState(newSt);
}
}
std::string ControlComponent::getOperationMode()
{
return this->get_status<std::string>(constants::opMode);
}
void ControlComponent::setOperationMode(const std::string &opMode)
{
this->insert_status(constants::opMode, opMode);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedOperationMode(opMode);
}
}
std::string ControlComponent::getWorkState()
{
return this->get_status<std::string>(constants::workState);
}
void ControlComponent::setWorkState(const std::string &workState)
{
this->insert_status(constants::workState, workState);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedWorkState(workState);
}
}
std::string ControlComponent::getErrorState()
{
return this->get_status<std::string>(constants::errorState);
}
void ControlComponent::setErrorState(const std::string &errorState)
{
this->insert_status(constants::errorState, errorState);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedErrorState(errorState);
}
}
std::string ControlComponent::getLastErrorState()
{
return this->get_status<std::string>(constants::prevError);
}
void ControlComponent::setLastErrorState(const std::string &lastErrorState)
{
this->insert_status(constants::errorState, lastErrorState);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedPrevError(lastErrorState);
}
}
std::string ControlComponent::getCommand()
{
return this->map.getProperty(constants_::to_string(constants::cmd)).GetStringContent();
}
void ControlComponent::setCommand(const std::string &cmd)
{
this->map.insertKey(constants_::to_string(constants::cmd), cmd);
}
std::string ControlComponent::getLocalOverwrite()
{
return this->map.getProperty(constants_::to_string(constants::localOverwrite)).GetStringContent();
}
void ControlComponent::setLocalOverwrite(const std::string &cmd)
{
this->map.insertKey(constants_::to_string(constants::localOverwrite), cmd);
}
std::string ControlComponent::getLocalOverwriteFree()
{
return this->map.getProperty(constants_::to_string(constants::localOverwriteFree)).GetStringContent();
}
void ControlComponent::setLocalOverwriteFree(const std::string &cmd)
{
this->map.insertKey(constants_::to_string(constants::localOverwriteFree), cmd);
}
void ControlComponent::changeExecutionState(const ExecutionOrder &ex_order)
{
// Check if execution order leads to valid state in current state
switch (this->getExecutionState())
{
case ExecutionState::idle:
// Process expected orders
if (ex_order == ExecutionOrder::start)
{
this->setExecutionState(ExecutionState::starting);
return;
}
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::starting:
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::execute:
// Process expected orders
if (ex_order == ExecutionOrder::complete)
{
this->setExecutionState(ExecutionState::completing);
return;
}
if (ex_order == ExecutionOrder::hold)
{
this->setExecutionState(ExecutionState::holding);
return;
}
if (ex_order == ExecutionOrder::suspend)
{
this->setExecutionState(ExecutionState::suspending);
return;
}
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::completing:
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::complete:
if (ex_order == ExecutionOrder::reset)
{
this->setExecutionState(ExecutionState::resetting);
return;
}
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::resetting:
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::holding:
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::held:
if (ex_order == ExecutionOrder::unhold)
{
this->setExecutionState(ExecutionState::unholding);
return;
}
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::unholding:
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::suspending:
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::suspended:
if (ex_order == ExecutionOrder::unsuspend)
{
this->setExecutionState(ExecutionState::unsuspending);
return;
}
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::unsuspending:
if (ex_order == ExecutionOrder::stop)
{
this->setExecutionState(ExecutionState::stopping);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::stopping:
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::stopped:
if (ex_order == ExecutionOrder::reset)
{
this->setExecutionState(ExecutionState::resetting);
return;
}
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
case ExecutionState::aborted:
if (ex_order == ExecutionOrder::clear)
{
this->setExecutionState(ExecutionState::clearing);
return;
}
case ExecutionState::clearing:
if (ex_order == ExecutionOrder::abort)
{
this->setExecutionState(ExecutionState::aborting);
return;
}
}
}
void ControlComponent::invokeLocalOverwrite()
{
// Store current occupier because we need to restore it later
this->savedOccupierId = this->getOccupierID();
// Enter local overwrite state
this->setOccupationState(OccupationState::local);
this->setOccupierID(constants_::to_string(constants::LOCAL));
}
void ControlComponent::clearLocalOverwrite()
{
this->setOccupierID(this->savedOccupierId);
// Restore occupier state based on variables
if (this->savedOccupierId.empty())
this->setOccupationState(OccupationState::free);
else if (this->getLastOccupierID().empty())
this->setOccupationState(OccupationState::occupied);
else
this->setOccupationState(OccupationState::priority);
}
template<typename T> void ControlComponent::insert_status(const ControlComponentConstants &status_key, T status)
{
this->status_map.insertKey(constants_::to_string(status_key), status);
for (auto listener : this->componentChangeListeners)
{
listener.second->onVariableChange(constants_::to_string(status_key), status);
}
}
template<typename T> T ControlComponent::get_status(const basyx::controlcomponent::ControlComponentConstants &key)
{
return this->status_map.getProperty(constants_::to_string(key)).Get<T>();
}
object ControlComponent::init_service_operations()
{
object map = object::make_map();
// All lambdas returning bool since this is supported by vab
map.insertKey(constants_::to_string(constants::free), object::make_function([this](std::string senderId) {
this->freeControlComponent(senderId);
return true;
}));
map.insertKey(constants_::to_string(constants::occupy), object::make_function([this](std::string occupier) {
this->occupyControlComponent(occupier);
return true;
}));
map.insertKey(constants_::to_string(constants::priority), object::make_function([this](std::string occupier) {
this->priorityOccupation(occupier);
return true;
}));
map.insertKey(constants_::to_string(constants::Auto), object::make_function([this]() {
this->setExecutionMode(ExecutionMode::Auto);
return true;
}));
map.insertKey(constants_::to_string(constants::semiauto), object::make_function([this]() {
this->setExecutionMode(ExecutionMode::Semiauto);
return true;
}));
map.insertKey(constants_::to_string(constants::manual), object::make_function([this]() {
this->setExecutionMode(ExecutionMode::Manual);
return true;
}));
map.insertKey(constants_::to_string(constants::simulation), object::make_function([this]() {
this->setExecutionMode(ExecutionMode::Simulation);
return true;
}));
map.insertKey(constants_::to_string(constants::start), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::start);
return true;
}));
map.insertKey(constants_::to_string(constants::reset), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::reset);
return true;
}));
map.insertKey(constants_::to_string(constants::hold), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::hold);
return true;
}));
map.insertKey(constants_::to_string(constants::unhold), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::unhold);
return true;
}));
map.insertKey(constants_::to_string(constants::suspend), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::suspend);
return true;
}));
map.insertKey(constants_::to_string(constants::unsuspend), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::unsuspend);
return true;
}));
map.insertKey(constants_::to_string(constants::abort), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::abort);
return true;
}));
map.insertKey(constants_::to_string(constants::stop), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::stop);
return true;
}));
map.insertKey(constants_::to_string(constants::clear), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::clear);
return true;
}));
map.insertKey(constants_::to_string(constants::bstate), object::make_function([this]() {
this->setOperationMode(std::string {"BSTATE"});
return true;
}));
return map;
}
void ControlComponent::freeControlComponent(const std::string &senderId)
{
if (this->getOccupierID().compare(senderId) == 0)
{
this->setOccupierID(this->getLastOccupierID());
this->setLastOccupierID("");
if (this->getOccupierID().empty())
this->setOccupationState(OccupationState::free);
else
this->setOccupationState(OccupationState::occupied);
}
}
void ControlComponent::occupyControlComponent(const std::string &occupier)
{
if (this->getOccupationState() == OccupationState::free)
{
this->setOccupierID(occupier);
this->setOccupationState(OccupationState::occupied);
}
}
void ControlComponent::priorityOccupation(const std::string &occupier)
{
if ((this->getOccupationState() == OccupationState::free) or (this->getOccupationState() == OccupationState::occupied))
{
this->setLastOccupierID(this->getOccupierID());
this->setOccupierID(occupier);
this->setOccupationState(OccupationState::priority);
}
}
}
}
}