You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit d1e4dfb
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: _docs/tutorials/core/programming_rcl_rclc/index.md
+136-6Lines changed: 136 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -380,15 +380,15 @@ if (rc != RCL_RET_OK) {
380
380
printf("Error in rclc_executor_add_timer.\n");
381
381
}
382
382
```
383
-
A key feature of the rclc-Executor is, that the order of these `rclc-executor-add-* `-functions matters. It defines static processing order of the callbacks when the spin-function is called.
383
+
A key feature of the rclc-Executor is, that the order of these `rclc-executor-add-* `-functions matters. The order in which these functions are called, defines the static processing order of the callbacks when the spin-function of the executor is running.
384
384
385
-
In this example, if the timer is ready and also a new message for the subscription is available, then the timer is executed first and then the subscription. Such a behavior cannot be defined currently with the rclcpp Executor.
385
+
In this example, the timer was added to the executor before the subscription. Therefore, if the timer is ready and also a new message for the subscription is available, then the timer is executed first and after it the subscription. Such a behavior cannot be defined currently with the rclcpp Executor and is useful to implement a deterministic execution semantics.
386
386
387
-
The easiest way to run the Executor is to call `rclc_executor_spin()`:
387
+
Finally, you can run the executor with `rclc_executor_spin()`:
388
388
```C
389
389
rclc_executor_spin(&executor);
390
390
```
391
-
This function runs forever without coming back. In this examplewe want to publish the message only ten times. Therefore we are using another spin-method `rclc_executor_spin_some`, which spins once and returns. The timeout for waiting for new messages is one second
391
+
This function runs forever without coming back. In this example, however, we want to publish the message only ten times. Therefore we are using the spin-method `rclc_executor_spin_some`, which spins only once and returns. The wait timeout for checking for new messages at the DDS-queue or waiting timers to get ready is configured to be one second.
392
392
```C
393
393
for (unsignedint i = 0; i < 10; i++) {
394
394
// timeout specified in nanoseconds (here 1s)
@@ -417,7 +417,7 @@ return 0;
417
417
} // main
418
418
```
419
419
420
-
This completes the example. The source code can be found in [rclc-examples/example_executor_convenience.c](https://github.com/micro-ROS/rclc-examples/example_executor_convenience.c).
420
+
This completes the example. The source code can be found in the package rclc-examples [rclc-examples/example_executor_convenience.c](https://github.com/micro-ROS/rclc-examples/example_executor_convenience.c).
421
421
422
422
#### Example 2: Triggered rclc_executor
423
423
Sesor fusion is the first step in robotic applications when multiple sensor are used to improve localization precision. These sensors can have different frequencies, for example, a high frequency IMU sensor and a low frequency laser scanner. One way is to trigger execution upon arrival of a laser scan and only then evaluate the most recent data from the aggregated IMU data.
@@ -463,7 +463,7 @@ typedef struct
463
463
rcl_subscription_t * sub2;
464
464
} sub_trigger_object_t;
465
465
```
466
-
The executor for the publishers, shall publish when any of corresponding timers for the publishers is ready. That is the or-logic. You could also use the predefined `rclc_executor_trigger_any` trigger condition, but this example shows, how you can write your own trigger conditions.
466
+
The executor for the publishers, shall publish when any of corresponding timers for the publishers is ready. That is the or-logic. You could also use the predefined `rclc_executor_trigger_any` trigger condition, but this example shows, how you can write your own trigger conditions.
467
467
468
468
In principle the condition gets a list of handles, the length of this list, and the pre-defined condition type, in this case we expect `pub_trigger_object_t`. First, the parameter `obj` is cased to this type (`comm_obj`). Then, each element of the handle list is checked for new data (or a timer is ready) by evaluating the field `handles[i].data_available` and its handle pointer is compared to the pointer of the communicatoin object. If at least one timer is ready, then the trigger condition returns true.
The trigger condition for the subscription `sub_trigger`shall implement an AND-logic. That is, only if both subscriptions have received a new message, then the executor shall start processing the callbacks.
503
+
504
+
The implementation is analogous to `pub_trigger`. The only difference is, that this trigger returns true, if both subscriptions have been found in the handle list. This is implemented in the condition `sub1 && sub2` of the last if-statement.
505
+
506
+
```C
507
+
bool sub_trigger(rclc_executor_handle_t * handles, unsigned int size, void * obj)
508
+
{
509
+
if (handles == NULL) {
510
+
printf("Error in sub_trigger: 'handles' is a NULL pointer\n");
511
+
return false;
512
+
}
513
+
if (obj == NULL) {
514
+
printf("Error in sub_trigger: 'obj' is a NULL pointer\n");
printf("my_int_subscriber_callback: msgin is NULL\n");
562
+
} else {
563
+
printf("Callback 2: %d\n", msg->data);
564
+
}
565
+
}
566
+
```
567
+
To publish messages with different frequencies, we setup two timers.
568
+
One timer to publish a string message, the `my_timer_string_callback` and one timer to publish the integer, the `my_timer_int_callback`.
569
+
570
+
In the `my_timer_string_callback`, the message `pub_msg` is created and filled with the string `Hello World` plus an integer, which is incremented by one, each time the timer callback is called. The the message is published with `rcl_publish()`
571
+
572
+
The macro `UNUSED` is a workaround for the linter warning, that the second parameter `last_call_time` is not used.
printf("Error in my_timer_string_callback: publishing message %s\n", pub_msg.data.data);
595
+
}
596
+
std_msgs__msg__String__fini(&pub_msg);
597
+
} else {
598
+
printf("Error in my_timer_string_callback: timer parameter is NULL\n");
599
+
}
600
+
}
601
+
```
602
+
Likewise, the `my_timer_int_callback` increments the integer value `pub_int_value` in every call and assigns it to the message field `pub_int_msg.data`. Then the message is published with `rcl_publish()`
0 commit comments