-
Notifications
You must be signed in to change notification settings - Fork 55
Expand file tree
/
Copy pathapp.c
More file actions
160 lines (122 loc) · 4.93 KB
/
app.c
File metadata and controls
160 lines (122 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <rcl/rcl.h>
#include <rcl/error_handling.h>
#include <rclc/rclc.h>
#include <rclc/executor.h>
#include <std_msgs/msg/header.h>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#endif
#define STRING_BUFFER_LEN 50
#define RCCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){printf("Failed status on line %d: %d. Aborting.\n",__LINE__,(int)temp_rc); vTaskDelete(NULL);}}
#define RCSOFTCHECK(fn) { rcl_ret_t temp_rc = fn; if((temp_rc != RCL_RET_OK)){printf("Failed status on line %d: %d. Continuing.\n",__LINE__,(int)temp_rc);}}
rcl_publisher_t ping_publisher;
rcl_publisher_t pong_publisher;
rcl_subscription_t ping_subscriber;
rcl_subscription_t pong_subscriber;
std_msgs__msg__Header incoming_ping;
std_msgs__msg__Header outcoming_ping;
std_msgs__msg__Header incoming_pong;
int device_id;
int seq_no;
int pong_count;
void ping_timer_callback(rcl_timer_t * timer, int64_t last_call_time)
{
RCLC_UNUSED(last_call_time);
if (timer != NULL) {
seq_no = rand();
sprintf(outcoming_ping.frame_id.data, "%d_%d", seq_no, device_id);
outcoming_ping.frame_id.size = strlen(outcoming_ping.frame_id.data);
// Fill the message timestamp
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
outcoming_ping.stamp.sec = ts.tv_sec;
outcoming_ping.stamp.nanosec = ts.tv_nsec;
// Reset the pong count and publish the ping message
pong_count = 0;
rcl_publish(&ping_publisher, (const void*)&outcoming_ping, NULL);
printf("Ping send seq %s\n", outcoming_ping.frame_id.data);
}
}
void ping_subscription_callback(const void * msgin)
{
const std_msgs__msg__Header * msg = (const std_msgs__msg__Header *)msgin;
// Dont pong my own pings
if(strcmp(outcoming_ping.frame_id.data, msg->frame_id.data) != 0){
printf("Ping received with seq %s. Answering.\n", msg->frame_id.data);
rcl_publish(&pong_publisher, (const void*)msg, NULL);
}
}
void pong_subscription_callback(const void * msgin)
{
const std_msgs__msg__Header * msg = (const std_msgs__msg__Header *)msgin;
if(strcmp(outcoming_ping.frame_id.data, msg->frame_id.data) == 0) {
pong_count++;
printf("Pong for seq %s (%d)\n", msg->frame_id.data, pong_count);
}
}
void appMain(void *argument)
{
#if defined(CONFIG_ESP_WIFI_AP)
volatile bool *is_sta = (volatile bool *) argument;
// Wait for a connection to the wifi AP. The first to connect
// is considered the agent
while (! *is_sta) {
usleep(100000);
}
#endif // if defined(CONFIG_ESP_WIFI_AP)
rcl_allocator_t allocator = rcl_get_default_allocator();
rclc_support_t support;
// create init_options
RCCHECK(rclc_support_init(&support, 0, NULL, &allocator));
// create node
rcl_node_t node;
RCCHECK(rclc_node_init_default(&node, "pingpong_node", "", &support));
// Create a reliable ping publisher
RCCHECK(rclc_publisher_init_default(&ping_publisher, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Header), "/microROS/ping"));
// Create a best effort pong publisher
RCCHECK(rclc_publisher_init_best_effort(&pong_publisher, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Header), "/microROS/pong"));
// Create a best effort ping subscriber
RCCHECK(rclc_subscription_init_best_effort(&ping_subscriber, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Header), "/microROS/ping"));
// Create a best effort pong subscriber
RCCHECK(rclc_subscription_init_best_effort(&pong_subscriber, &node,
ROSIDL_GET_MSG_TYPE_SUPPORT(std_msgs, msg, Header), "/microROS/pong"));
// Create a 3 seconds ping timer timer,
rcl_timer_t timer;
RCCHECK(rclc_timer_init_default(&timer, &support, RCL_MS_TO_NS(2000), ping_timer_callback));
// Create executor
rclc_executor_t executor;
RCCHECK(rclc_executor_init(&executor, &support.context, 3, &allocator));
RCCHECK(rclc_executor_add_timer(&executor, &timer));
RCCHECK(rclc_executor_add_subscription(&executor, &ping_subscriber, &incoming_ping,
&ping_subscription_callback, ON_NEW_DATA));
RCCHECK(rclc_executor_add_subscription(&executor, &pong_subscriber, &incoming_pong,
&pong_subscription_callback, ON_NEW_DATA));
// Create and allocate the pingpong messages
char outcoming_ping_buffer[STRING_BUFFER_LEN];
outcoming_ping.frame_id.data = outcoming_ping_buffer;
outcoming_ping.frame_id.capacity = STRING_BUFFER_LEN;
char incoming_ping_buffer[STRING_BUFFER_LEN];
incoming_ping.frame_id.data = incoming_ping_buffer;
incoming_ping.frame_id.capacity = STRING_BUFFER_LEN;
char incoming_pong_buffer[STRING_BUFFER_LEN];
incoming_pong.frame_id.data = incoming_pong_buffer;
incoming_pong.frame_id.capacity = STRING_BUFFER_LEN;
device_id = rand();
while(1){
rclc_executor_spin_some(&executor, RCL_MS_TO_NS(10));
usleep(10000);
}
// Free resources
RCCHECK(rcl_publisher_fini(&ping_publisher, &node));
RCCHECK(rcl_publisher_fini(&pong_publisher, &node));
RCCHECK(rcl_subscription_fini(&ping_subscriber, &node));
RCCHECK(rcl_subscription_fini(&pong_subscriber, &node));
RCCHECK(rcl_node_fini(&node));
}