cx_executive_plugin
CLIPS plugin to continuously refresh agendas and run CLIPS environments
README
Executive Plugin
Source code on GitHub.
This plugin provides continuous and ad-hoc execution of CLIPS environments. Additionally, it enables reasoning about the current ROS and system time.
Configuration
refresh_rate:
Type
Default
int
10
Description : Target rate (in Hz) with which agendas are refreshed and run is called. This is done sequentially for the registered environments.
publish_on_refresh:
Type
Default
bool
false
Description : Whether to publish an empty message with each agenda refresh on the clips_executive/refresh_agenda topic. Mainly useful for debug purposes to measure the actual refresh rate.
assert_time:
Type
Default
bool
true
Description : Whether the latest ROS time as fact into the CLIPS environment on each iteration.
autostart:
Type
Default
bool
true
Description : Whether to start periodic execution when loading the plugin.
Features
The executive plugin periodically runs all managed CLIPS environments at the configured refresh_rate. Each tick performs the following steps:
Optionally asserts the current time as
(time (now))into the environment.Refreshes all agendas.
If a focus_stack is configured for an environment, iterates through the stack in order, running each module’s agenda (respecting a possibly set rule_limit) before moving to the next. Otherwise, runs the
MAINmodule’s agenda.Repeats steps 2-3 until no rules fire, ensuring cross-module interactions are fully resolved.
Optionally publishes the total number of rules fired on a topic.
Execution can be paused and resumed at any time via services, or a single tick can be triggered manually, regardless of the current pause state.
CLIPS commands can be sent directly to a managed environment via dedicated eval and build services.
eval evaluates an expression using CLIPS Eval, while build defines a new construct using CLIPS Build.
If no environment is specified, the command is executed in the first managed environment.
NOTE
When using a focus stack, the current module is reset to MAIN after each module’s agenda is run.
This ensures that time assertion and other framework operations always operate in a predictable context.
NOTE
Eval is intended for invoking arbirary commands (e.g. (assert (foo)), (facts)),
while Build is intended for defining constructs (e.g. (defrule ...), (deftemplate ...)).
ROS Interfaces
All interaces are prefixed by tha name of the CX node, followed by the name of the executive plugin, e.g., clips_manager/executive.
/ns/node/plugin/refresh_agenda: Topic where a mesage is published after each tick, indicating the number of rules that fired (requires publish_on_refresh).
/ns/node/plugin/pause: Service for stopping periodic ticks according to the configured refresh_rate.
/ns/node/plugin/resume: Service that for starting the periodic ticks.
/ns/node/plugin/tick_once: Serivce for ticking once.
/ns/node/plugin/eval: Service for processing a string as an
evalcommand in a given environment./ns/node/plugin/build: Service for processing a string as an
buildcommand in a given environment.
Facts
If assert_time is set to true, it asserts the ordered fact time with the current ROS time as float.
(time ?ros-time-float)
Functions
This plugin adds deffunctions to retrieve the current time.
(bind ?ros-time (now)) ; returns a FLOAT holding get_clock()->now().seconds()
(bind ?sys-time (now-systime)) ; returns a FLOAT of system time
Other
Lastly, the time fact is unwatched after the first assertion.
Usage Example
A minimal working example is provided by the cx_bringup package. Run it via:
ros2 launch cx_bringup cx_launch.py manager_config:=plugin_examples/executive.yaml
It prints the current ROS and system time in each iteration and compares the time at the start of the iteration with the time at the time the rule is fired.
The executive can be stopped by calling the pause service:
ros2 service call /executive/pause std_srvs/srv/Trigger {}
Individual ticks (a run of the inference engine until termination) can be invoked via the tick_once service:
ros2 service call /executive/tick_once std_srvs/srv/Trigger {}
The eval and build functions allow for ad-hoc interaction with an environment:
ros2 service call /executive/build cx_msgs/srv/ClipsCommand \
'{env_name: "cx_executive", command: "(deftemplate example (slot message (type STRING)))"}'
ros2 service call /executive/eval cx_msgs/srv/ClipsCommand \
'{env_name: "cx_executive", command: "(assert (example (message \"hello\")))"}'
Finally, the resume service is used in order to resume automatic execution:
ros2 service call /executive/resume std_srvs/srv/Trigger {}
Configuration
File cx_bringup/params/plugin_examples/executive.yaml.
clips_manager:
ros__parameters:
environments: ["cx_executive"]
cx_executive:
plugins: ["executive", "files"]
log_clips_to_file: true
watch: ["facts", "rules"]
executive:
plugin: "cx::ExecutivePlugin"
publish_on_refresh: false
assert_time: true
refresh_rate: 10
files:
plugin: "cx::FileLoadPlugin"
pkg_share_dirs: ["cx_bringup"]
load: [
"clips/plugin_examples/executive.clp"]
Code
File cx_bringup/clips/plugin_examples/executive.clp.
(defrule print-time
(time ?now)
=>
(printout info "time between agenda refresh and rule fire: " (- (now) ?now) crlf)
(printout info "ROS time: " (now) crlf)
(printout info "sys time: " (now-systime) crlf)
)