2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Contact: Jeonghoon Park <jh1979.park@samsung.com>
6 * Licensed under the Flora License, Version 1.1 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://floralicense.org/license/
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an AS IS BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
24 #include <service_app.h>
29 #include "cloud/cloud_communication.h"
30 #include "messages/message_manager.h"
31 #include "controller_connection_manager.h"
32 #include "lap_counter/lap_counter.h"
35 #define ENABLE_MOTOR 1
36 #define STERING_SERVO_CENTER 340
37 #define STERING_SERVO_RANGE 125
39 #define MAX_UDP_INPUT 10000
41 #define CONFIG_GRP_CAR "Car"
42 #define CONFIG_GRP_STEERING "Steering"
43 #define CONFIG_GRP_CAMERA "Camera"
44 #define CONFIG_GRP_ENGINE "Engine"
45 #define CONFIG_GRP_RPI "Rpi"
47 #define CONFIG_KEY_ID "Id"
48 #define CONFIG_KEY_NAME "Name"
50 #define CONFIG_KEY_STEERING_CENTER "Center"
51 #define CONFIG_KEY_STEERING_RANGE "Range"
52 #define CONFIG_KEY_CAMERA_AZIMUTH_CENTER "Azimuth.Center"
53 #define CONFIG_KEY_CAMERA_AZIMUTH_RANGE "Azimuth.Range"
54 #define CONFIG_KEY_CAMERA_ELEVATION_MIN "Elevation.Min"
55 #define CONFIG_KEY_CAMERA_ELEVATION_MAX "Elevation.Max"
56 #define CONFIG_KEY_CAMERA_ENGINE_MIN "Min"
57 #define CONFIG_KEY_CAMERA_ENGINE_MAX "Max"
59 #define CONFIG_KEY_RPI_PIN_STERING "Stering"
60 #define CONFIG_KEY_RPI_PIN_CAMERA_AZIMUTH "Azimuth"
61 #define CONFIG_KEY_RPI_PIN_CAMERA_ELEVATION "Elevation"
63 #define CONFIG_KEY_RPI_PIN_ENGINE_1_FORWARD "1.forward"
64 #define CONFIG_KEY_RPI_PIN_ENGINE_1_BACK "1.back"
65 #define CONFIG_KEY_RPI_ENGINE_CHANNEL_1 "Channel.1"
66 #define CONFIG_KEY_RPI_PIN_ENGINE_2_FORWARD "2.forward"
67 #define CONFIG_KEY_RPI_PIN_ENGINE_2_BACK "2.back"
68 #define CONFIG_KEY_RPI_ENGINE_CHANNEL_2 "Channel.2"
70 #define CLOUD_REQUESTS_FREQUENCY 15
72 #define ELEVATION_MIN 200
73 #define ELEVATION_MAX 400
74 #define AZIMUTH_MIN 200
75 #define AZIMUTH_MAX 700
83 typedef struct app_data_s {
86 unsigned int dir_state;
87 const char *user_name;
93 int camera_azimuth_center;
94 int camera_azimuth_range;
96 int camera_elevation_min;
97 int camera_elevation_max;
107 int engine_1_forward_pin;
108 int engine_1_back_pin;
109 int engine_1_channel;
111 int engine_2_forward_pin;
112 int engine_2_back_pin;
113 int engine_2_channel;
116 static app_data s_info = {
117 .stering_center = STERING_SERVO_CENTER,
118 .stering_range = STERING_SERVO_RANGE,
120 .camera_azimuth_center = (AZIMUTH_MAX + AZIMUTH_MIN) /2,
121 .camera_azimuth_range = AZIMUTH_MAX - ((AZIMUTH_MAX + AZIMUTH_MIN) /2),
123 .camera_elevation_min = ELEVATION_MIN,
124 .camera_elevation_max = ELEVATION_MAX,
134 .engine_1_forward_pin = 6,
135 .engine_1_back_pin = 5,
136 .engine_1_channel = 5,
138 .engine_2_forward_pin = 21,
139 .engine_2_back_pin = 20,
140 .engine_2_channel = 4,
143 static void _initialize_components(app_data *ad);
144 static void _initialize_config();
146 static void service_app_lang_changed(app_event_info_h event_info, void *user_data)
151 static void service_app_region_changed(app_event_info_h event_info, void *user_data)
156 static void service_app_low_battery(app_event_info_h event_info, void *user_data)
158 _E("low battery! exit app");
164 static void service_app_low_memory(app_event_info_h event_info, void *user_data)
169 static inline double __map_round(double val)
171 return floor(val + 0.5);
174 static int __map_range_val(int v_min, int v_max, int d_min, int d_max, int val)
178 slope = 1.0 * (d_max - d_min) / (v_max - v_min);
180 rval = d_min + __map_round(slope * (val - v_min));
185 static inline int ___map_speed_val(int speed)
187 return __map_range_val(-MAX_UDP_INPUT, MAX_UDP_INPUT, s_info.engine_min, s_info.engine_max, speed);
190 static inline int ___map_servo_val(int servo)
192 return __map_range_val(-MAX_UDP_INPUT, MAX_UDP_INPUT,
193 s_info.stering_center - s_info.stering_range,
194 s_info.stering_center + s_info.stering_range, servo);
197 static int __driving_motors(int servo, int speed)
202 val_servo = ___map_servo_val(servo);
203 val_speed = ___map_speed_val(speed);
205 _D("control motor - servo[%4d : %4d], speed[%4d : %4d]",
206 servo, val_servo, speed, val_speed);
208 resource_set_servo_motor_value(0, val_servo);
209 resource_set_motor_driver_L298N_speed(MOTOR_ID_1, val_speed);
210 resource_set_motor_driver_L298N_speed(MOTOR_ID_2, val_speed);
216 static void __camera(int azimuth, int elevation)
218 int val_azimuth = __map_range_val(-MAX_UDP_INPUT, MAX_UDP_INPUT,
219 s_info.camera_azimuth_center - s_info.camera_azimuth_range,
220 s_info.camera_azimuth_center + s_info.camera_azimuth_range, azimuth);
222 int val_elevation = __map_range_val(0, MAX_UDP_INPUT, s_info.camera_elevation_min, s_info.camera_elevation_max, elevation); // No need to look upside down
224 _D("camera - azimuth[%4d : %4d], elevation[%4d : %4d]", azimuth, val_azimuth, elevation, val_elevation);
226 resource_set_servo_motor_value(s_info.elevation_pin, val_elevation);
227 resource_set_servo_motor_value(s_info.azimuth_pin, val_azimuth);
231 static void __command_received_cb(command_s command) {
232 switch(command.type) {
233 case COMMAND_TYPE_DRIVE:
234 __driving_motors(command.data.steering.direction, command.data.steering.speed);
236 case COMMAND_TYPE_CAMERA:
237 __camera(command.data.camera_position.camera_azimuth, command.data.camera_position.camera_elevation);
239 case COMMAND_TYPE_DRIVE_AND_CAMERA:
240 __driving_motors(command.data.steering_and_camera.direction, command.data.steering_and_camera.speed);
241 __camera(command.data.steering_and_camera.camera_azimuth, command.data.steering_and_camera.camera_elevation);
243 case COMMAND_TYPE_NONE:
246 _E("Unknown command type");
251 static void __user_name_received_cb(const char *name)
253 _D("User name received: %s", name);
254 lap_counter_set_user_name(name);
255 lap_counter_set_start_lap();
258 static void _initialize_config()
266 gboolean modified = false;
268 if (config_get_string(CONFIG_GRP_CAR, CONFIG_KEY_ID, &id) != 0) {
269 char *uuid = g_uuid_string_random();
270 config_set_string(CONFIG_GRP_CAR, CONFIG_KEY_ID, uuid);
275 char *uuid = g_uuid_string_random();
276 modified |= config_get_string_or_set_default(CONFIG_GRP_CAR, CONFIG_KEY_ID, uuid, &id);
279 modified |= config_get_string_or_set_default(CONFIG_GRP_CAR, CONFIG_KEY_NAME, "Passerati", &name);
281 modified |= config_get_int_with_default(CONFIG_GRP_STEERING, CONFIG_KEY_STEERING_CENTER, s_info.stering_center, &s_info.stering_center);
282 modified |= config_get_int_with_default(CONFIG_GRP_STEERING, CONFIG_KEY_STEERING_RANGE, s_info.stering_range, &s_info.stering_range);
284 modified |= config_get_int_with_default(CONFIG_GRP_CAMERA, CONFIG_KEY_CAMERA_AZIMUTH_CENTER, s_info.camera_azimuth_center, &s_info.camera_azimuth_center);
285 modified |= config_get_int_with_default(CONFIG_GRP_CAMERA, CONFIG_KEY_CAMERA_AZIMUTH_RANGE, s_info.camera_azimuth_range, &s_info.camera_azimuth_range);
286 modified |= config_get_int_with_default(CONFIG_GRP_CAMERA, CONFIG_KEY_CAMERA_ELEVATION_MIN, s_info.camera_elevation_min, &s_info.camera_elevation_min);
287 modified |= config_get_int_with_default(CONFIG_GRP_CAMERA, CONFIG_KEY_CAMERA_ELEVATION_MAX, s_info.camera_elevation_max, &s_info.camera_elevation_max);
289 modified |= config_get_int_with_default(CONFIG_GRP_ENGINE, CONFIG_KEY_CAMERA_ENGINE_MIN, s_info.engine_min, &s_info.engine_min);
290 modified |= config_get_int_with_default(CONFIG_GRP_ENGINE, CONFIG_KEY_CAMERA_ENGINE_MAX, s_info.engine_max, &s_info.engine_max);
292 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_PIN_STERING, s_info.stering_pin, &s_info.stering_pin);
293 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_PIN_CAMERA_AZIMUTH, s_info.azimuth_pin, &s_info.azimuth_pin);
294 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_PIN_CAMERA_ELEVATION, s_info.elevation_pin, &s_info.elevation_pin);
296 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_PIN_ENGINE_1_FORWARD, s_info.engine_1_forward_pin, &s_info.engine_1_forward_pin);
297 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_PIN_ENGINE_1_BACK, s_info.engine_1_back_pin, &s_info.engine_1_back_pin);
298 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_ENGINE_CHANNEL_1, s_info.engine_1_channel, &s_info.engine_1_channel);
300 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_PIN_ENGINE_2_FORWARD, s_info.engine_2_forward_pin, &s_info.engine_2_forward_pin);
301 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_PIN_ENGINE_2_BACK, s_info.engine_2_back_pin, &s_info.engine_2_back_pin);
302 modified |= config_get_int_with_default(CONFIG_GRP_RPI, CONFIG_KEY_RPI_ENGINE_CHANNEL_2, s_info.engine_2_channel, &s_info.engine_2_channel);
304 if (modified == true) {
312 static void _initialize_components(app_data *ad)
315 _initialize_config();
316 cloud_communication_init();
317 message_manager_init();
318 controller_connection_manager_listen();
323 _D("Car settings: Stering[%d +/- %d] Engine[%d - %d], CamAzimuth[%d +/- %d], CamElev[%d - %d]",
324 s_info.stering_center, s_info.stering_range,
325 s_info.engine_min, s_info.engine_max,
326 s_info.camera_azimuth_center, s_info.camera_azimuth_range,
327 s_info.camera_elevation_min, s_info.camera_elevation_max);
329 _D("RPI: Stering[%d], Azimuth[%d], Elev[%d]; ENG_1[%d, %d, %d]; ENG_2[%d, %d, %d];",
330 s_info.stering_pin, s_info.azimuth_pin, s_info.elevation_pin,
331 s_info.engine_1_forward_pin, s_info.engine_1_back_pin, s_info.engine_1_channel,
332 s_info.engine_2_forward_pin, s_info.engine_2_back_pin, s_info.engine_2_channel);
335 static bool service_app_create(void *data)
340 _D("-----------------------=======================================================================-----------------------");
341 _D("-----------------------=======================================================================-----------------------");
342 _D("-----------------------============================== APP %s %s ==============================-----------------------", __DATE__, __TIME__);
343 _D("-----------------------=======================================================================-----------------------");
344 _D("-----------------------=======================================================================-----------------------");
347 * if you want to use default configuration,
348 * Do not need to call resource_set_motor_driver_L298N_configuration(),
352 ret = resource_set_motor_driver_L298N_configuration(MOTOR_ID_1, s_info.engine_1_forward_pin, s_info.engine_1_back_pin, s_info.engine_1_channel);
354 _E("resource_set_motor_driver_L298N_configuration()");
357 ret = resource_set_motor_driver_L298N_configuration(MOTOR_ID_2, s_info.engine_2_forward_pin, s_info.engine_2_back_pin, s_info.engine_2_channel);
359 _E("resource_set_motor_driver_L298N_configuration()");
364 _initialize_components(ad);
365 resource_lap_counter_init();
366 cloud_communication_start(CLOUD_REQUESTS_FREQUENCY);
368 controller_connection_manager_set_command_received_cb(__command_received_cb);
369 controller_connection_manager_set_user_name_received_cb(__user_name_received_cb);
371 resource_bi_led_set(LED_COLOR_RED);
376 static void service_app_control(app_control_h app_control, void *data)
380 /* set speed 0, to reduce delay of initializing motor driver */
381 resource_set_motor_driver_L298N_speed(MOTOR_ID_1, 0);
382 resource_set_motor_driver_L298N_speed(MOTOR_ID_2, 0);
383 resource_set_servo_motor_value(s_info.stering_pin, STERING_SERVO_CENTER);
384 resource_set_servo_motor_value(s_info.elevation_pin, ELEVATION_MIN);
385 resource_set_servo_motor_value(s_info.azimuth_pin, (AZIMUTH_MIN + AZIMUTH_MAX) / 2);
391 static void service_app_terminate(void *data)
394 resource_bi_led_set(LED_COLOR_NONE);
396 resource_set_servo_motor_value(s_info.stering_pin, STERING_SERVO_CENTER);
397 resource_set_servo_motor_value(s_info.elevation_pin, ELEVATION_MIN);
398 resource_set_servo_motor_value(s_info.azimuth_pin, (AZIMUTH_MIN + AZIMUTH_MAX) / 2);
400 resource_lap_counter_destroy();
401 resource_led_destroy();
404 g_source_remove(ad->idle_h);
406 lap_counter_shutdown();
407 controller_connection_manager_release();
408 message_manager_shutdown();
410 cloud_communication_stop();
411 cloud_communication_fini();
415 resource_close_all();
423 int main(int argc, char* argv[])
427 service_app_lifecycle_callback_s event_callback;
428 app_event_handler_h handlers[5] = {NULL, };
430 log_type_set(LOG_TYPE_DLOG);
432 ad = calloc(1, sizeof(app_data));
435 event_callback.create = service_app_create;
436 event_callback.terminate = service_app_terminate;
437 event_callback.app_control = service_app_control;
439 service_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY],
440 APP_EVENT_LOW_BATTERY, service_app_low_battery, &ad);
441 service_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY],
442 APP_EVENT_LOW_MEMORY, service_app_low_memory, &ad);
443 service_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED],
444 APP_EVENT_LANGUAGE_CHANGED, service_app_lang_changed, &ad);
445 service_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED],
446 APP_EVENT_REGION_FORMAT_CHANGED, service_app_region_changed, &ad);
448 ret = service_app_main(argc, argv, &event_callback, ad);
450 _E("failed to start app");