Rename hcore=>smocore
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
# Core library
|
||||
add_library(smocore STATIC
|
||||
mind.cpp
|
||||
opts.cpp
|
||||
componentThread.cpp
|
||||
)
|
||||
|
||||
target_include_directories(smocore PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
add_subdirectory(deviceManager)
|
||||
add_subdirectory(senseApis)
|
||||
add_subdirectory(marionette)
|
||||
@@ -0,0 +1,98 @@
|
||||
#include <iostream>
|
||||
#include <componentThread.h>
|
||||
|
||||
namespace hk {
|
||||
|
||||
namespace director {
|
||||
/* The director is the seat of volition in Harikoff. It receives sensor
|
||||
* events from the body and world, and uses them to direct its implexors
|
||||
* to implex new menties. It then loads the menties into canvas for simulation
|
||||
* and correlation with intrins, in order to form new attrimotions and
|
||||
* menties.
|
||||
*/
|
||||
ComponentThread director;
|
||||
}
|
||||
namespace simulator {
|
||||
/* The canvas is the simulation engine in Harikoff. It receives menties and
|
||||
* simulates them in accordance with the instructions from director. It then
|
||||
* re-renders them into perception for director to get feedback.
|
||||
*/
|
||||
ComponentThread canvas;
|
||||
}
|
||||
namespace subconscious {
|
||||
/* The subconscious is the seat of memory in Harikoff. It receives menties
|
||||
* from director and stores them in memory for later recall.
|
||||
*/
|
||||
ComponentThread subconscious;
|
||||
}
|
||||
namespace body {
|
||||
/* The body is a thread that polls, processes, and sends interoceptive sensor
|
||||
* events to director. It enables these events to occur asynchronously,
|
||||
* indepdendent any actions that the other threads are taking.
|
||||
*/
|
||||
ComponentThread body;
|
||||
}
|
||||
namespace world {
|
||||
/* The world performs the same functions as the body, but for extrospective
|
||||
* sensor events.
|
||||
*/
|
||||
ComponentThread world;
|
||||
}
|
||||
|
||||
|
||||
std::unordered_map<std::thread::id, ComponentThread&>
|
||||
ComponentThread::componentThreads =
|
||||
{
|
||||
{director::director.thread.get_id(), director::director},
|
||||
{simulator::canvas.thread.get_id(), simulator::canvas},
|
||||
{subconscious::subconscious.thread.get_id(), subconscious::subconscious},
|
||||
{body::body.thread.get_id(), body::body},
|
||||
{world::world.thread.get_id(), world::world}
|
||||
};
|
||||
|
||||
void ComponentThread::signalThread(std::thread::id id)
|
||||
{
|
||||
auto it = componentThreads.find(id);
|
||||
if (it == componentThreads.end())
|
||||
{
|
||||
throw std::runtime_error(std::string(__func__)
|
||||
+ ": Thread ID not found in componentThreads map");
|
||||
}
|
||||
|
||||
ComponentThread& componentThread = it->second;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(componentThread.startupSync.mutex);
|
||||
componentThread.startupSync.ready = true;
|
||||
}
|
||||
componentThread.startupSync.cv.notify_one();
|
||||
}
|
||||
|
||||
void ComponentThread::main(ComponentThread& self)
|
||||
{
|
||||
// We sleep on spawn until the main thread tells us to continue.
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(self.startupSync.mutex);
|
||||
self.startupSync.cv.wait(lock, [&self]() {
|
||||
return self.startupSync.ready;
|
||||
});
|
||||
}
|
||||
|
||||
std::cout << __func__ << ": Starting event loop." << std::endl;
|
||||
self.getIoService().run();
|
||||
std::cout << __func__ << ": Exiting." << std::endl;
|
||||
}
|
||||
|
||||
void ComponentThread::validateThreadIds(void)
|
||||
{
|
||||
for (const auto& [id, componentThread] : componentThreads)
|
||||
{
|
||||
// std::thread::id() is usable as an invalid ID.
|
||||
if (id == std::thread::id())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Invalid Thread ID.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace hk
|
||||
@@ -0,0 +1,29 @@
|
||||
# Flex/Bison generated files
|
||||
set(LEX_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/deviceSpecl.cc)
|
||||
set(YACC_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/deviceSpecp.cc)
|
||||
set(YACC_HEADER ${CMAKE_CURRENT_BINARY_DIR}/deviceSpecp.hh)
|
||||
|
||||
# Generate Flex/Bison files using custom commands
|
||||
add_custom_command(
|
||||
OUTPUT ${LEX_OUTPUT}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/deviceSpecl.ll ${YACC_HEADER}
|
||||
COMMAND ${FLEX_EXECUTABLE} --header-file=${CMAKE_CURRENT_BINARY_DIR}/deviceSpecl.hh -o ${LEX_OUTPUT} ${CMAKE_CURRENT_SOURCE_DIR}/deviceSpecl.ll
|
||||
COMMENT "Generating deviceSpecl.cc from deviceSpecl.ll"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${YACC_OUTPUT} ${YACC_HEADER}
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/deviceSpecp.yy
|
||||
COMMAND ${BISON_EXECUTABLE} -p deviceSpecp --header=${YACC_HEADER} -o ${YACC_OUTPUT} ${CMAKE_CURRENT_SOURCE_DIR}/deviceSpecp.yy
|
||||
COMMENT "Generating deviceSpecp.cc and deviceSpecp.hh from deviceSpecp.yy"
|
||||
)
|
||||
|
||||
# Device manager library
|
||||
add_library(deviceManager STATIC
|
||||
deviceManager.cpp
|
||||
deviceSpecParser.cpp
|
||||
${LEX_OUTPUT}
|
||||
${YACC_OUTPUT}
|
||||
)
|
||||
|
||||
target_include_directories(deviceManager PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
|
||||
@@ -0,0 +1,37 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <opts.h>
|
||||
#include <deviceManager/deviceManager.h>
|
||||
|
||||
namespace hk {
|
||||
namespace device {
|
||||
|
||||
std::vector<std::shared_ptr<InteroceptorDeviceSpec>>
|
||||
DeviceManager::interoceptorDeviceSpecs;
|
||||
std::vector<std::shared_ptr<ExtrospectorDeviceSpec>>
|
||||
DeviceManager::extrospectorDeviceSpecs;
|
||||
std::vector<std::shared_ptr<SenseDeviceSpec>>
|
||||
DeviceManager::senseDeviceSpecs;
|
||||
|
||||
const std::string DeviceManager::stringifyDeviceSpecs(void)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
for (const auto& spec : DeviceManager::interoceptorDeviceSpecs) {
|
||||
oss << "Interoceptor " << spec->stringify();
|
||||
}
|
||||
|
||||
for (const auto& spec : DeviceManager::extrospectorDeviceSpecs) {
|
||||
oss << "Extrospector " << spec->stringify();
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
} // namespace hk
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
#include <cstdio>
|
||||
#include <deviceManager/deviceManager.h>
|
||||
#include "deviceSpecp.hh"
|
||||
#include "deviceSpecl.hh"
|
||||
|
||||
namespace hk {
|
||||
namespace device {
|
||||
|
||||
std::string DeviceManager::readDeviceFile(const std::string& filename)
|
||||
{
|
||||
std::ifstream file(filename);
|
||||
if (!file.is_open())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Couldn't open deviceSpec file: "
|
||||
+ filename);
|
||||
}
|
||||
|
||||
std::string content(
|
||||
(std::istreambuf_iterator<char>(file)),
|
||||
std::istreambuf_iterator<char>());
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
void DeviceManager::collateAllDeviceSpecs(void)
|
||||
{
|
||||
OptionParser &options = OptionParser::getOptions();
|
||||
allDeviceSpecs = options.deviceSpecs;
|
||||
|
||||
for (const auto& file : options.deviceSpecFiles)
|
||||
{
|
||||
std::string fileContent = readDeviceFile(file);
|
||||
if (!allDeviceSpecs.empty()) {
|
||||
allDeviceSpecs += "||";
|
||||
}
|
||||
allDeviceSpecs += fileContent;
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::parseAllDeviceSpecs(void)
|
||||
{
|
||||
std::unique_ptr<FILE, decltype(&fclose)> input(
|
||||
fmemopen((void*)allDeviceSpecs.c_str(), allDeviceSpecs.size(), "r"),
|
||||
&fclose);
|
||||
|
||||
if (!input)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Failed to fmemopen() a FILE* for "
|
||||
"parsing device specs");
|
||||
}
|
||||
|
||||
deviceSpeclin = input.get();
|
||||
if (deviceSpecpparse())
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Failed to parse device specs. "
|
||||
"Check specs for errors");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace device
|
||||
} // namespace hk
|
||||
@@ -0,0 +1,62 @@
|
||||
%option prefix="deviceSpecl"
|
||||
%option nounput
|
||||
%option noinput
|
||||
%{
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <deviceManager/deviceManager.h>
|
||||
#include "deviceSpecp.hh"
|
||||
%}
|
||||
|
||||
%%
|
||||
"+adev" {
|
||||
deviceSpecplval.chr = yytext[1];
|
||||
return KEYWORD_SPECTYPE_ACTUATOR;
|
||||
}
|
||||
"+edev" {
|
||||
deviceSpecplval.chr = yytext[1];
|
||||
return KEYWORD_SPECTYPE_EXTROSPECTOR;
|
||||
}
|
||||
"+idev" {
|
||||
deviceSpecplval.chr = yytext[1];
|
||||
return KEYWORD_SPECTYPE_INTEROSPECTOR;
|
||||
}
|
||||
"||" { return DOUBLE_PIPE; }
|
||||
"|" { return PIPE; }
|
||||
"(" { return LPAREN; }
|
||||
")" { return RPAREN; }
|
||||
"=" { return EQUALS; }
|
||||
(\\.|[^=\|\(\) \t\r\n])+ {
|
||||
std::string token(yytext);
|
||||
std::string unescaped;
|
||||
unescaped.reserve(token.size());
|
||||
|
||||
for (size_t i = 0; i < token.size(); ++i)
|
||||
{
|
||||
if (token[i] != '\\')
|
||||
{
|
||||
unescaped.push_back(token[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If a backslash is the final char before EOF, just continue so it gets
|
||||
* dropped as a side effect.
|
||||
*/
|
||||
if (i + 1 >= token.size()) { continue; }
|
||||
|
||||
// Else push the char following the backslash.
|
||||
unescaped.push_back(token[++i]);
|
||||
}
|
||||
|
||||
deviceSpecplval.str = strdup(unescaped.c_str());
|
||||
return STRING;
|
||||
}
|
||||
[ \t\r\n]+ { /* ignore all whitespace, including newlines */ }
|
||||
. { return yytext[0]; }
|
||||
%%
|
||||
|
||||
int deviceSpeclwrap(void)
|
||||
{
|
||||
return 1; // Indicate end of input
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
%{
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
#include <user/senseDeviceSpec.h>
|
||||
#include <deviceManager/deviceManager.h>
|
||||
|
||||
#ifndef yylex
|
||||
/* We use different prefixes for the lexer and parser.
|
||||
* * Our lexer's prefix is deviceSpecl.
|
||||
* * Our parser's prefix is deviceSpecp.
|
||||
*
|
||||
* Yacc and Bison don't have a way to handle the scenario where the lexer has
|
||||
* a different prefix from the parser that they generate. They assume that the
|
||||
* lexer must have the same prefix as the parser they generate. So we just use
|
||||
* this #define below to override yacc/bison's presumed prefix for the lexer.
|
||||
*/
|
||||
#error "Yacc should have defined yylex as a preprocessor token, and we need to override it to tell yacc the name of our lex function."
|
||||
#endif
|
||||
#undef yylex
|
||||
#define yylex deviceSpecllex
|
||||
|
||||
#ifdef yytext
|
||||
#undef yytext
|
||||
#endif
|
||||
#define yytext deviceSpecltext
|
||||
|
||||
// Declare the symbols that our lexer will export.
|
||||
int yylex(void);
|
||||
extern char* yytext; // Declare yytext to access the current token text
|
||||
void yyerror(const char *message)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string("deviceSpec parser error: ")
|
||||
+ std::string(message)
|
||||
+ " at token: " + std::string(yytext));
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%union {
|
||||
char* str;
|
||||
char chr;
|
||||
hk::device::SenseDeviceSpec* sensorSpec;
|
||||
hk::device::InteroceptorDeviceSpec* interoceptorSpec;
|
||||
hk::device::ExtrospectorDeviceSpec* extrospectorSpec;
|
||||
std::vector<std::pair<std::string,std::string>>* paramVector;
|
||||
std::pair<std::string,std::string>* param;
|
||||
}
|
||||
|
||||
%token <str> STRING
|
||||
%token PIPE DOUBLE_PIPE LPAREN RPAREN
|
||||
%token <chr> KEYWORD_SPECTYPE_ACTUATOR
|
||||
%token <chr> KEYWORD_SPECTYPE_EXTROSPECTOR KEYWORD_SPECTYPE_INTEROSPECTOR
|
||||
%token EQUALS // Add new token for '='
|
||||
|
||||
%type <paramVector> params opt_params
|
||||
%type <param> param
|
||||
%type <sensorSpec> spec_body
|
||||
%type <interoceptorSpec> interoceptor_spec
|
||||
%type <extrospectorSpec> extrospector_spec
|
||||
|
||||
%%
|
||||
|
||||
file: /* NOTHING */
|
||||
| sensor_specs
|
||||
;
|
||||
|
||||
sensor_specs:
|
||||
sensor_spec
|
||||
| sensor_specs DOUBLE_PIPE sensor_spec
|
||||
;
|
||||
|
||||
sensor_spec:
|
||||
interoceptor_spec
|
||||
| extrospector_spec
|
||||
;
|
||||
|
||||
interoceptor_spec:
|
||||
KEYWORD_SPECTYPE_INTEROSPECTOR PIPE spec_body {
|
||||
auto spec = std::make_shared<hk::device::InteroceptorDeviceSpec>(
|
||||
*static_cast<hk::device::InteroceptorDeviceSpec *>($3));
|
||||
|
||||
spec->sensorType = $1;
|
||||
hk::device::DeviceManager::interoceptorDeviceSpecs.push_back(spec);
|
||||
hk::device::DeviceManager::senseDeviceSpecs.push_back(spec);
|
||||
|
||||
delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
extrospector_spec:
|
||||
KEYWORD_SPECTYPE_EXTROSPECTOR PIPE spec_body {
|
||||
auto spec = std::make_shared<hk::device::ExtrospectorDeviceSpec>(
|
||||
*static_cast<hk::device::ExtrospectorDeviceSpec *>($3));
|
||||
|
||||
spec->sensorType = $1;
|
||||
hk::device::DeviceManager::extrospectorDeviceSpecs.push_back(spec);
|
||||
hk::device::DeviceManager::senseDeviceSpecs.push_back(spec);
|
||||
|
||||
delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
spec_body:
|
||||
STRING PIPE STRING LPAREN opt_params RPAREN PIPE STRING LPAREN opt_params RPAREN PIPE STRING {
|
||||
$$ = new hk::device::SenseDeviceSpec();
|
||||
$$->sensorType = '\0';
|
||||
$$->implexor = std::string($1);
|
||||
$$->api = std::string($3);
|
||||
$$->apiParams = std::move(*$5);
|
||||
$$->provider = std::string($8);
|
||||
$$->providerParams = std::move(*$10);
|
||||
$$->deviceSelector = std::string($13);
|
||||
delete $5;
|
||||
delete $10;
|
||||
}
|
||||
;
|
||||
|
||||
opt_params:
|
||||
params
|
||||
| /* empty */ { $$ = new std::vector<std::pair<std::string,std::string>>(); }
|
||||
;
|
||||
|
||||
params:
|
||||
param {
|
||||
$$ = new std::vector<std::pair<std::string,std::string>>();
|
||||
$$->push_back(*$1);
|
||||
delete $1;
|
||||
}
|
||||
| params PIPE param {
|
||||
$$ = $1;
|
||||
$$->push_back(*$3);
|
||||
delete $3;
|
||||
}
|
||||
;
|
||||
|
||||
param:
|
||||
STRING {
|
||||
$$ = new std::pair<std::string,std::string>($1, "");
|
||||
}
|
||||
| STRING EQUALS {
|
||||
$$ = new std::pair<std::string,std::string>($1, "");
|
||||
}
|
||||
| STRING EQUALS STRING {
|
||||
$$ = new std::pair<std::string,std::string>($1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef _ASSOCIATION_H
|
||||
#define _ASSOCIATION_H
|
||||
|
||||
#include <chronomenon.h>
|
||||
#include <existent.h>
|
||||
|
||||
class Association
|
||||
{
|
||||
public:
|
||||
Association(Quale quale, Chronomenon chron);
|
||||
Association(Quale quale, Existent ex);
|
||||
Association(Quale quale, Existent ex);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef _ATTENTION_GRABBER_H
|
||||
#define _ATTENTION_GRABBER_H
|
||||
|
||||
#include <cstdbool>
|
||||
#include <attentionTrigger.h>
|
||||
#include <chronomenon.h>
|
||||
|
||||
class AttentionGrabber
|
||||
{
|
||||
public:
|
||||
AttentionGrabber(AttentionTrigger cause, Chronomenon chron)
|
||||
: isNull(false)
|
||||
{
|
||||
}
|
||||
|
||||
void setNull(void) { isNull = true; }
|
||||
int operator!(void) { return isNull; }
|
||||
|
||||
public:
|
||||
AttentionTrigger cause;
|
||||
Chronomenon chron;
|
||||
bool isNull;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
#ifndef _ATTENTION_TRIGGER_H
|
||||
#define _ATTENTION_TRIGGER_H
|
||||
|
||||
class AttentionTrigger
|
||||
{};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef _CHRONOMENON_H
|
||||
#define _CHRONOMENON_H
|
||||
|
||||
#include <vector>
|
||||
#include <qualeBundle.h>
|
||||
#include <mentalEntity.h>
|
||||
|
||||
class Chronomenon
|
||||
: public MentalEntity
|
||||
{
|
||||
public:
|
||||
class Timestamp
|
||||
{
|
||||
uintptr_t value;
|
||||
};
|
||||
|
||||
class Duration
|
||||
{
|
||||
uintptr_t value;
|
||||
};
|
||||
|
||||
public:
|
||||
Chronomenon extract(Timestamp start, Duration len);
|
||||
|
||||
public:
|
||||
std::vector<QualeBundle> qualia;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef COMPONENT_THREAD_H
|
||||
#define COMPONENT_THREAD_H
|
||||
|
||||
#include <thread>
|
||||
#include <unordered_map>
|
||||
#include <condition_variable>
|
||||
#include <boost/asio.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace hk {
|
||||
|
||||
class ComponentThread
|
||||
{
|
||||
public:
|
||||
ComponentThread()
|
||||
: work(io_service), startupSync(),
|
||||
thread(ComponentThread::main, std::ref(*this))
|
||||
{}
|
||||
|
||||
boost::asio::io_service& getIoService(void) { return io_service; }
|
||||
|
||||
static boost::asio::io_service& getEventLoop(
|
||||
std::thread::id id = std::this_thread::get_id())
|
||||
{
|
||||
auto it = componentThreads.find(id);
|
||||
if (it == componentThreads.end())
|
||||
{
|
||||
throw std::runtime_error(std::string(__func__)
|
||||
+ ": Thread ID not found in componentThreads map");
|
||||
}
|
||||
|
||||
return it->second.getIoService();
|
||||
}
|
||||
|
||||
static void main(ComponentThread &self);
|
||||
static void signalThread(std::thread::id id);
|
||||
static void validateThreadIds(void);
|
||||
|
||||
public:
|
||||
boost::asio::io_service io_service;
|
||||
boost::asio::io_service::work work;
|
||||
struct StartupSync {
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
bool ready;
|
||||
|
||||
StartupSync() : ready(false) {}
|
||||
} startupSync;
|
||||
|
||||
/* Always ensure that this is last so that the thread is spawned after
|
||||
* everything else.
|
||||
*/
|
||||
std::thread thread;
|
||||
static std::unordered_map<std::thread::id, ComponentThread&> componentThreads;
|
||||
};
|
||||
|
||||
namespace director {
|
||||
extern ComponentThread director;
|
||||
}
|
||||
namespace simulator {
|
||||
extern ComponentThread canvas;
|
||||
}
|
||||
namespace subconscious {
|
||||
extern ComponentThread subconscious;
|
||||
}
|
||||
|
||||
} // namespace hk
|
||||
|
||||
#endif // COMPONENT_THREAD_H
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef _CONCEPT_H
|
||||
#define _CONCEPT_H
|
||||
|
||||
#include <mentalEntity.h>
|
||||
|
||||
class Concept
|
||||
: public MentalEntity
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef DEVICEMANAGER_H
|
||||
#define DEVICEMANAGER_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <opts.h>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <user/senseDeviceSpec.h>
|
||||
|
||||
namespace hk {
|
||||
namespace device {
|
||||
|
||||
class DeviceManager
|
||||
{
|
||||
public:
|
||||
static DeviceManager& getInstance()
|
||||
{
|
||||
static DeviceManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::string readDeviceFile(const std::string& filename);
|
||||
void collateAllDeviceSpecs(void);
|
||||
void parseAllDeviceSpecs(void);
|
||||
static const std::string stringifyDeviceSpecs(void);
|
||||
|
||||
private:
|
||||
DeviceManager() = default;
|
||||
~DeviceManager() = default;
|
||||
DeviceManager(const DeviceManager&) = delete;
|
||||
DeviceManager& operator=(const DeviceManager&) = delete;
|
||||
|
||||
public:
|
||||
std::string allDeviceSpecs;
|
||||
static std::vector<std::shared_ptr<InteroceptorDeviceSpec>>
|
||||
interoceptorDeviceSpecs;
|
||||
static std::vector<std::shared_ptr<ExtrospectorDeviceSpec>>
|
||||
extrospectorDeviceSpecs;
|
||||
static std::vector<std::shared_ptr<SenseDeviceSpec>>
|
||||
senseDeviceSpecs;
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
} // namespace hk
|
||||
|
||||
#endif // DEVICEMANAGER_H
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef DIRECTOR_COMMANDLIST_H
|
||||
#define DIRECTOR_COMMANDLIST_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <mentalEntity.h>
|
||||
|
||||
namespace hk {
|
||||
namespace director {
|
||||
|
||||
/**
|
||||
* @brief Base class for all commands, storing a reference to a mental entity ID.
|
||||
*
|
||||
* Derived classes can extend this to include additional command-specific
|
||||
* data and behavior.
|
||||
*/
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
Command(const MentalEntity::Id menty) : menty(menty) {}
|
||||
|
||||
public:
|
||||
const MentalEntity::Id menty;
|
||||
};
|
||||
|
||||
class CommandList
|
||||
{
|
||||
public:
|
||||
CommandList() = default;
|
||||
|
||||
/**
|
||||
* @brief Used by Director to point to the currently executing command.
|
||||
*
|
||||
* director::Director maintains an internal cursor. As it executes commands
|
||||
* from its internal command list, it advances the cursor to the current
|
||||
* command before executing it.
|
||||
*/
|
||||
class Cursor
|
||||
{
|
||||
public:
|
||||
Cursor(CommandList& commandList)
|
||||
: commandList(commandList), iter(commandList.commands.begin())
|
||||
{}
|
||||
|
||||
void reset() { iter = commandList.commands.begin(); }
|
||||
bool hasNext() const { return iter != commandList.commands.end(); }
|
||||
Cursor next() { return ++(*this); }
|
||||
|
||||
Cursor& operator++() {
|
||||
++iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Cursor(
|
||||
CommandList& commandList,
|
||||
std::vector<Command>::iterator iter)
|
||||
: commandList(commandList), iter(iter)
|
||||
{}
|
||||
|
||||
public:
|
||||
CommandList& commandList;
|
||||
std::vector<Command>::iterator iter;
|
||||
};
|
||||
|
||||
Cursor getCursor() { return Cursor(*this); }
|
||||
void addCommand(const Command& command)
|
||||
{
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<Command> commands;
|
||||
};
|
||||
|
||||
} // namespace director
|
||||
} // namespace hk
|
||||
|
||||
#endif // DIRECTOR_COMMANDLIST_H
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef DIRECTOR_H
|
||||
#define DIRECTOR_H
|
||||
|
||||
#include <config.h>
|
||||
#include <goal.h>
|
||||
|
||||
namespace hk {
|
||||
namespace director {
|
||||
|
||||
class Director {
|
||||
public:
|
||||
Director() = default;
|
||||
~Director() = default;
|
||||
|
||||
Goal purpose;
|
||||
};
|
||||
|
||||
} // namespace director
|
||||
} // namespace hk
|
||||
|
||||
#endif // DIRECTOR_H
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef _GOAL_H
|
||||
#define _GOAL_H
|
||||
|
||||
#include <simulator/scene.h>
|
||||
|
||||
namespace hk {
|
||||
|
||||
class Goal
|
||||
: public simulator::Scene {
|
||||
public:
|
||||
Goal() = default;
|
||||
~Goal() = default;
|
||||
};
|
||||
|
||||
} // namespace hk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef IMPLIX_H
|
||||
#define IMPLIX_H
|
||||
|
||||
namespace hk {
|
||||
namespace implix {
|
||||
|
||||
class Implix
|
||||
{
|
||||
public:
|
||||
Implix() = default;
|
||||
~Implix() = default;
|
||||
};
|
||||
|
||||
} // namespace implix
|
||||
} // namespace hk
|
||||
|
||||
#endif // IMPLIX_H
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef _BODY_H
|
||||
#define _BODY_H
|
||||
|
||||
namespace mrntt {
|
||||
namespace body {
|
||||
|
||||
class Body
|
||||
{
|
||||
public:
|
||||
Body() = default;
|
||||
~Body() = default;
|
||||
};
|
||||
|
||||
} // namespace body
|
||||
} // namespace mrntt
|
||||
|
||||
#endif // _BODY_H
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef MRNTT_BODY_BODYMAP_H
|
||||
#define MRNTT_BODY_BODYMAP_H
|
||||
|
||||
#include <set>
|
||||
#include <cstdint>
|
||||
#include <body/limb.h>
|
||||
|
||||
namespace mrntt {
|
||||
namespace body {
|
||||
|
||||
class BodyMap {
|
||||
public:
|
||||
BodyMap() = default;
|
||||
~BodyMap() = default;
|
||||
|
||||
public:
|
||||
std::set<uint32_t, Limb> limbs;
|
||||
};
|
||||
|
||||
} // namespace body
|
||||
} // namespace mrntt
|
||||
|
||||
#endif // MRNTT_BODY_BODYMAP_H
|
||||
@@ -0,0 +1,66 @@
|
||||
#ifndef MRNTT_BODY_BODYMESSAGE_H
|
||||
#define MRNTT_BODY_BODYMESSAGE_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#include <body/limb.h>
|
||||
#include <body/part.h>
|
||||
|
||||
namespace mrntt {
|
||||
namespace body {
|
||||
|
||||
class BodyMessage
|
||||
{
|
||||
public:
|
||||
BodyMessage() = default;
|
||||
~BodyMessage() = default;
|
||||
};
|
||||
|
||||
class SpotImpactEntry
|
||||
{
|
||||
public:
|
||||
enum class ReportType
|
||||
{
|
||||
PRESSURE,
|
||||
PAIN,
|
||||
PLEASURE,
|
||||
HEAT,
|
||||
COLD
|
||||
};
|
||||
|
||||
SpotImpactEntry(uint32_t _spot, ReportType _type, uint32_t _value)
|
||||
: spot(_spot), type(_type), value(_value)
|
||||
{}
|
||||
~SpotImpactEntry() = default;
|
||||
|
||||
public:
|
||||
uint32_t spot;
|
||||
ReportType type;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
class SpotImpactInd : public BodyMessage
|
||||
{
|
||||
public:
|
||||
SpotImpactInd(Part &_part) : part(_part) {}
|
||||
~SpotImpactInd() = default;
|
||||
|
||||
public:
|
||||
Part ∂
|
||||
std::vector<SpotImpactEntry> entries;
|
||||
};
|
||||
|
||||
class PartMsg : public BodyMessage
|
||||
{
|
||||
public:
|
||||
PartMsg(const Part& _part) : part(_part) {}
|
||||
|
||||
public:
|
||||
const Part& part;
|
||||
};
|
||||
|
||||
} // namespace body
|
||||
} // namespace mrntt
|
||||
|
||||
#endif // MRNTT_BODY_BODYMESSAGE_H
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef MRNTT_BODY_LIMB_H
|
||||
#define MRNTT_BODY_LIMB_H
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <cstdint>
|
||||
|
||||
#include <body/part.h>
|
||||
|
||||
namespace mrntt {
|
||||
namespace body {
|
||||
|
||||
class Limb
|
||||
{
|
||||
public:
|
||||
Limb(uint32_t _id) : id(_id) {}
|
||||
Limb(uint32_t _id,
|
||||
const std::string& _name, const std::string& _desc,
|
||||
const std::string& _loc)
|
||||
: id(_id), name(_name), description(_desc), location(_loc)
|
||||
{}
|
||||
|
||||
~Limb() = default;
|
||||
|
||||
public:
|
||||
uint32_t id;
|
||||
std::string name, description, location;
|
||||
std::set<uint32_t, Part> parts;
|
||||
};
|
||||
|
||||
} // namespace body
|
||||
} // namespace mrntt
|
||||
|
||||
#endif // MRNTT_BODY_LIMB_H
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef _BODY_MAP_H
|
||||
#define _BODY_MAP_H
|
||||
|
||||
#include <set>
|
||||
#include <cstdint>
|
||||
|
||||
#include <body/limb.h>
|
||||
|
||||
namespace mrntt {
|
||||
namespace body {
|
||||
|
||||
class BodyMap {
|
||||
public:
|
||||
BodyMap() = default;
|
||||
~BodyMap() = default;
|
||||
|
||||
std::set<uint32_t, Limb> limbs;
|
||||
};
|
||||
|
||||
} // namespace body
|
||||
} // namespace mrntt
|
||||
|
||||
#endif // _BODY_MAP_H
|
||||
@@ -0,0 +1,48 @@
|
||||
#ifndef BODYPART_H
|
||||
#define BODYPART_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
#include <sensors/interoceptor.h>
|
||||
|
||||
namespace mrntt {
|
||||
namespace body {
|
||||
|
||||
class Spot
|
||||
{
|
||||
public:
|
||||
Spot(uint32_t _id, std::string _description)
|
||||
: id(_id), description(_description)
|
||||
{}
|
||||
|
||||
~Spot() = default;
|
||||
|
||||
public:
|
||||
uint32_t id;
|
||||
std::string description;
|
||||
std::set<uint32_t, Interoceptor> interoceptors;
|
||||
};
|
||||
|
||||
class Part
|
||||
{
|
||||
public:
|
||||
Part(uint32_t _partId, std::string _partName,
|
||||
std::string _partDesc, std::string _partLoc)
|
||||
: id(_partId), name(_partName),
|
||||
description(_partDesc), location(_partLoc)
|
||||
{}
|
||||
|
||||
~Part() = default;
|
||||
|
||||
public:
|
||||
const uint32_t id;
|
||||
std::string name, description, location;
|
||||
std::set<uint32_t, Spot> spots;
|
||||
};
|
||||
|
||||
} // namespace body
|
||||
} // namespace mrntt
|
||||
|
||||
#endif // BODYPART_H
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef _MARIONETTE_H
|
||||
#define _MARIONETTE_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace mrntt {
|
||||
|
||||
class Marionette
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace mrntt
|
||||
|
||||
#endif // _MARIONETTE_H
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef _MENTAL_ENTITY_H
|
||||
#define _MENTAL_ENTITY_H
|
||||
|
||||
namespace hk {
|
||||
|
||||
class MentalEntity
|
||||
{
|
||||
public:
|
||||
using Id = uint32_t;
|
||||
};
|
||||
|
||||
} // namespace hk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef _MIND_H
|
||||
#define _MIND_H
|
||||
|
||||
#include <config.h>
|
||||
#include <thread>
|
||||
|
||||
#include <director/director.h>
|
||||
#include <simulator/simulator.h>
|
||||
|
||||
namespace hk {
|
||||
|
||||
class Mind
|
||||
{
|
||||
public:
|
||||
void execute(void);
|
||||
|
||||
public:
|
||||
std::thread directorThread;
|
||||
std::thread simulatorThread;
|
||||
std::thread subconsciousThread;
|
||||
|
||||
director::Director director;
|
||||
simulator::Simulator canvas;
|
||||
};
|
||||
|
||||
} // namespace hk
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef _NON_NEUTRAL_QUALIA_H
|
||||
#define _NON_NEUTRAL_QUALIA_H
|
||||
|
||||
#include <quale.h>
|
||||
|
||||
class PleasurableQuale
|
||||
: public NonNeutralQuale
|
||||
{
|
||||
public:
|
||||
virtual void eventInd(void);
|
||||
};
|
||||
|
||||
class PainfulQuale
|
||||
: public NonNeutralQuale
|
||||
{
|
||||
public:
|
||||
virtual void eventInd(void);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef OPTS_H
|
||||
#define OPTS_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <getopt.h>
|
||||
|
||||
// Define a class to hold the options and parse arguments
|
||||
class OptionParser
|
||||
{
|
||||
public:
|
||||
OptionParser() : verbose(false), printUsage(false) {}
|
||||
~OptionParser() = default;
|
||||
|
||||
void parseArguments(int argc, char *argv[], char **envp);
|
||||
std::string stringifyOptions(void) const;
|
||||
std::string getUsage() const;
|
||||
|
||||
static OptionParser &getOptions(void)
|
||||
{
|
||||
static OptionParser options;
|
||||
return options;
|
||||
}
|
||||
|
||||
public:
|
||||
std::string argv0;
|
||||
std::string senseApiLibPath;
|
||||
std::vector<std::string> senseApiLibs;
|
||||
std::string deviceSpecs;
|
||||
std::vector<std::string> deviceSpecFiles;
|
||||
bool verbose, printUsage;
|
||||
|
||||
static struct option longOptions[];
|
||||
};
|
||||
|
||||
#endif // OPTS_H
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef _QUALE_H
|
||||
#define _QUALE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <attentionTrigger.h>
|
||||
|
||||
class Quale
|
||||
{
|
||||
public:
|
||||
enum class Type
|
||||
{
|
||||
NEUTRAL,
|
||||
/* Bounding refers to qualia such as tactile pressure which
|
||||
* are mostly neutral but disclose information about the limits
|
||||
* of the body.
|
||||
**/
|
||||
BOUNDING,
|
||||
PAINFUL,
|
||||
PLEASURABLE
|
||||
} type;
|
||||
|
||||
int32_t intensity;
|
||||
};
|
||||
|
||||
class NeutralQuale
|
||||
: public Quale
|
||||
{
|
||||
};
|
||||
|
||||
class NonNeutralQuale
|
||||
: public Quale, public AttentionTrigger
|
||||
{
|
||||
public:
|
||||
virtual void eventInd(void);
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef _QUALE_BUNDLE_H
|
||||
#define _QUALE_BUNDLE_H
|
||||
|
||||
#include <config.h>
|
||||
#include <array>
|
||||
#include <quale.h>
|
||||
|
||||
#define CONFIG_NUM_SENSORS 5
|
||||
|
||||
typedef std::array<Quale, CONFIG_NUM_SENSORS> QualeBundle_t;
|
||||
class QualeBundle
|
||||
{
|
||||
QualeBundle_t qualia;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,85 @@
|
||||
#ifndef SENSE_API_PROVIDER_DESC_H
|
||||
#define SENSE_API_PROVIDER_DESC_H
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <dlfcn.h>
|
||||
#include <functional>
|
||||
#include <user/senseApiDesc.h>
|
||||
|
||||
namespace hk {
|
||||
namespace sense_api {
|
||||
|
||||
class SenseApiLib
|
||||
{
|
||||
private:
|
||||
friend class SenseApiManager;
|
||||
struct DlCloser
|
||||
{
|
||||
void operator()(void* handle) const
|
||||
{
|
||||
if (handle) {
|
||||
dlclose(handle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
SenseApiLib(
|
||||
const std::string& path, void *_dlopen_handle,
|
||||
HK_GET_SENSE_API_DESC_FN_TYPEDEF *descFn)
|
||||
: libraryPath(path),
|
||||
dlopen_handle(_dlopen_handle, DlCloser()),
|
||||
HK_GET_SENSE_API_DESC_FN_NAME(descFn)
|
||||
{}
|
||||
|
||||
void setSenseApiDesc(const SenseApiDesc &desc)
|
||||
{
|
||||
if (!SenseApiDesc::sanityCheck(desc))
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Sanity check failed for sense API "
|
||||
"descriptor in library '" + libraryPath + "'");
|
||||
}
|
||||
|
||||
senseApiDesc = desc;
|
||||
}
|
||||
|
||||
public:
|
||||
std::string libraryPath;
|
||||
std::unique_ptr<void, DlCloser> dlopen_handle;
|
||||
/* UNIMPLEMENTED: API-specific cmdline options. These affect this specific
|
||||
* sense api lib's behaviour globally.
|
||||
*/
|
||||
std::vector<std::string> options;
|
||||
|
||||
/**
|
||||
* @brief Every sense API lib is required to provide a function that returns
|
||||
* a SenseApiDesc struct. This struct states which API the lib uses to
|
||||
* connect Harikoff to the sense provider it supports.
|
||||
*
|
||||
* This getter function should be visible to dlsym() so that Harikoff can
|
||||
* find it in the lib after loading it, and call it.
|
||||
*/
|
||||
std::function<HK_GET_SENSE_API_DESC_FN_TYPEDEF>
|
||||
HK_GET_SENSE_API_DESC_FN_NAME;
|
||||
|
||||
/**
|
||||
* @brief Harikoff will call the `HK_GET_SENSE_API_DESC_FN_NAME` getter
|
||||
* function and use the data it provides in order to fill out this
|
||||
* descriptor.
|
||||
*/
|
||||
SenseApiDesc senseApiDesc;
|
||||
|
||||
std::string stringify() const {
|
||||
std::string result = "Library Path: " + libraryPath + "\n";
|
||||
result += "Sense API Descriptor: " + senseApiDesc.stringify() + "\n";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace sense_api
|
||||
} // namespace hk
|
||||
|
||||
#endif // SENSE_API_PROVIDER_DESC_H
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef SENSE_API_MANAGER_H
|
||||
#define SENSE_API_MANAGER_H
|
||||
|
||||
#include <config.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <senseApis/senseApiLib.h>
|
||||
#include <user/senseDeviceSpec.h>
|
||||
|
||||
namespace hk {
|
||||
namespace sense_api {
|
||||
|
||||
class SenseApiManager
|
||||
{
|
||||
public:
|
||||
static SenseApiManager& getInstance()
|
||||
{
|
||||
static SenseApiManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
SenseApiLib& loadSenseApiLib(const std::string& libraryPath);
|
||||
std::optional<std::reference_wrapper<SenseApiLib>> getSenseApiLib(
|
||||
const std::string& libraryPath);
|
||||
std::optional<std::reference_wrapper<SenseApiLib>> getSenseApiLibByApiName(
|
||||
const std::string& apiName);
|
||||
void unloadSenseApiLib(const std::string& libraryPath);
|
||||
|
||||
void initializeSenseApiLib(SenseApiLib& lib);
|
||||
void finalizeSenseApiLib(SenseApiLib& lib);
|
||||
|
||||
void loadAllSenseApiLibsFromOptions(void);
|
||||
void unloadAllSenseApiLibs(void);
|
||||
void initializeAllSenseApiLibs(void);
|
||||
void finalizeAllSenseApiLibs(void);
|
||||
|
||||
void attachAllSenseDevicesFromSpecs(void);
|
||||
void attachSenseDevice(const device::SenseDeviceSpec& spec);
|
||||
void detachSenseDevice(const device::SenseDeviceSpec& spec);
|
||||
void detachAllSenseDevices(void);
|
||||
|
||||
std::string stringifyLibs() const;
|
||||
|
||||
private:
|
||||
SenseApiManager() = default;
|
||||
~SenseApiManager() = default;
|
||||
|
||||
SenseApiManager(const SenseApiManager&) = delete;
|
||||
SenseApiManager& operator=(const SenseApiManager&) = delete;
|
||||
|
||||
std::vector<std::unique_ptr<SenseApiLib>> senseApiLibs;
|
||||
};
|
||||
|
||||
} // namespace sense_api
|
||||
} // namespace hk
|
||||
|
||||
#endif // SENSE_API_MANAGER_H
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef _EXTROSPECTOR_H
|
||||
#define _EXTROSPECTOR_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <sensors/sensor.h>
|
||||
|
||||
namespace hk {
|
||||
namespace sensors {
|
||||
|
||||
class Extrospector
|
||||
: public Sensor
|
||||
{
|
||||
public:
|
||||
Extrospector(void) = default;
|
||||
~Extrospector() = default;
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
} // namespace sensors
|
||||
} // namespace hk
|
||||
|
||||
#endif // _EXTROSPECTOR_H
|
||||
@@ -0,0 +1,109 @@
|
||||
#ifndef _INTEROCEPTOR_H
|
||||
#define _INTEROCEPTOR_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <sensors/sensor.h>
|
||||
|
||||
namespace hk {
|
||||
namespace sensors {
|
||||
|
||||
class Interoceptor
|
||||
: public Sensor
|
||||
{
|
||||
public:
|
||||
Interoceptor(uint32_t _id, uint32_t _value = 0)
|
||||
: id(_id), value(_value)
|
||||
{}
|
||||
~Interoceptor() = default;
|
||||
|
||||
public:
|
||||
uint32_t id;
|
||||
uint64_t value;
|
||||
};
|
||||
|
||||
class NeutrinTeroceptor
|
||||
: public Interoceptor
|
||||
{
|
||||
public:
|
||||
NeutrinTeroceptor(uint32_t _id, uint32_t _value = 0)
|
||||
: Interoceptor(_id, _value)
|
||||
{}
|
||||
};
|
||||
|
||||
class IntrinTeroceptor
|
||||
: public Interoceptor
|
||||
{
|
||||
public:
|
||||
static constexpr uint32_t DEFAULT_INDICATION_THRESHOLD = 1;
|
||||
static constexpr uint32_t DEFAULT_ALERT_THRESHOLD = 5;
|
||||
static constexpr uint32_t DEFAULT_OVERLOAD_THRESHOLD = 9;
|
||||
|
||||
IntrinTeroceptor(
|
||||
uint32_t _id,
|
||||
uint32_t _value = 0,
|
||||
uint32_t _indicationThreshold = DEFAULT_INDICATION_THRESHOLD,
|
||||
uint32_t _alertThreshold = DEFAULT_ALERT_THRESHOLD,
|
||||
uint32_t _overloadThreshold = DEFAULT_OVERLOAD_THRESHOLD)
|
||||
: Interoceptor(_id, _value),
|
||||
indicationThreshold(_indicationThreshold),
|
||||
alertThreshold(_alertThreshold),
|
||||
overloadThreshold(_overloadThreshold)
|
||||
{}
|
||||
|
||||
~IntrinTeroceptor() = default;
|
||||
|
||||
public:
|
||||
uint32_t indicationThreshold;
|
||||
uint32_t alertThreshold;
|
||||
uint32_t overloadThreshold;
|
||||
};
|
||||
|
||||
/**
|
||||
* Negtrin and Postrin interoceptors are specialized intrinsic interoceptors
|
||||
* that, unlike neutral interoceptors, have activation thresholds for different
|
||||
* response levels (indication, alert, and overload). These thresholds allow
|
||||
* them to trigger graduated responses based on stimulus intensity.
|
||||
*
|
||||
* While neutral interoceptors simply record a binary state or basic value,
|
||||
* Negtrin and Postrin Interoceptors can model complex sensory responses with
|
||||
* multiple activation levels, similar to biological pain/pleasure responses.
|
||||
* Each threshold represents a different level of urgency or intensity in the
|
||||
* sensory input.
|
||||
*
|
||||
* @see IntrinTeroceptor for the threshold values and implementation details
|
||||
******************************************************************************/
|
||||
|
||||
class NegtrinTeroceptor
|
||||
: public IntrinTeroceptor
|
||||
{
|
||||
public:
|
||||
NegtrinTeroceptor(
|
||||
uint32_t _id,
|
||||
uint32_t _value = 0,
|
||||
uint32_t _indicationThreshold = DEFAULT_INDICATION_THRESHOLD,
|
||||
uint32_t _alertThreshold = DEFAULT_ALERT_THRESHOLD,
|
||||
uint32_t _overloadThreshold = DEFAULT_OVERLOAD_THRESHOLD)
|
||||
: IntrinTeroceptor(_id, _value,
|
||||
_indicationThreshold, _alertThreshold, _overloadThreshold)
|
||||
{}
|
||||
};
|
||||
|
||||
class PostrinTeroceptor
|
||||
: public IntrinTeroceptor
|
||||
{
|
||||
public:
|
||||
PostrinTeroceptor(
|
||||
uint32_t _id,
|
||||
uint32_t _value = 0,
|
||||
uint32_t _indicationThreshold = DEFAULT_INDICATION_THRESHOLD,
|
||||
uint32_t _alertThreshold = DEFAULT_ALERT_THRESHOLD,
|
||||
uint32_t _overloadThreshold = DEFAULT_OVERLOAD_THRESHOLD)
|
||||
: IntrinTeroceptor(_id, _value,
|
||||
_indicationThreshold, _alertThreshold, _overloadThreshold)
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace sensors
|
||||
} // namespace hk
|
||||
|
||||
#endif // _INTEROCEPTOR_H
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _SENSOR_H
|
||||
#define _SENSOR_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace hk {
|
||||
namespace sensors {
|
||||
|
||||
class Sensor
|
||||
{
|
||||
public:
|
||||
Sensor() = default;
|
||||
~Sensor() = default;
|
||||
|
||||
public:
|
||||
};
|
||||
|
||||
} // namespace sensors
|
||||
} // namespace hk
|
||||
|
||||
#endif // _SENSOR_H
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef SIMULATOR_COMMANDLIST_H
|
||||
#define SIMULATOR_COMMANDLIST_H
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <mentalEntity.h>
|
||||
|
||||
namespace hk {
|
||||
namespace simulator {
|
||||
|
||||
/**
|
||||
* @brief Base class for all commands, storing a reference to a mental entity ID.
|
||||
*
|
||||
* Derived classes can extend this to include additional command-specific
|
||||
* data and behavior.
|
||||
*/
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
Command(const MentalEntity::Id menty) : menty(menty) {}
|
||||
|
||||
public:
|
||||
const MentalEntity::Id menty;
|
||||
};
|
||||
|
||||
class CommandList
|
||||
{
|
||||
public:
|
||||
CommandList() = default;
|
||||
|
||||
/**
|
||||
* @brief Used by Scene to point to the currently executing command.
|
||||
*
|
||||
* simulator::Scene maintains an internal cursor. As it executes commands
|
||||
* from its internal command list, it advances the cursor to the current
|
||||
* command before executing it.
|
||||
*/
|
||||
class Cursor
|
||||
{
|
||||
public:
|
||||
Cursor(CommandList& commandList)
|
||||
: commandList(commandList), iter(commandList.commands.begin())
|
||||
{}
|
||||
|
||||
void reset() { iter = commandList.commands.begin(); }
|
||||
bool hasNext() const { return iter != commandList.commands.end(); }
|
||||
Cursor next() { return ++(*this); }
|
||||
|
||||
Cursor& operator++() {
|
||||
++iter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Cursor(
|
||||
CommandList& commandList,
|
||||
std::vector<Command>::iterator iter)
|
||||
: commandList(commandList), iter(iter)
|
||||
{}
|
||||
|
||||
public:
|
||||
CommandList& commandList;
|
||||
std::vector<Command>::iterator iter;
|
||||
};
|
||||
|
||||
Cursor getCursor() { return Cursor(*this); }
|
||||
void addCommand(const Command& command)
|
||||
{
|
||||
commands.push_back(command);
|
||||
}
|
||||
|
||||
public:
|
||||
std::vector<Command> commands;
|
||||
};
|
||||
|
||||
} // namespace simulator
|
||||
} // namespace hk
|
||||
|
||||
#endif // SIMULATOR_COMMANDLIST_H
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef _SCENE_H
|
||||
#define _SCENE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <mentalEntity.h>
|
||||
#include <simulator/commandList.h>
|
||||
|
||||
namespace hk {
|
||||
namespace simulator {
|
||||
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
using Id = uint32_t;
|
||||
|
||||
Scene(void) :
|
||||
cursor(commands)
|
||||
{}
|
||||
~Scene() = default;
|
||||
|
||||
bool hasMentalEntity(const MentalEntity::Id menty) const;
|
||||
MentalEntity::Id addMentalEntity(const MentalEntity& menty);
|
||||
void replaceMentalEntity(const MentalEntity::Id menty, const MentalEntity& newMenty);
|
||||
void removeMentalEntity(const MentalEntity::Id menty);
|
||||
|
||||
void executeInd(void);
|
||||
CommandList::Cursor haltInd(void);
|
||||
|
||||
private:
|
||||
std::map<MentalEntity::Id, MentalEntity &> menties;
|
||||
CommandList commands;
|
||||
CommandList::Cursor cursor;
|
||||
};
|
||||
|
||||
} // namespace simulator
|
||||
} // namespace hk
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef SIMULATOR_H
|
||||
#define SIMULATOR_H
|
||||
|
||||
#include <config.h>
|
||||
#include <simulator/scene.h>
|
||||
|
||||
namespace hk {
|
||||
namespace simulator {
|
||||
|
||||
class Simulator {
|
||||
public:
|
||||
Simulator() = default;
|
||||
~Simulator() = default;
|
||||
|
||||
void initialize();
|
||||
void loadScene(Scene::Id sceneId, Scene &scene);
|
||||
|
||||
private:
|
||||
Scene::Id sceneId;
|
||||
Scene scene;
|
||||
};
|
||||
|
||||
} // namespace simulator
|
||||
} // namespace hk
|
||||
|
||||
#endif // SIMULATOR_H
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef _SINGLECEPT_H
|
||||
#define _SINGLECEPT_H
|
||||
|
||||
#include <mentalEntity.h>
|
||||
#include <implix/implix.h>
|
||||
|
||||
class Singlecept
|
||||
: public MentalEntity
|
||||
{
|
||||
public:
|
||||
Singlecept() = default;
|
||||
~Singlecept() = default;
|
||||
|
||||
Singlecept(const implix::Implix&) {
|
||||
// Conversion logic from Implix to Singlecept
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef STUPEFIER_H
|
||||
#define STUPEFIER_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class Stupefier {
|
||||
public:
|
||||
Stupefier();
|
||||
~Stupefier();
|
||||
|
||||
void up(uint32_t);
|
||||
void down(uint32_t);
|
||||
|
||||
public:
|
||||
uint32_t focus;
|
||||
};
|
||||
|
||||
class SoftStupefier : public Stupefier {
|
||||
public:
|
||||
SoftStupefier();
|
||||
~SoftStupefier();
|
||||
};
|
||||
|
||||
class HardStupefier : public Stupefier {
|
||||
public:
|
||||
HardStupefier();
|
||||
~HardStupefier();
|
||||
};
|
||||
|
||||
#endif // STUPEFIER_H
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef _SUBCONSCIOUS_H
|
||||
#define _SUBCONSCIOUS_H
|
||||
|
||||
#include <thoughtContentSource.h>
|
||||
|
||||
class Subconscious
|
||||
: public ThoughtContentSource
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,60 @@
|
||||
#ifndef _THOUGHT_H
|
||||
#define _THOUGHT_H
|
||||
|
||||
#include <iostream>
|
||||
#include <scene.h>
|
||||
#include <attentionGrabber.h>
|
||||
#include <goal.h>
|
||||
|
||||
class Thought
|
||||
{
|
||||
public:
|
||||
Thought(void)
|
||||
{
|
||||
setGoal(thought::Goal::DRIFT);
|
||||
}
|
||||
|
||||
public:
|
||||
void walk(void)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
step();
|
||||
}
|
||||
};
|
||||
|
||||
void step(void) { std::cout <<"Step\n"; }
|
||||
void setGoal(thought::Goal g)
|
||||
{ goal = g; }
|
||||
|
||||
public:
|
||||
Scene scene;
|
||||
thought::Goal goal;
|
||||
};
|
||||
|
||||
class ActiveThought
|
||||
: public Thought
|
||||
{
|
||||
public:
|
||||
ActiveThought(AttentionGrabber ag)
|
||||
: currFocus(ag)
|
||||
{
|
||||
setGoal(thought::Goal
|
||||
::ASSOCIATE_CAUSAL_QUALE_WITH_INTRINSIC_MOTIVATORS);
|
||||
}
|
||||
|
||||
public:
|
||||
AttentionGrabber currFocus;
|
||||
};
|
||||
|
||||
class IdleThought
|
||||
: public Thought
|
||||
{
|
||||
public:
|
||||
IdleThought(void)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef _THOUGHT_CONTENT_SOURCE_H
|
||||
#define _THOUGHT_CONTENT_SOURCE_H
|
||||
|
||||
class ThoughtContentSource
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef _VALUE_JUDGEMENT_H
|
||||
#define _VALUE_JUDGEMENT_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class ValueJdgmnt
|
||||
{
|
||||
uint32_t intensity;
|
||||
};
|
||||
|
||||
class PosValueJdgmnt
|
||||
: public ValueJdgmnt
|
||||
{
|
||||
};
|
||||
|
||||
class NegValueJdgmnt
|
||||
: public ValueJdgmnt
|
||||
{
|
||||
};
|
||||
|
||||
class NtrlValueJdgmnt
|
||||
: public ValueJdgmnt
|
||||
{
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
add_library(marionette STATIC
|
||||
marionette.cpp
|
||||
)
|
||||
|
||||
target_include_directories(marionette PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
@@ -0,0 +1,9 @@
|
||||
|
||||
namespace mrntt {
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace mrntt
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
#include <mind.h>
|
||||
@@ -0,0 +1,120 @@
|
||||
#include <opts.h>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <getopt.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
struct option OptionParser::longOptions[] = {
|
||||
{"devicespec", required_argument, 0, 's'},
|
||||
{"spec", required_argument, 0, 's'},
|
||||
{"devspec", required_argument, 0, 's'},
|
||||
{"devfile", required_argument, 0, 'd'},
|
||||
{"devicefile", required_argument, 0, 'd'},
|
||||
{"sense-api-lib", required_argument, 0, 'a'},
|
||||
{"senseapi", required_argument, 0, 'a'},
|
||||
{"sense-api-path", required_argument, 0, 'p'},
|
||||
{"verbose", no_argument, 0, 'v'},
|
||||
{"help", no_argument, 0, '?'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
void OptionParser::parseArguments(int argc, char *argv[], char **envp)
|
||||
{
|
||||
(void)envp;
|
||||
int opt;
|
||||
int optionIndex = 0;
|
||||
|
||||
argv0 = argv[0];
|
||||
|
||||
optind = 1; // Reset optind to 1 before parsing
|
||||
while ((opt = getopt_long(
|
||||
argc, argv, "s:d:a:p:v?", longOptions, &optionIndex)) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 's':
|
||||
if (!deviceSpecs.empty()) {
|
||||
deviceSpecs += "||";
|
||||
}
|
||||
deviceSpecs += std::string(optarg);
|
||||
break;
|
||||
case 'd':
|
||||
deviceSpecFiles.push_back(optarg);
|
||||
break;
|
||||
case 'a':
|
||||
senseApiLibs.push_back(optarg);
|
||||
break;
|
||||
case 'p':
|
||||
{
|
||||
struct stat info;
|
||||
|
||||
if (!senseApiLibPath.empty())
|
||||
{
|
||||
std::cerr << std::string(__func__)
|
||||
+ " - Overwriting previous sense-api-path with: " << optarg
|
||||
<< '\n';
|
||||
}
|
||||
|
||||
if (stat(optarg, &info) != 0 || !(info.st_mode & S_IFDIR))
|
||||
{
|
||||
throw std::invalid_argument(
|
||||
std::string(__func__) + " - The specified path is not a "
|
||||
"directory: " + optarg);
|
||||
}
|
||||
|
||||
senseApiLibPath = optarg;
|
||||
break;
|
||||
}
|
||||
case 'v':
|
||||
verbose = true;
|
||||
break;
|
||||
case '?':
|
||||
printUsage = true;
|
||||
return;
|
||||
default:
|
||||
throw std::invalid_argument(
|
||||
std::string(__func__) + " - Invalid argument encountered: "
|
||||
+ std::string(argv[optind - 1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string OptionParser::getUsage() const
|
||||
{
|
||||
return "Usage: " + argv0 + " [-s|--devicespec|--spec|--devspec <device_spec>] "
|
||||
"[-d|--devfile|--devicefile <filename>] "
|
||||
"[-a|--sense-api-lib|--senseapi <filename>] "
|
||||
"[-p|--sense-api-path <directory>] "
|
||||
"[-v|--verbose] "
|
||||
"[-?|--help]";
|
||||
}
|
||||
|
||||
std::string OptionParser::stringifyOptions(void) const
|
||||
{
|
||||
std::ostringstream oss;
|
||||
|
||||
if (verbose) {
|
||||
oss << "Verbose mode is on" << std::endl;
|
||||
}
|
||||
|
||||
oss << "Device Specs: " << deviceSpecs << std::endl;
|
||||
|
||||
oss << "Device Spec Files: ";
|
||||
for (const auto& file : deviceSpecFiles) {
|
||||
oss << file << " ";
|
||||
}
|
||||
oss << std::endl;
|
||||
|
||||
oss << "Sense API Library Path: " << senseApiLibPath << std::endl;
|
||||
oss << "Sense API Libraries: ";
|
||||
for (const auto& lib : senseApiLibs) {
|
||||
oss << lib << " ";
|
||||
}
|
||||
oss << std::endl;
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
#include <nonNeutralQualia.h>
|
||||
@@ -0,0 +1,5 @@
|
||||
add_library(senseApis STATIC
|
||||
senseApiManager.cpp
|
||||
)
|
||||
|
||||
target_include_directories(senseApis PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
@@ -0,0 +1,268 @@
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
#include <optional>
|
||||
#include <filesystem>
|
||||
#include <senseApis/senseApiManager.h>
|
||||
#include <senseApis/senseApiLib.h>
|
||||
#include <opts.h>
|
||||
#include <user/senseApiDesc.h>
|
||||
#include <deviceManager/deviceManager.h>
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace hk {
|
||||
namespace sense_api {
|
||||
|
||||
/**
|
||||
* @brief Searches for a library in predefined locations
|
||||
* @param libraryPath The name or path of the library to find
|
||||
* @return Optional containing the full path if found in search paths, nullopt
|
||||
* if not
|
||||
*
|
||||
* Searches for the library in the following locations in order:
|
||||
* 1. Custom path specified by --sense-api-lib-path option (if provided)
|
||||
* 2. Current working directory
|
||||
* 3. Directory containing the executable
|
||||
*
|
||||
* If the library is not found in any of these locations, returns nullopt and
|
||||
* falls back to system default library search paths (LD_LIBRARY_PATH, etc.)
|
||||
*/
|
||||
static std::optional<std::string> findLibraryPath(
|
||||
const std::string& libraryPath)
|
||||
{
|
||||
std::vector<std::string> searchPaths = {
|
||||
fs::current_path().string(),
|
||||
fs::path("/proc/self/exe").parent_path().string()
|
||||
};
|
||||
|
||||
if (!OptionParser::getOptions().senseApiLibPath.empty())
|
||||
{
|
||||
searchPaths.insert(
|
||||
searchPaths.begin(), OptionParser::getOptions().senseApiLibPath);
|
||||
}
|
||||
|
||||
for (const auto& path : searchPaths)
|
||||
{
|
||||
fs::path fullPath = fs::path(path) / libraryPath;
|
||||
if (fs::exists(fullPath))
|
||||
{
|
||||
return fullPath.string();
|
||||
}
|
||||
}
|
||||
|
||||
std::cerr << std::string(__func__) + ": library '"
|
||||
+ libraryPath + "' isn't in search bespoke search paths: ";
|
||||
for (const auto& path : searchPaths) {
|
||||
std::cerr << path << " ";
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "Trying to load " + libraryPath + " from system default "
|
||||
"search paths\n";
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
SenseApiLib& SenseApiManager::loadSenseApiLib(const std::string& libraryPath)
|
||||
{
|
||||
std::optional<std::string> fullPath = findLibraryPath(libraryPath);
|
||||
std::string resolvedPath = fullPath.value_or(libraryPath);
|
||||
|
||||
// Clear any existing error
|
||||
dlerror();
|
||||
auto dlopen_handle = std::unique_ptr<void, SenseApiLib::DlCloser>(
|
||||
dlopen(resolvedPath.c_str(), RTLD_LAZY));
|
||||
if (!dlopen_handle && fullPath.has_value())
|
||||
{
|
||||
// Fallback to using the supplied libraryPath
|
||||
dlerror();
|
||||
dlopen_handle.reset(dlopen(libraryPath.c_str(), RTLD_LAZY));
|
||||
}
|
||||
|
||||
if (!dlopen_handle)
|
||||
{
|
||||
const char *dlerr = dlerror();
|
||||
|
||||
std::string error = (dlerr
|
||||
? dlerr
|
||||
: "Unknown error while opening shlib");
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": Cannot load library '"
|
||||
+ libraryPath + "': "
|
||||
+ error);
|
||||
}
|
||||
|
||||
// Initialize getSenseApiDescriptor
|
||||
auto func = reinterpret_cast<HK_GET_SENSE_API_DESC_FN_TYPEDEF *>(
|
||||
dlsym(dlopen_handle.get(), HK_GET_SENSE_API_DESC_FN_NAME_STR));
|
||||
if (!func)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": dlsym('"
|
||||
HK_GET_SENSE_API_DESC_FN_NAME_STR "') failed for library '"
|
||||
+ libraryPath + "'");
|
||||
}
|
||||
|
||||
const SenseApiDesc &libApiDesc = func();
|
||||
auto lib = std::make_unique<SenseApiLib>(
|
||||
libraryPath, dlopen_handle.release(), func);
|
||||
lib->setSenseApiDesc(libApiDesc);
|
||||
senseApiLibs.push_back(std::move(lib));
|
||||
return *senseApiLibs.back();
|
||||
}
|
||||
|
||||
std::optional<std::reference_wrapper<SenseApiLib>>
|
||||
SenseApiManager::getSenseApiLib(const std::string& libraryPath)
|
||||
{
|
||||
auto it = std::find_if(senseApiLibs.begin(), senseApiLibs.end(),
|
||||
[&libPath = libraryPath](const std::unique_ptr<SenseApiLib>& lib) {
|
||||
return lib->libraryPath == libPath;
|
||||
}
|
||||
);
|
||||
|
||||
if (it != senseApiLibs.end()) { return **it; }
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::reference_wrapper<SenseApiLib>>
|
||||
SenseApiManager::getSenseApiLibByApiName(const std::string& apiName)
|
||||
{
|
||||
auto it = std::find_if(senseApiLibs.begin(), senseApiLibs.end(),
|
||||
[&apiName](const std::unique_ptr<SenseApiLib>& lib) {
|
||||
return lib->senseApiDesc.name == apiName;
|
||||
}
|
||||
);
|
||||
|
||||
if (it != senseApiLibs.end()) { return **it; }
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
void SenseApiManager::unloadSenseApiLib(const std::string& libraryPath)
|
||||
{
|
||||
auto it = std::find_if(senseApiLibs.begin(), senseApiLibs.end(),
|
||||
[&lpath = libraryPath](const std::unique_ptr<SenseApiLib>& lib) {
|
||||
return lib->libraryPath == lpath;
|
||||
}
|
||||
);
|
||||
|
||||
if (it != senseApiLibs.end())
|
||||
{
|
||||
senseApiLibs.erase(it);
|
||||
return;
|
||||
}
|
||||
|
||||
std::cerr << std::string(__func__) + ": Library not found: "
|
||||
<< libraryPath << '\n';
|
||||
}
|
||||
|
||||
void SenseApiManager::unloadAllSenseApiLibs(void)
|
||||
{
|
||||
senseApiLibs.clear();
|
||||
}
|
||||
|
||||
void SenseApiManager::loadAllSenseApiLibsFromOptions()
|
||||
{
|
||||
const auto& options = OptionParser::getOptions();
|
||||
for (const auto& libPath : options.senseApiLibs) {
|
||||
loadSenseApiLib(libPath);
|
||||
}
|
||||
}
|
||||
|
||||
std::string SenseApiManager::stringifyLibs() const
|
||||
{
|
||||
std::string result;
|
||||
for (const auto& lib : senseApiLibs) {
|
||||
result += lib->stringify() + "\n";
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void SenseApiManager::initializeSenseApiLib(SenseApiLib& lib)
|
||||
{
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps.initializeInd)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": initializeInd() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
lib.senseApiDesc.sal_mgmt_libOps.initializeInd();
|
||||
}
|
||||
|
||||
void SenseApiManager::finalizeSenseApiLib(SenseApiLib& lib)
|
||||
{
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps.finalizeInd)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": finalizeInd() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
lib.senseApiDesc.sal_mgmt_libOps.finalizeInd();
|
||||
}
|
||||
|
||||
void SenseApiManager::initializeAllSenseApiLibs(void)
|
||||
{
|
||||
for (auto& lib : senseApiLibs) {
|
||||
initializeSenseApiLib(*lib);
|
||||
}
|
||||
}
|
||||
|
||||
void SenseApiManager::finalizeAllSenseApiLibs(void)
|
||||
{
|
||||
for (auto& lib : senseApiLibs) {
|
||||
finalizeSenseApiLib(*lib);
|
||||
}
|
||||
}
|
||||
|
||||
void SenseApiManager::attachSenseDevice(const device::SenseDeviceSpec& spec)
|
||||
{
|
||||
auto libOpt = getSenseApiLibByApiName(spec.api);
|
||||
if (!libOpt)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": No library found for API '"
|
||||
+ spec.api + "'");
|
||||
}
|
||||
auto& lib = libOpt.value().get();
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": attachDeviceReq() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
lib.senseApiDesc.sal_mgmt_libOps.attachDeviceReq(spec);
|
||||
}
|
||||
|
||||
void SenseApiManager::detachSenseDevice(const device::SenseDeviceSpec& spec)
|
||||
{
|
||||
auto libOpt = getSenseApiLibByApiName(spec.api);
|
||||
if (!libOpt)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": No library found for API '"
|
||||
+ spec.api + "'");
|
||||
}
|
||||
auto& lib = libOpt.value().get();
|
||||
if (!lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq)
|
||||
{
|
||||
throw std::runtime_error(
|
||||
std::string(__func__) + ": detachDeviceReq() is NULL for library '"
|
||||
+ lib.libraryPath + "'");
|
||||
}
|
||||
lib.senseApiDesc.sal_mgmt_libOps.detachDeviceReq(spec);
|
||||
}
|
||||
|
||||
void SenseApiManager::attachAllSenseDevicesFromSpecs(void)
|
||||
{
|
||||
for (const auto& spec : device::DeviceManager::senseDeviceSpecs) {
|
||||
attachSenseDevice(*spec);
|
||||
}
|
||||
}
|
||||
|
||||
void SenseApiManager::detachAllSenseDevices(void)
|
||||
{
|
||||
for (const auto& spec : device::DeviceManager::senseDeviceSpecs) {
|
||||
detachSenseDevice(*spec);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sense_api
|
||||
} // namespace hk
|
||||
Reference in New Issue
Block a user