Generated ROS Action Plugin

Source code generated by cx_ros_comm_gen.

Given the package (e.g., example_interfaces) and action_name (e.g., Fibonacci), this document uses the following abbreviations:

  • PkgCamel: CamelCase of package (e.g., ExampleInterfaces)

  • SrvCamel: CamelCase of action_name (e.g., Fibonacci)

  • pkg-kebab: kebab-case of package (e.g., example-interfaces)

  • action-kebab: kebab-case of action_name (e.g., fibonacci)

Plugin Class

cx::CXPkgCamelACtionCamelPlugin

(e.g., cx::CXExampleInterfacesFibonacciPlugin)

Configuration

This plugin has no specific configuration.

Features

Facts

; Asserted by the respective creat-client function.
; Retracted by the respective destroy-client function.
(<package-kebab>-<action-kebab>-client (server ?server-name-string))

; Asserted by the respective create-server function.
; Retracted by the respective destroy-server function.
(<package-kebab>-<action-kebab>-server (name ?server-name-string))

; Asserted by the goal response callback of a client.
; Process the response and then destroy feedback.
; The client-goal-handle should persist until the processing of the request is fully done.
(<package-kebab>-<action-kebab>-goal-response (server ?server-name-string) (client-goal-handle-ptr ?cgh-ptr))

; Asserted by the goal feedback callback of a client.
; Process the response and then destroy feedback (it is read-only, do not modify it).
; The client-goal-handle should persist (and not be destroyed) until the processing of the goal is fully done and the action is terminated.
; In particular, the client goal handle pointer here will match the one from the goal-response fact.
(<package-kebab>-<action-kebab>-goal-feedback (server ?server-name-string) (client-goal-handle-ptr ?cgh-ptr) (feedback-ptr ?f-ptr))

; Asserted by the goal result callback of a client.
; Process the result and then destroy the result pointer before retracting this fact.
; "code" is either UNKNOWN SUCCEEDED CANCELED or ABORTED.
; "goal-id" is the string representation of a uuid according to rclcpp_action::to_string().
(<package-kebab>-<action-kebab>-wrapped-result (server ?server-name-string) (goal-id ?uuid-str) (code ?code-symbol) (result-ptr ?f-ptr))

; Asserted by the goal result callback of a server.
; Process the server goal handle to retrieve important information such as the goal sent by the client.
; The server-goal-handle should persist (and not be destroyed) until the processing of the action is fully done and the action is terminated.
(<package-kebab>-<action-kebab>-accepted-goal (server ?server-name-string) (server-goal-handle-ptr ?f-ptr))

Functions

; Create and destroy clients and servers.
; After creating a server, user-defined function is called whenever a goal request arrives.
(<package-kebab>-<action-kebab>-create-server ?server-name)
(<package-kebab>-<action-kebab>-destroy-server ?server-name)
(<package-kebab>-<action-kebab>-create-client ?server-name)
(<package-kebab>-<action-kebab>-destroy-client ?server-name)

; Send a goal to an action server
; Requires the client to be created first using create-client.
; Callbacks will assert goal-response feedback and wrapped-result facts.
; Do not destroy the ?msg-ptr immediately, keep it until the goal is fully processed.
(<package-kebab>-<action-kebab>-send-goal ?msg-ptr ?server-name)

; Creating, destroying and processing of goals
(bind ?msg-ptr (<package-kebab>-<action-kebab>-goal-create))
(<package-kebab>-<action-kebab>-goal-destroy ?msg-ptr)
(<package-kebab>-<action-kebab>-goal-set-field ?msg-ptr ?field-name ?field-value)
(<package-kebab>-<action-kebab>-goal-get-field ?msg-ptr ?field-name)

; Creating, destroying and processing of feedback
(bind ?msg-ptr (<package-kebab>-<action-kebab>-feedback-create))
(<package-kebab>-<action-kebab>-feedback-destroy ?msg-ptr)
(<package-kebab>-<action-kebab>-feedback-set-field ?msg-ptr ?field-name ?field-value)
(<package-kebab>-<action-kebab>-feedback-get-field ?msg-ptr ?field-name)

; Creating, destroying and processing of results
(bind ?msg-ptr (<package-kebab>-<action-kebab>-result-create))
(<package-kebab>-<action-kebab>-result-destroy ?msg-ptr)
(<package-kebab>-<action-kebab>-result-set-field ?msg-ptr ?field-name ?field-value)
(<package-kebab>-<action-kebab>-result-get-field ?msg-ptr ?field-name)

; Destroy server goal handle pointer.
(<package-kebab>-<action-kebab>-server-goal-handle-destroy ?handle-ptr)
; server goal handle members (see rclcpp_action documentation)
(<package-kebab>-<action-kebab>-server-goal-handle-abort ?handle-ptr ?result-ptr)
(<package-kebab>-<action-kebab>-server-goal-handle-succeed ?handle-ptr ?result-ptr)
(<package-kebab>-<action-kebab>-server-goal-handle-canceled ?handle-ptr ?result-ptr)
(bind ?goal-ptr (<package-kebab>-<action-kebab>-server-goal-handle-get-goal ?handle-ptr))
; the goal id is returned as string representation via rclcpp_action::to_string()
(bind ?uuid-str (<package-kebab>-<action-kebab>-server-goal-handle-get-goal-id ?handle-ptr))
(bind ?bool-sym (<package-kebab>-<action-kebab>-server-goal-handle-is-canceling ?handle-ptr))
(bind ?bool-sym (<package-kebab>-<action-kebab>-server-goal-handle-is-active ?handle-ptr))
(bind ?bool-sym (<package-kebab>-<action-kebab>-server-goal-handle-is-executing ?handle-ptr))
(<package-kebab>-<action-kebab>-server-goal-handle-execute ?handle-ptr)
(<package-kebab>-<action-kebab>-server-goal-handle-publish-feedback ?handle-ptr ?feedback-ptr)

; client goal handle members (see rclcpp_action documentation)
(bind ?bool-sym (<package-kebab>-<action-kebab>-client-goal-handle-is-feedback-aware ?handle-ptr))
(bind ?bool-sym (<package-kebab>-<action-kebab>-client-goal-handle-is-result-aware ?handle-ptr))
; return codes:
; 0 = STATUS_UNKNOWN
; 1 = STATUS_ACCEPTED
; 2 = STATUS_EXECUTING
; 3 = STATUS_CANCELING
; 4 = STATUS_SUCCEEDED
; 5 = STATUS_CANCELED
; 6 = STATUS_ABORTED
(bind ?status-int (<package-kebab>-<action-kebab>-client-goal-handle-get-status ?handle-ptr))
; the goal id is returned as string representation via rclcpp_action::to_string()
(bind ?uuid-str (<package-kebab>-<action-kebab>-client-goal-handle-get-goal-id ?handle-ptr))
(bind ?time-seconds-float (<package-kebab>-<action-kebab>-client-goal-handle-get-goal-stamp ?handle-ptr))

Functions Defined by User

The following functions are called at the appropriate places if they are defined by the user.

; Gets called for each server receiving a goal, needs to return one of these integers:
; (return 1) ; REJECT
; (return 2) ; ACCEPT_AND_EXECUTE
; (return 3) ; ACCEPT_AND_DEFER
; If the function does not exist, every goal is automatically accepted (ACCEPT_AND_EXECUTE)
(bind ?response-int (<package-kebab>-<action-kebab>-handle-goal-callback ?server-name-str ?goal-ptr ?uuid-str))

; Gets called for each server receiving a cancellation request, needs to return one of these integers: ; (return 0) ; REJECT ; (return 1) ; ACCEPT ; If the function does not exist, every request is automatically accepted (ACCEPT) (bind ?response-int (<package-kebab>-<action-kebab>-cancel-goal-callback ?server-name-str ?server-goal-handle-ptr))

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/fibonacci_action.yaml

It creates a std_srvs/srv/SetBool service /ros_cx_srv. The services answers by giving the requested value in success.

A simple service call can be made using the ROS CLI tool:

ros2 service call /ros_cx_srv std_srvs/srv/SetBool "{data: false}"

Additionally, if true was requested, the example makes a new request with data true to a service called /ros_cx_srv_client. To start a simple server accepting the request, simply run the following command:

ros2 run cx_bringup test_service.py

Configuration

File cx_bringup/params/plugin_examples/fibonacci_action.yaml.

clips_manager:
  ros__parameters:
    environments: ["cx_fibonacci_action"]
    cx_fibonacci_action:
      plugins: ["executive", "fibonacci", "files"]
      log_clips_to_file: true
      watch: ["facts", "rules"]

    executive:
      plugin: "cx::ExecutivePlugin"
      publish_on_refresh: false
      assert_time: true
      refresh_rate: 10
    fibonacci:
      plugin: "cx::CXExampleInterfacesFibonacciPlugin"
    files:
      plugin: "cx::FileLoadPlugin"
      pkg_share_dirs: ["cx_bringup"]
      load: [
        "clips/plugin_examples/fibonacci-action.clp"]

Code

File cx_bringup/clips/plugin_examples/fibonacci-action.clp.

(deffunction example-interfaces-fibonacci-handle-goal-callback (?server ?goal ?uuid)
  (printout blue ?server " callback (goal " ?goal " ; id " ?uuid  " )" crlf)
  ; (return 1) ; REJECT
  (return 2) ; ACCEPT_AND_EXECUTE
  ; (return 3) ; ACCEPT_AND_DEFER
)

(deffunction example-interfaces-fibonacci-cancel-goal-callback (?server ?goal ?goal-handle)
  ; (return 0) ; REJECT
  (return 1) ; ACCEPT
)

(defrule fibonacci-action-client-server-init
" Create a simple client and service using the generated bindings. "
  (not (example-interfaces-fibonacci-client (server "ros_cx_fibonacci")))
  (not (example-interfaces-fibonacci-server (name "ros_cx_fibonacci")))
  (not (executive-finalize))
  ;(not (client-server-already-created))
=>
  ;(assert (client-server-already-created))
  (example-interfaces-fibonacci-create-client "ros_cx_fibonacci")
  (printout info "Created client for /ros_cx_fibonacci" crlf)
  (example-interfaces-fibonacci-create-server "ros_cx_fibonacci")
  (printout info "Created server for /ros_cx_fibonacci" crlf)
)

(deftemplate fibonacci
  (slot uuid (type STRING))
  (slot order (type INTEGER))
  (slot progress (type INTEGER))
  (multislot sequence (type INTEGER))
  (slot result (type INTEGER))
  (slot last-computed (type FLOAT))
)

(defrule fibonacci-goal-accepted-start-compute
  (example-interfaces-fibonacci-accepted-goal (server ?server) (server-goal-handle-ptr ?ptr))
  (not (fibonacci (uuid ?uuid&:(eq ?uuid (example-interfaces-fibonacci-server-goal-handle-get-goal-id ?ptr)))))
  =>
  (if (not (example-interfaces-fibonacci-server-goal-handle-is-canceling ?ptr)) then
    (bind ?goal (example-interfaces-fibonacci-server-goal-handle-get-goal ?ptr))
    (bind ?order (example-interfaces-fibonacci-goal-get-field ?goal "order"))
    (bind ?uuid (example-interfaces-fibonacci-server-goal-handle-get-goal-id ?ptr))
    (assert (fibonacci (uuid ?uuid) (order ?order) (progress 2) (result 0) (sequence (create$ 0 1)) (last-computed (now))))
   else
    (printout error "Somehow the goal is canceling already" crlf)
  )
  ; do not destroy the server goal handle here, only do it once the goal is fully processed and finished
  ; (example-interfaces-fibonacci-server-goal-handle-destroy ?ptr)
)

(defrule fibonacci-compute-next
  (example-interfaces-fibonacci-accepted-goal (server ?server) (server-goal-handle-ptr ?ptr))
  ?f <- (fibonacci (order ?order) (progress ?remaining&:(>= ?order ?remaining))
  (last-computed ?computed) (result ?old-res) (sequence $?seq) (uuid ?uuid))
  (time ?now&:(> (- ?now ?computed) 1))
  (test (eq ?uuid (example-interfaces-fibonacci-server-goal-handle-get-goal-id ?ptr)))
  =>
  (bind ?step (+ ?remaining 1))
  (bind ?res (+ (nth$ ?remaining ?seq) (nth$ (- ?remaining 1) ?seq)))
  (printout magenta "Computing partial result fibonacci(" ?remaining ") = " ?res crlf)
  (bind ?seq (create$ ?seq ?res))
  (modify ?f (progress ?step) (result (+ ?old-res ?res)) (sequence ?seq))
  (bind ?feedback (example-interfaces-fibonacci-feedback-create))
  (example-interfaces-fibonacci-feedback-set-field ?feedback "sequence" ?seq)
  (example-interfaces-fibonacci-server-goal-handle-publish-feedback ?ptr ?feedback)
  (example-interfaces-fibonacci-feedback-destroy ?feedback)
  (modify ?f (last-computed ?now))
)

(defrule fibonacci-compute-done
  ?ag <- (example-interfaces-fibonacci-accepted-goal (server ?server) (server-goal-handle-ptr ?ptr))
  ?f <- (fibonacci (order ?order) (progress ?remaining&:(< ?order ?remaining)) (result ?old-res) (sequence $?seq) (uuid ?uuid&:(eq ?uuid (example-interfaces-fibonacci-server-goal-handle-get-goal-id ?ptr))))
  =>
  (printout green "Final fibonacci sequence (server): " ?seq crlf)
  (bind ?result (example-interfaces-fibonacci-result-create))
  (example-interfaces-fibonacci-result-set-field ?result "sequence" ?seq)
  (example-interfaces-fibonacci-server-goal-handle-succeed ?ptr ?result)
  (example-interfaces-fibonacci-result-destroy ?result)
  (example-interfaces-fibonacci-server-goal-handle-destroy ?ptr)
  (retract ?f)
  (retract ?ag)
)

(defrule fibonacci-client-send-goal
  (example-interfaces-fibonacci-client (server ?server))
  (not (send-request))
  =>
  (assert (send-request))
  (bind ?goal (example-interfaces-fibonacci-goal-create))
  (assert (fibnoacci-goal ?goal))
  (example-interfaces-fibonacci-goal-set-field ?goal "order" 5)
  (example-interfaces-fibonacci-send-goal ?goal ?server)

  ; do not destroy the goal here, only do it once the goal is fully processed and finished
  ; (example-interfaces-fibonacci-goal-destroy ?goal)
)

(defrule fibonacci-client-get-feedback
  (declare (salience 100))
  ?f <- (example-interfaces-fibonacci-goal-feedback (server ?server) (client-goal-handle-ptr ?ghp) (feedback-ptr ?fp))
  =>
  (bind ?g-id (example-interfaces-fibonacci-client-goal-handle-get-goal-id ?ghp))
  (bind ?g-stamp (example-interfaces-fibonacci-client-goal-handle-get-goal-stamp ?ghp))
  (bind ?g-status (example-interfaces-fibonacci-client-goal-handle-get-status ?ghp))
  (bind ?g-is-f-aware (example-interfaces-fibonacci-client-goal-handle-is-feedback-aware ?ghp))
  (bind ?g-is-r-aware (example-interfaces-fibonacci-client-goal-handle-is-result-aware ?ghp))
  ; the stamp seems to be broken (looks like a rclcpp_action issue)
  (printout cyan "[" (- (now) ?g-stamp) "] " ?g-status " " ?g-id " f " ?g-is-f-aware " r " ?g-is-r-aware crlf)
  (bind ?part-seq (example-interfaces-fibonacci-feedback-get-field ?fp "sequence"))
  (printout blue "partial sequence: " ?part-seq   crlf)
  (example-interfaces-fibonacci-feedback-destroy ?fp)
  (retract ?f)
)

(defrule fibonacci-client-cleanup-after-wrapped-result
  (declare (salience 10))
  ?f <- (example-interfaces-fibonacci-goal-response (server ?server) (client-goal-handle-ptr ?ghp))
  ?g <- (example-interfaces-fibonacci-wrapped-result (server ?server) (goal-id ?uuid) (code SUCCEEDED) (result-ptr ?rp))
  ?request-goal <- (fibnoacci-goal ?goal)
  (time ?now)
  =>
  (bind ?g-status (example-interfaces-fibonacci-client-goal-handle-get-status ?ghp))
  (if (> ?g-status 3) then ; status is final in one way or another
    (bind ?seq (example-interfaces-fibonacci-result-get-field ?rp "sequence"))
    (printout green "Final fibonacci sequence (client): " ?seq crlf)
    (example-interfaces-fibonacci-result-destroy ?rp)
    (retract ?g)
    (bind ?g-id (example-interfaces-fibonacci-client-goal-handle-get-goal-id ?ghp))
    (bind ?g-stamp (example-interfaces-fibonacci-client-goal-handle-get-goal-stamp ?ghp))
    (bind ?g-is-f-aware (example-interfaces-fibonacci-client-goal-handle-is-feedback-aware ?ghp))
    (bind ?g-is-r-aware (example-interfaces-fibonacci-client-goal-handle-is-result-aware ?ghp))
    (printout cyan "Final goal response [" (- (now) ?g-stamp) "] " ?uuid " " ?g-status " " ?g-id " f " ?g-is-f-aware " r " ?g-is-r-aware crlf)
    (example-interfaces-fibonacci-client-goal-handle-destroy ?ghp)
    (retract ?f)
    (example-interfaces-fibonacci-goal-destroy ?goal)
    (retract ?request-goal)
  )
)

(defrule fibonacci-client-server-cleanup
  (executive-finalize)
  (example-interfaces-fibonacci-client (server ?client))
  (example-interfaces-fibonacci-server (name ?server))
  =>
  (example-interfaces-fibonacci-destroy-client ?client)
  (example-interfaces-fibonacci-destroy-server ?server)
)

(defrule fibonacci-goal-response-cleanup
  (executive-finalize)
  ?f <- (example-interfaces-fibonacci-goal-response (client-goal-handle-ptr ?p))
  =>
  (example-interfaces-fibonacci-client-goal-handle-destroy ?p)
  (retract ?f)
)

(defrule fibonacci-accepted-goal-cleanup
  (executive-finalize)
  ?f <- (example-interfaces-fibonacci-accepted-goal (server-goal-handle-ptr ?p))
  =>
  (example-interfaces-fibonacci-server-goal-handle-destroy ?p)
  (retract ?f)
)

(defrule fibonacci-accepted-goal-cleanup
  (executive-finalize)
  ?f <- (fibnoacci-goal p)
  =>
  (example-interfaces-fibonacci--goal-destroy ?p)
  (retract ?f)
)