blob: da523dada4f3e8e9900189080f94840f0565aae1 [file] [log] [blame]
#include <BaSyx/controlcomponent/simple/ControlComponent.h>
#include <BaSyx/controlcomponent/enumerations/ControlComponentConstants.h>
namespace basyx {
namespace controlcomponent {
namespace simple {
using constants = basyx::controlcomponent::ControlComponentConstants;
using constants_ = basyx::controlcomponent::ControlComponentConstants_;
ControlComponent::ControlComponent()
: savedOccupierId {""}
, occupationState{OccupationState::free}
, occupier{""}
, lastOccupier{""}
, exMode{ExecutionMode::Auto}
, exState{ExecutionState::idle}
, opMode{""}
, workState{""}
, errorState{""}
, prevError{""}
, cmd{""}
, localOverwrite{""}
, localOverwriteFree{""}
, service_operations{object::make_map()}
{
this->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->service_operations;
}
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->orderList;
}
void ControlComponent::addOrder(const std::string &newOrder)
{
this->orderList.push_back(newOrder);
}
void ControlComponent::clearOrder()
{
this->orderList.clear();
}
OccupationState ControlComponent::getOccupationState()
{
return static_cast<OccupationState>(this->occupationState);
}
void ControlComponent::setOccupationState(const OccupationState &occState)
{
this->occupationState = occState;
this->notify_change_listeners_on_variable_change(constants::occupationState, (int) occState);
for (auto listener : this->componentChangeListeners)
{
listener.second->onNewOccupationState(occState);
}
}
std::string ControlComponent::getOccupierID()
{
return this->occupier;
}
void ControlComponent::setOccupierID(const std::string &occId)
{
this->occupier = occId;
this->notify_change_listeners_on_variable_change(constants::occupier, occId);
for (auto listener : this->componentChangeListeners)
{
listener.second->onNewOccupier(occId);
}
}
std::string ControlComponent::getLastOccupierID()
{
return this->lastOccupier;
}
void ControlComponent::setLastOccupierID(const std::string &occId)
{
this->lastOccupier = occId;
this->notify_change_listeners_on_variable_change(constants::lastOccupier, occId);
for (auto listener : this->componentChangeListeners)
{
listener.second->onLastOccupier(occId);
}
}
ExecutionMode ControlComponent::getExecutionMode()
{
return this->exMode;
}
void ControlComponent::setExecutionMode(const ExecutionMode &exMode)
{
this->exMode = exMode;
this->notify_change_listeners_on_variable_change(constants::exMode, (int) exMode);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedExecutionMode(exMode);
}
}
ExecutionState ControlComponent::getExecutionState()
{
return this->exState;
}
void ControlComponent::setExecutionState(const ExecutionState &newSt)
{
this->exState = newSt;
this->notify_change_listeners_on_variable_change(constants::exState, ExecutionState_::to_string(newSt));
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedExecutionState(newSt);
}
}
std::string ControlComponent::getOperationMode()
{
return this->opMode;
}
void ControlComponent::setOperationMode(const std::string &opMode)
{
this->opMode = opMode;
this->notify_change_listeners_on_variable_change(constants::opMode, opMode);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedOperationMode(opMode);
}
}
std::string ControlComponent::getWorkState()
{
return this->workState;
}
void ControlComponent::setWorkState(const std::string &workState)
{
this->workState = workState;
this->notify_change_listeners_on_variable_change(constants::workState, workState);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedWorkState(workState);
}
}
std::string ControlComponent::getErrorState()
{
return this->errorState;
}
void ControlComponent::setErrorState(const std::string &errorState)
{
this->errorState = errorState;
this->notify_change_listeners_on_variable_change(constants::errorState, errorState);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedErrorState(errorState);
}
}
std::string ControlComponent::getLastErrorState()
{
return this->prevError;
}
void ControlComponent::setLastErrorState(const std::string &lastErrorState)
{
this->errorState = lastErrorState;
this->notify_change_listeners_on_variable_change(constants::errorState, lastErrorState);
for (auto listener : this->componentChangeListeners)
{
listener.second->onChangedPrevError(lastErrorState);
}
}
std::string ControlComponent::getCommand()
{
return this->cmd;
}
void ControlComponent::setCommand(const std::string &cmd)
{
this->cmd = cmd;
}
std::string ControlComponent::getLocalOverwrite()
{
return this->localOverwrite;
}
void ControlComponent::setLocalOverwrite(const std::string &cmd)
{
this->localOverwrite = cmd;
}
std::string ControlComponent::getLocalOverwriteFree()
{
return this->localOverwriteFree;
}
void ControlComponent::setLocalOverwriteFree(const std::string &cmd)
{
this->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::notify_change_listeners_on_variable_change(const ControlComponentConstants &status_key, T status)
{
for (auto listener : this->componentChangeListeners)
{
listener.second->onVariableChange(constants_::to_string(status_key), status);
}
}
void ControlComponent::init_service_operations()
{
// All lambdas returning bool since this is supported by vab
this->service_operations.insertKey(constants_::to_string(constants::free), object::make_function([this](std::string senderId) {
this->freeControlComponent(senderId);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::occupy), object::make_function([this](std::string occupier) {
this->occupyControlComponent(occupier);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::priority), object::make_function([this](std::string occupier) {
this->priorityOccupation(occupier);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::Auto), object::make_function([this]() {
this->setExecutionMode(ExecutionMode::Auto);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::semiauto), object::make_function([this]() {
this->setExecutionMode(ExecutionMode::Semiauto);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::manual), object::make_function([this]() {
this->setExecutionMode(ExecutionMode::Manual);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::simulation), object::make_function([this]() {
this->setExecutionMode(ExecutionMode::Simulation);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::start), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::start);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::reset), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::reset);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::hold), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::hold);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::unhold), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::unhold);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::suspend), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::suspend);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::unsuspend), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::unsuspend);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::abort), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::abort);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::stop), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::stop);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::clear), object::make_function([this]() {
this->changeExecutionState(ExecutionOrder::clear);
return true;
}));
this->service_operations.insertKey(constants_::to_string(constants::bstate), object::make_function([this]() {
this->setOperationMode(std::string {"BSTATE"});
return true;
}));
}
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);
}
}
}
}
}