Skip to content

Commit

Permalink
Add ability to set keys on the global blackboard (#527)
Browse files Browse the repository at this point in the history
* Add ability to set keys on the global blackboard

The master plan can specify if its keys are meant for the global
blackboard using the inherit_blackboard flag in the .plc file.
If true, the keys are populated to the global blackboard & the master
plan simply inherits the global blackboard as its own. If false,
the behaviour remains unchanged.

* Fix supplementary tests

* Run pre-commit hooks

* Add support for blackboard default values

* Fix inherit blackboard tests

* Add unit test for global blackboard

* Regenarate plan files, set default value in designer

* Use default value from file

* Regenerate alica turtlesim plans

* Review comment
  • Loading branch information
veerajsk authored Aug 16, 2024
1 parent 2ea37c7 commit 209b61e
Show file tree
Hide file tree
Showing 85 changed files with 475 additions and 99 deletions.
13 changes: 10 additions & 3 deletions alica_engine/include/engine/AlicaContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <atomic>
#include <cassert>
#include <engine/blackboard/BlackboardBlueprint.h>
#include <memory>
#include <optional>
#include <string>
Expand Down Expand Up @@ -302,8 +303,10 @@ class AlicaContext
*
* @return A reference to the global blackboard
*/
const Blackboard& getGlobalBlackboard() const;
Blackboard& editGlobalBlackboard();
[[deprecated("call std::shared_ptr<Blackboard> getGlobalBlackboardShared() instead")]] const Blackboard& getGlobalBlackboard() const;
[[deprecated("call std::shared_ptr<Blackboard> getGlobalBlackboardShared() instead")]] Blackboard& editGlobalBlackboard();

const std::shared_ptr<Blackboard> getGlobalBlackboardShared();

/**
* Add a solver to be used by this alica instance.
Expand Down Expand Up @@ -474,6 +477,7 @@ class AlicaContext
static const std::unordered_map<std::string, Verbosity> _verbosityStringToVerbosityMap;

bool _initialized = false;
std::shared_ptr<Blackboard> _globalBlackboard;

/**
* Initializes yaml configuration.
Expand Down Expand Up @@ -503,7 +507,10 @@ class AlicaContext
*/
AlicaCommunicationHandlers getCommunicationHandlers();

Blackboard _globalBlackboard;
/*
* Load the global blackoard blueprint
*/
std::unique_ptr<BlackboardBlueprint> loadGlobalBlackboardBlueprint();
};

template <class ClockType, class... Args>
Expand Down
3 changes: 1 addition & 2 deletions alica_engine/include/engine/AlicaEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ class AlicaEngine
const TeamObserver& getTeamObserver() const { return _teamObserver; }
TeamObserver& editTeamObserver() { return _teamObserver; }

const Blackboard& getGlobalBlackboard() const { return _ctx.getGlobalBlackboard(); }
Blackboard& editGlobalBlackboard() { return _ctx.editGlobalBlackboard(); }
const std::shared_ptr<Blackboard> getGlobalBlackboard() { return _ctx.getGlobalBlackboardShared(); }

// Data Access:
const RoleSet* getRoleSet() const { return _roleSet; }
Expand Down
2 changes: 1 addition & 1 deletion alica_engine/include/engine/BasicBehaviour.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class EntryPoint;

struct BehaviourContext
{
Blackboard& globalBlackboard;
std::shared_ptr<Blackboard> globalBlackboard;
const std::string name;
const Behaviour* behaviourModel;
const IAlicaTraceFactory* traceFactory;
Expand Down
2 changes: 1 addition & 1 deletion alica_engine/include/engine/BasicPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Transition;

struct PlanContext
{
Blackboard& globalBlackboard;
std::shared_ptr<Blackboard> globalBlackboard;
const std::string name;
const Plan* planModel;
const IAlicaTraceFactory* traceFactory;
Expand Down
4 changes: 2 additions & 2 deletions alica_engine/include/engine/PlanBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class PlanBase
public:
PlanBase(ConfigChangeListener& configChangeListener, const AlicaClock& clock, const IAlicaCommunication& communicator, IRoleAssignment& roleAssignment,
SyncModule& syncModule, AuthorityManager& authorityManager, TeamObserver& teamObserver, TeamManager& teamManager,
const PlanRepository& planRepository, std::atomic<bool>& stepEngine, std::atomic<bool>& stepCalled, Blackboard& globalBlackboard,
const PlanRepository& planRepository, std::atomic<bool>& stepEngine, std::atomic<bool>& stepCalled, std::shared_ptr<Blackboard> globalBlackboard,
VariableSyncModule& resultStore, const std::unordered_map<size_t, std::unique_ptr<ISolverBase>>& solvers, const IAlicaTimerFactory& timerFactory,
const IAlicaTraceFactory* traceFactory);
~PlanBase();
Expand Down Expand Up @@ -95,7 +95,7 @@ class PlanBase
const PlanRepository& _planRepository;
std::atomic<bool>& _stepEngine;
std::atomic<bool>& _stepCalled;
Blackboard& _globalBlackboard;
std::shared_ptr<Blackboard> _globalBlackboard;
RuntimePlanFactory _runTimePlanFactory;
RuntimeBehaviourFactory _runTimeBehaviourFactory;
VariableSyncModule& _resultStore;
Expand Down
4 changes: 2 additions & 2 deletions alica_engine/include/engine/RuleBook.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class RuleBook
void resetChangeOccurred() { _changeOccurred = false; }
PlanSelector* getPlanSelector() const { return _ps.get(); }
void reload(const YAML::Node& config);
void init(const Blackboard* globalBlackboard);
void init(std::shared_ptr<const Blackboard> globalBlackboard);

private:
static constexpr const char* LOGNAME = "Rulebook";
Expand All @@ -56,7 +56,7 @@ class RuleBook
int _maxConsecutiveChanges;
bool _autoFailureHandlingEnabled;
bool _changeOccurred;
const Blackboard* _globalBlackboard;
std::shared_ptr<const Blackboard> _globalBlackboard;

PlanChange synchTransitionRule(RunningPlan& rp);
PlanChange transitionRule(RunningPlan& r);
Expand Down
6 changes: 3 additions & 3 deletions alica_engine/include/engine/RunnableObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class RunnableObject
protected:
using TracingType = TraceRunnableObject::TracingType;

RunnableObject(Blackboard& globalBlackboard, const IAlicaTraceFactory* tf, const std::string& name = "");
RunnableObject(std::shared_ptr<Blackboard> globalBlackboard, const IAlicaTraceFactory* tf, const std::string& name = "");
virtual ~RunnableObject() = default;

static constexpr int DEFAULT_MS_INTERVAL = 100;
Expand All @@ -108,7 +108,7 @@ class RunnableObject
RunningPlan* getPlanContext() const { return _runningplanContext; }
const std::shared_ptr<Blackboard> getBlackboard() { return _blackboard; }
const BlackboardBlueprint* getBlackboardBlueprint() const { return _blackboardBlueprint; }
Blackboard* getGlobalBlackboard() { return &_globalBlackboard; };
const std::shared_ptr<Blackboard> getGlobalBlackboard() { return _globalBlackboard; };

void start(RunningPlan* rp);
void stop();
Expand Down Expand Up @@ -149,7 +149,7 @@ class RunnableObject
std::unique_ptr<IAlicaTimer> _activeRunTimer;
const BlackboardBlueprint* _blackboardBlueprint;
std::shared_ptr<Blackboard> _blackboard;
Blackboard& _globalBlackboard;
std::shared_ptr<Blackboard> _globalBlackboard;

// Map from ConfAbstractPlanWrapper id to associated attachment
// Only plan will have these
Expand Down
8 changes: 4 additions & 4 deletions alica_engine/include/engine/RunningPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@ class RunningPlan : public std::enable_shared_from_this<RunningPlan>
bool allocationNeeded;
mutable std::atomic<EvalStatus> runTimeConditionStatus;
};
explicit RunningPlan(ConfigChangeListener& configChangeListener, const AlicaClock& clock, const Blackboard& globalBlackboard,
explicit RunningPlan(ConfigChangeListener& configChangeListener, const AlicaClock& clock, std::shared_ptr<const Blackboard> globalBlackboard,
const RuntimePlanFactory& runTimePlanFactory, TeamObserver& teamObserver, TeamManager& teamManager, const PlanRepository& planRepository,
VariableSyncModule& resultStore, const std::unordered_map<size_t, std::unique_ptr<ISolverBase>>& solvers);
RunningPlan(ConfigChangeListener& configChangeListener, const AlicaClock& clock, const Blackboard& globalBlackboard, TeamObserver& teamObserver,
TeamManager& teamManager, const PlanRepository& planRepository, VariableSyncModule& resultStore,
RunningPlan(ConfigChangeListener& configChangeListener, const AlicaClock& clock, std::shared_ptr<const Blackboard> globalBlackboard,
TeamObserver& teamObserver, TeamManager& teamManager, const PlanRepository& planRepository, VariableSyncModule& resultStore,
const std::unordered_map<size_t, std::unique_ptr<ISolverBase>>& solvers, const RuntimePlanFactory& runTimePlanFactory,
const RuntimeBehaviourFactory& runTimeBehaviourFactory, const AbstractPlan* abstractPlan, const ConfAbstractPlanWrapper* wrapper);
static void init(const YAML::Node& config);
Expand Down Expand Up @@ -262,7 +262,7 @@ class RunningPlan : public std::enable_shared_from_this<RunningPlan>

// engine Pointer
const AlicaClock& _clock;
const Blackboard& _globalBlackboard;
std::shared_ptr<const Blackboard> _globalBlackboard;
const RuntimePlanFactory& _runTimePlanFactory;
TeamObserver& _teamObserver;
TeamManager& _teamManager;
Expand Down
6 changes: 3 additions & 3 deletions alica_engine/include/engine/RuntimeBehaviourFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ class IAlicaTimerFactory;
class RuntimeBehaviourFactory
{
public:
RuntimeBehaviourFactory(Blackboard& globalBlackboard, TeamManager& teamManager, PlanBase& planBase, const IAlicaCommunication& communication,
const IAlicaTraceFactory* traceFactory, const IAlicaTimerFactory& timerFactory);
RuntimeBehaviourFactory(std::shared_ptr<Blackboard> globalBlackboard, TeamManager& teamManager, PlanBase& planBase,
const IAlicaCommunication& communication, const IAlicaTraceFactory* traceFactory, const IAlicaTimerFactory& timerFactory);
~RuntimeBehaviourFactory() = default;
void init(std::unique_ptr<IBehaviourCreator>&& bc);

std::unique_ptr<BasicBehaviour> create(int64_t id, const Behaviour* behaviourModel) const;

private:
std::unique_ptr<IBehaviourCreator> _creator;
Blackboard& _globalBlackboard;
std::shared_ptr<Blackboard> _globalBlackboard;
TeamManager& _teamManager;
PlanBase& _planBase;
const IAlicaCommunication& _communication;
Expand Down
6 changes: 3 additions & 3 deletions alica_engine/include/engine/RuntimePlanFactory.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@ class IAlicaTimerFactory;
class RuntimePlanFactory
{
public:
RuntimePlanFactory(
Blackboard& globalBlackboard, const IAlicaTraceFactory* traceFactory, const TeamManager& teamManager, const IAlicaTimerFactory& timerFactory);
RuntimePlanFactory(std::shared_ptr<Blackboard> globalBlackboard, const IAlicaTraceFactory* traceFactory, const TeamManager& teamManager,
const IAlicaTimerFactory& timerFactory);
~RuntimePlanFactory() = default;
void init(std::unique_ptr<IPlanCreator>&& pc);

std::unique_ptr<BasicPlan> create(int64_t id, const Plan* planModel) const;

private:
std::unique_ptr<IPlanCreator> _creator;
Blackboard& _globalBlackboard;
std::shared_ptr<Blackboard> _globalBlackboard;
const IAlicaTraceFactory* _traceFactory;
const TeamManager& _teamManager;
const IAlicaTimerFactory& _timerFactory;
Expand Down
10 changes: 8 additions & 2 deletions alica_engine/include/engine/blackboard/Blackboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,14 @@ class BlackboardImpl
typeIndex = BB_VALUE_TYPE_ANY_INDEX;
}
try {
// insert a default constructed value
_vals.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(makeBBValueForIndex<false>::make(typeIndex.value())));
// insert a default constructed value or construct from the specified default value for the key
if (keyInfo.defaultValue.empty()) {
_vals.emplace(
std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(makeBBValueForIndex<false>::make(typeIndex.value())));
} else {
_vals.emplace(std::piecewise_construct, std::forward_as_tuple(key),
std::forward_as_tuple(makeBBValueForIndex<true>::make(typeIndex.value(), keyInfo.defaultValue)));
}
} catch (const std::exception& ex) {
throw BlackboardException(stringify("Could not initialize key: ", key, " with value of type: ", keyInfo.type, ", details: ", ex.what()));
}
Expand Down
5 changes: 3 additions & 2 deletions alica_engine/include/engine/blackboard/BlackboardBlueprint.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ class BlackboardBlueprint
{
std::string type;
std::string access;
std::string defaultValue;
};

public:
using const_iterator = std::unordered_map<std::string, KeyInfo>::const_iterator;

void addKey(const std::string& key, const std::string& type, const std::string& access)
void addKey(const std::string& key, const std::string& type, const std::string& access, const std::string& defaultValue = std::string{})
{
_keyInfo.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(KeyInfo{type, access}));
_keyInfo.emplace(std::piecewise_construct, std::forward_as_tuple(key), std::forward_as_tuple(KeyInfo{type, access, defaultValue}));
}
const_iterator begin() const { return _keyInfo.begin(); }
const_iterator end() const { return _keyInfo.end(); }
Expand Down
2 changes: 1 addition & 1 deletion alica_engine/include/engine/model/Condition.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Condition : public AlicaElement

const std::shared_ptr<BasicCondition>& getBasicCondition() const { return _basicCondition; }

bool evaluate(const RunningPlan& rp, const Blackboard* globalBlackboard) const;
bool evaluate(const RunningPlan& rp, std::shared_ptr<const Blackboard> globalBlackboard) const;

std::string getLibraryName() const;

Expand Down
1 change: 1 addition & 0 deletions alica_engine/include/engine/modelmanagement/Strings.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ static const std::string normalStateType = "State";
static const std::string isSuccessState = "success";
static const std::string inheritBlackboard = "inheritBlackboard";
static const std::string key = "key";
static const std::string defaultValue = "defaultValue";
static const std::string transitionCondition = "transitionCondition";
static const std::string transitionConditionRepository = "transitionConditionRepository";
static const std::string libraryName = "libraryName";
Expand Down
2 changes: 1 addition & 1 deletion alica_engine/include/engine/planselector/PlanSelector.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class PlanSelector

RunningPlan* createRunningPlan(RunningPlan* planningParent, const PlanGrp& plans, const AgentGrp& robotIDs, const RunningPlan* oldRp,
const PlanType* relevantPlanType, double& o_oldUtility, const ConfAbstractPlanWrapper* wrapper);
void setGlobalBlackboard(const Blackboard* globalBlackboard);
void setGlobalBlackboard(std::shared_ptr<const Blackboard> globalBlackboard);

private:
static constexpr const char* LOGNAME = "PlanSelector";
Expand Down
39 changes: 37 additions & 2 deletions alica_engine/src/engine/AlicaContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
#include "engine/Types.h"
#include "engine/constraintmodul/VariableSyncModule.h"
#include "engine/logging/AlicaDefaultLogger.h"
#include "engine/modelmanagement/factories/BlackboardBlueprintFactory.h"

#include <engine/FileSystem.h>
#include <engine/modelmanagement/Strings.h>
#include <memory>
#include <yaml-cpp/node/node.h>
#include <yaml-cpp/node/parse.h>

namespace alica
{
Expand All @@ -25,11 +30,36 @@ AlicaContext::AlicaContext(const AlicaContextParams& alicaContextParams)
, _configRootNode(initConfig(alicaContextParams.configPaths, alicaContextParams.agentName))
, _validTag(ALICA_CTX_GOOD)
, _clock(std::make_unique<AlicaClock>())
, _globalBlackboard(std::make_shared<Blackboard>(loadGlobalBlackboardBlueprint().get()))
{
// reset the logger but this time the config is read
setLogger<AlicaDefaultLogger>();
}

std::unique_ptr<BlackboardBlueprint> AlicaContext::loadGlobalBlackboardBlueprint()
{
std::string filePath;
for (const auto& folder : _alicaContextParams.configPaths) {
if (essentials::FileSystem::findFile(folder, _alicaContextParams.masterPlanName + alica::Strings::plan_extension, filePath)) {
break;
}
}
if (filePath.empty()) {
AlicaEngine::abort(LOGNAME, "Master file not found, aborting");
}
YAML::Node masterPlanNode;
try {
masterPlanNode = YAML::LoadFile(filePath);
} catch (YAML::BadFile& badFile) {
AlicaEngine::abort(LOGNAME, "Could not load master file: ", filePath, ", error details- ", badFile.msg, ", aborting");
}
auto inheritBlackboard = Factory::getValue<bool>(masterPlanNode, alica::Strings::inheritBlackboard, false);
if (inheritBlackboard && Factory::isValid(masterPlanNode[alica::Strings::blackboard])) {
return BlackboardBlueprintFactory::create(masterPlanNode[alica::Strings::blackboard]);
}
return BlackboardBlueprintFactory::createEmpty();
}

AlicaContext::~AlicaContext()
{
if (_initialized) {
Expand Down Expand Up @@ -65,7 +95,7 @@ int AlicaContext::init(AlicaCreators&& creatorCtx, bool delayStart)
_communicator->startCommunication();

if (_engine->init(std::move(creatorCtx))) {
LockedBlackboardRW gbb(_globalBlackboard);
LockedBlackboardRW gbb(*_globalBlackboard);
gbb.set("agentName", _engine->getLocalAgentName());
gbb.set("agentId", _engine->getTeamManager().getLocalAgentID());
if (!delayStart) {
Expand Down Expand Up @@ -225,10 +255,15 @@ ISolverBase& AlicaContext::getSolverBase(const std::type_info& solverType) const

const Blackboard& AlicaContext::getGlobalBlackboard() const
{
return _globalBlackboard;
return *_globalBlackboard;
}

Blackboard& AlicaContext::editGlobalBlackboard()
{
return *_globalBlackboard;
}

const std::shared_ptr<Blackboard> AlicaContext::getGlobalBlackboardShared()
{
return _globalBlackboard;
}
Expand Down
2 changes: 1 addition & 1 deletion alica_engine/src/engine/AlicaEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ AlicaEngine::AlicaEngine(AlicaContext& ctx, YAML::Node& config, const AlicaConte
, _variableSyncModule(std::make_unique<VariableSyncModule>(
_configChangeListener, _ctx.getCommunicator(), _ctx.getAlicaClock(), editTeamManager(), _ctx.getTimerFactory()))
, _planBase(_configChangeListener, _ctx.getAlicaClock(), _ctx.getCommunicator(), editRoleAssignment(), editSyncModul(), editAuth(), editTeamObserver(),
editTeamManager(), getPlanRepository(), _stepEngine, _stepCalled, editGlobalBlackboard(), editResultStore(), _ctx.getSolvers(),
editTeamManager(), getPlanRepository(), _stepEngine, _stepCalled, getGlobalBlackboard(), editResultStore(), _ctx.getSolvers(),
getTimerFactory(), getTraceFactory())
{
auto reloadFunctionPtr = std::bind(&AlicaEngine::reload, this, std::placeholders::_1);
Expand Down
4 changes: 2 additions & 2 deletions alica_engine/src/engine/PlanBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace alica
*/
PlanBase::PlanBase(ConfigChangeListener& configChangeListener, const AlicaClock& clock, const IAlicaCommunication& communicator,
IRoleAssignment& roleAssignment, SyncModule& syncModule, AuthorityManager& authorityManager, TeamObserver& teamObserver, TeamManager& teamManager,
const PlanRepository& planRepository, std::atomic<bool>& stepEngine, std::atomic<bool>& stepCalled, Blackboard& globalBlackboard,
const PlanRepository& planRepository, std::atomic<bool>& stepEngine, std::atomic<bool>& stepCalled, std::shared_ptr<Blackboard> globalBlackboard,
VariableSyncModule& resultStore, const std::unordered_map<size_t, std::unique_ptr<ISolverBase>>& solvers, const IAlicaTimerFactory& timerFactory,
const IAlicaTraceFactory* traceFactory)
: _configChangeListener(configChangeListener)
Expand Down Expand Up @@ -117,7 +117,7 @@ void PlanBase::reload(const YAML::Node& config)
*/
void PlanBase::start(const Plan* masterPlan)
{
_ruleBook.init(&_globalBlackboard);
_ruleBook.init(_globalBlackboard);
if (!_running) {
_running = true;
if (_statusMessage) {
Expand Down
8 changes: 4 additions & 4 deletions alica_engine/src/engine/RuleBook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ RuleBook::RuleBook(ConfigChangeListener& configChangeListener, SyncModule& syncM

RuleBook::~RuleBook() {}

void RuleBook::init(const Blackboard* globalBlackboard)
void RuleBook::init(std::shared_ptr<const Blackboard> globalBlackboard)
{
_globalBlackboard = globalBlackboard;
_ps->setGlobalBlackboard(globalBlackboard);
Expand Down Expand Up @@ -424,7 +424,7 @@ PlanChange RuleBook::transitionRule(RunningPlan& r)
continue;
}

if (t->getTransitionCondition()->evaluate(&r, _globalBlackboard, t->getKeyMapping())) {
if (t->getTransitionCondition()->evaluate(&r, _globalBlackboard.get(), t->getKeyMapping())) {
nextState = t->getOutState();
break;
}
Expand Down Expand Up @@ -464,7 +464,7 @@ PlanChange RuleBook::synchTransitionRule(RunningPlan& rp)
continue;
}
if (_syncModule.isTransitionSuccessfullySynchronised(t)) {
if (t->getTransitionCondition()->evaluate(&rp, _globalBlackboard, t->getKeyMapping())) {
if (t->getTransitionCondition()->evaluate(&rp, _globalBlackboard.get(), t->getKeyMapping())) {
// we follow the transition, because it holds and is synchronised
nextState = t->getOutState();
// TODO: Find solution for constraints with new transition conditions
Expand All @@ -476,7 +476,7 @@ PlanChange RuleBook::synchTransitionRule(RunningPlan& rp)
}
} else {
// adds a new synchronisation process or updates existing
_syncModule.setSynchronisation(t, t->getTransitionCondition()->evaluate(&rp, _globalBlackboard, t->getKeyMapping()));
_syncModule.setSynchronisation(t, t->getTransitionCondition()->evaluate(&rp, _globalBlackboard.get(), t->getKeyMapping()));
}
}
if (nextState == nullptr) {
Expand Down
Loading

0 comments on commit 209b61e

Please sign in to comment.