Program Listing for File SoarRunner.hpp
↰ Return to documentation for file (include/soar_ros/SoarRunner.hpp
)
// Copyright 2024 Moritz Schmidt
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SOAR_ROS__SOARRUNNER_HPP_
#define SOAR_ROS__SOARRUNNER_HPP_
#include <cstdlib>
#include <iostream>
#include <map>
#include <memory>
#include <queue>
#include <sml_Client.h>
#include <stdexcept>
#include <string>
#include <thread>
#include <vector>
#include <rclcpp/rclcpp.hpp>
#include <std_msgs/msg/string.hpp>
#include <std_srvs/srv/trigger.hpp>
#include "Client.hpp"
#include "Interface.hpp"
#include "Publisher.hpp"
#include "Service.hpp"
#include "Subscriber.hpp"
namespace soar_ros
{
void SoarPrintEventHandler([[maybe_unused]] sml::smlPrintEventId id,
void * pSoarRunner_, sml::Agent * pAgent,
char const * pMessagee);
void updateEventHandler([[maybe_unused]] sml::smlUpdateEventId id,
void * pSoarRunner_,
[[maybe_unused]] sml::Kernel * kernel_ptr,
[[maybe_unused]] sml::smlRunFlags run_flags);
class SoarRunner : public rclcpp::Node
{
private:
sml::Agent * pAgent;
sml::Kernel * pKernel;
std::thread runThread;
rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr m_getSoarKernelStatus;
rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr m_kernelRun;
rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr m_kernelStop;
rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr m_debuggerLaunch;
std::map<std::string, std::shared_ptr<soar_ros::OutputBase>> outputs;
std::vector<std::shared_ptr<soar_ros::InputBase>> inputs;
bool m_debug;
sml::Identifier * ol;
void processOutputLinkChanges();
void processInput();
void run();
std::string getSoarLogFilePath();
std::atomic<bool> isRunning;
public:
SoarRunner(
const std::string & agent_name,
const std::string & path_productions);
void debuggerLaunch(
[[maybe_unused]] const std::shared_ptr<rmw_request_id_t> request_header,
[[maybe_unused]] std::shared_ptr<std_srvs::srv::Trigger::Request> request,
std::shared_ptr<std_srvs::srv::Trigger::Response> response);
void getSoarKernelStatus(
[[maybe_unused]] const std::shared_ptr<rmw_request_id_t> request_header,
[[maybe_unused]] std::shared_ptr<std_srvs::srv::Trigger::Request> request,
std::shared_ptr<std_srvs::srv::Trigger::Response> response);
void runSoarKernel(
[[maybe_unused]] const std::shared_ptr<rmw_request_id_t> request_header,
[[maybe_unused]] std::shared_ptr<std_srvs::srv::Trigger::Request> request,
std::shared_ptr<std_srvs::srv::Trigger::Response> response);
void stopSoarKernel(
[[maybe_unused]] const std::shared_ptr<rmw_request_id_t> request_header,
[[maybe_unused]] std::shared_ptr<std_srvs::srv::Trigger::Request> request,
std::shared_ptr<std_srvs::srv::Trigger::Response> response);
sml::Agent * addAgent(
const std::string & agent_name,
const std::string & path_productions);
~SoarRunner();
sml::Agent * getAgent() {return pAgent;}
template<typename T>
bool addPublisher(std::shared_ptr<soar_ros::Publisher<T>> output)
{
outputs[output.get()->getTopic()] = output;
return true;
}
template<typename T>
bool addPublisher(
std::shared_ptr<soar_ros::Publisher<T>> output,
const std::string & commandName)
{
outputs[commandName] = output;
return true;
}
template<typename T>
bool addSubscriber(std::shared_ptr<soar_ros::Subscriber<T>> input)
{
inputs.push_back(input);
return true;
}
template<typename T>
bool addService(std::shared_ptr<soar_ros::Service<T>> service)
{
return addService(service, service.get()->getTopic());
}
template<typename T>
bool addService(
std::shared_ptr<soar_ros::Service<T>> service,
const std::string & commandName)
{
outputs[commandName] =
std::static_pointer_cast<soar_ros::OutputBase>(service);
inputs.push_back(std::static_pointer_cast<soar_ros::InputBase>(service));
return true;
}
template<typename T>
bool addClient(std::shared_ptr<soar_ros::Client<T>> client)
{
return addClient(client, client.get()->getTopic());
}
template<typename T>
bool addClient(
std::shared_ptr<soar_ros::Client<T>> client,
const std::string & commandName)
{
outputs[commandName] =
std::static_pointer_cast<soar_ros::OutputBase>(client);
inputs.push_back(std::static_pointer_cast<soar_ros::InputBase>(client));
return true;
}
void startThread()
{
// If thread is already running, skip
if (isRunning.load() == true) {
RCLCPP_WARN(this->get_logger(), "runThread already running");
return;
} else {
isRunning.store(true);
}
RCLCPP_INFO(this->get_logger(), "Starting runThread");
runThread = std::thread(&SoarRunner::run, this);
}
void stopThread()
{
if (isRunning.load() == false) {
RCLCPP_INFO(this->get_logger(), "Run thread already stopped!");
return;
}
isRunning.store(false);
RCLCPP_WARN(this->get_logger(), "Stopping runThread");
if (runThread.joinable()) {
RCLCPP_INFO(this->get_logger(), "Waiting for run thread to join");
runThread.join();
}
}
void updateWorld()
{
// Read Soar output
processOutputLinkChanges();
if (ol == NULL) {
ol = pAgent->GetOutputLink();
RCLCPP_DEBUG(this->get_logger(), "Output link reference invalid!");
}
// Write to Soar input-link
processInput();
}
}; // class SoarRunner
} // namespace soar_ros
#endif // SOAR_ROS__SOARRUNNER_HPP_