Car params loaded using config api
[apps/native/gear-racing-car.git] / src / app.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
4  * Contact: Jeonghoon Park <jh1979.park@samsung.com>
5  *
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
9  *
10  * http://floralicense.org/license/
11  *
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.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <math.h>
23 #include <glib.h>
24 #include <service_app.h>
25 #include "log.h"
26 #include "resource.h"
27 #include "net-util.h"
28 #include "config.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"
33 #include "command.h"
34
35 #define ENABLE_MOTOR 1
36 #define STERING_SERVO_CENTER 340
37 #define STERING_SERVO_RANGE 125
38
39 #define MAX_UDP_INPUT 10000
40
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"
46
47 #define CONFIG_KEY_ID "Id"
48 #define CONFIG_KEY_NAME "Name"
49
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"
58
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"
62
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"
69
70 #define CLOUD_REQUESTS_FREQUENCY 15
71
72 #define ELEVATION_MIN 200
73 #define ELEVATION_MAX 400
74 #define AZIMUTH_MIN 200
75 #define AZIMUTH_MAX 700
76
77 enum {
78         DIR_STATE_S,
79         DIR_STATE_F,
80         DIR_STATE_B,
81 };
82
83 typedef struct app_data_s {
84         unsigned int f_value;
85         unsigned int r_value;
86         unsigned int dir_state;
87         const char *user_name;
88         guint idle_h;
89
90         int stering_center;
91         int stering_range;
92
93         int camera_azimuth_center;
94         int camera_azimuth_range;
95
96         int camera_elevation_min;
97         int camera_elevation_max;
98
99         int engine_min;
100         int engine_max;
101
102         int stering_pin;
103
104         int elevation_pin;
105         int azimuth_pin;
106
107         int engine_1_forward_pin;
108         int engine_1_back_pin;
109         int engine_1_channel;
110
111         int engine_2_forward_pin;
112         int engine_2_back_pin;
113         int engine_2_channel;
114 } app_data;
115
116 static app_data s_info = {
117                 .stering_center = STERING_SERVO_CENTER,
118                 .stering_range = STERING_SERVO_RANGE,
119
120                 .camera_azimuth_center = (AZIMUTH_MAX + AZIMUTH_MIN) /2,
121                 .camera_azimuth_range = AZIMUTH_MAX - ((AZIMUTH_MAX + AZIMUTH_MIN) /2),
122
123                 .camera_elevation_min = ELEVATION_MIN,
124                 .camera_elevation_max = ELEVATION_MAX,
125
126                 .engine_min = -4095,
127                 .engine_max = 4095,
128
129                 .stering_pin = 0,
130
131                 .elevation_pin = 14,
132                 .azimuth_pin = 15,
133
134                 .engine_1_forward_pin = 19,
135                 .engine_1_back_pin = 16,
136                 .engine_1_channel = 5,
137
138                 .engine_2_forward_pin = 24,
139                 .engine_2_back_pin = 20,
140                 .engine_2_channel = 4,
141 };
142
143 static void _initialize_components(app_data *ad);
144 static void _initialize_config();
145
146 static void service_app_lang_changed(app_event_info_h event_info, void *user_data)
147 {
148         return;
149 }
150
151 static void service_app_region_changed(app_event_info_h event_info, void *user_data)
152 {
153         return;
154 }
155
156 static void service_app_low_battery(app_event_info_h event_info, void *user_data)
157 {
158         _E("low battery! exit app");
159         service_app_exit();
160
161         return;
162 }
163
164 static void service_app_low_memory(app_event_info_h event_info, void *user_data)
165 {
166         return;
167 }
168
169 static inline double __map_round(double val)
170 {
171         return floor(val + 0.5);
172 }
173
174 static int __map_range_val(int v_min, int v_max, int d_min, int d_max, int val)
175 {
176         int rval = 0;
177         double slope = 0;
178         slope = 1.0 * (d_max - d_min) / (v_max - v_min);
179
180         rval = d_min + __map_round(slope * (val - v_min));
181
182         return rval;
183 }
184
185 static inline int ___map_speed_val(int speed)
186 {
187         return __map_range_val(-MAX_UDP_INPUT, MAX_UDP_INPUT, s_info.engine_min, s_info.engine_max, speed);
188 }
189
190 static inline int ___map_servo_val(int servo)
191 {
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);
195 }
196
197 static int __driving_motors(int servo, int speed)
198 {
199         int val_speed;
200         int val_servo;
201
202         val_servo = ___map_servo_val(servo);
203         val_speed = ___map_speed_val(speed);
204
205         _D("control motor - servo[%4d : %4d], speed[%4d : %4d]",
206                 servo, val_servo, speed, val_speed);
207 #if ENABLE_MOTOR
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);
211 #endif
212
213         return 0;
214 }
215
216 static void __camera(int azimuth, int elevation)
217 {
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);
221
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
223
224         _D("camera - azimuth[%4d : %4d], elevation[%4d : %4d]", azimuth, val_azimuth, elevation, val_elevation);
225 #if ENABLE_MOTOR
226         resource_set_servo_motor_value(s_info.elevation_pin, val_elevation);
227         resource_set_servo_motor_value(s_info.azimuth_pin, val_azimuth);
228 #endif
229 }
230
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);
235                 break;
236         case COMMAND_TYPE_CAMERA:
237                 __camera(command.data.camera_position.camera_azimuth, command.data.camera_position.camera_elevation);
238                 break;
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);
242                 break;
243         case COMMAND_TYPE_NONE:
244                 break;
245         default:
246                 _E("Unknown command type");
247                 break;
248         }
249 }
250
251 static void __user_name_received_cb(const char *name)
252 {
253         _D("User name received: %s", name);
254         lap_counter_set_user_name(name);
255         lap_counter_set_start_lap();
256 }
257
258 static void _initialize_config()
259 {
260         net_util_init();
261
262         config_init();
263
264         char *id = NULL;
265         char *name = NULL;
266         gboolean modified = false;
267
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);
271                 g_free(uuid);
272                 modified = true;
273         }
274
275         char *uuid = g_uuid_string_random();
276         modified |= config_get_string_or_set_default(CONFIG_GRP_CAR, CONFIG_KEY_ID, uuid, &id);
277         g_free(uuid);
278
279         modified |= config_get_string_or_set_default(CONFIG_GRP_CAR, CONFIG_KEY_NAME, "Passerati", &name);
280
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);
283
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);
288
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);
291
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);
295
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);
299
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);
303
304         if (modified == true) {
305                 config_save();
306         }
307
308         free(id);
309         free(name);
310 }
311
312 static void _initialize_components(app_data *ad)
313 {
314         net_util_init();
315         _initialize_config();
316         cloud_communication_init();
317         message_manager_init();
318         controller_connection_manager_listen();
319         lap_counter_init();
320
321         _D("Car settings: Stering[%d +/- %d] Engine[%d - %d], CamAzimuth[%d +/- %d], CamElev[%d - %d]",
322                         s_info.stering_center, s_info.stering_range,
323                         s_info.engine_min, s_info.engine_max,
324                         s_info.camera_azimuth_center, s_info.camera_azimuth_range,
325                         s_info.camera_elevation_min, s_info.camera_elevation_max);
326
327         _D("RPI: Stering[%d], Azimuth[%d], Elev[%d]; ENG_1[%d, %d, %d]; ENG_2[%d, %d, %d];",
328                         s_info.stering_pin, s_info.azimuth_pin, s_info.elevation_pin,
329                         s_info.engine_1_forward_pin, s_info.engine_1_back_pin, s_info.engine_1_channel,
330                         s_info.engine_2_forward_pin, s_info.engine_2_back_pin, s_info.engine_2_channel);
331 }
332
333 static bool service_app_create(void *data)
334 {
335         int ret = 0;
336         app_data *ad = data;
337
338         _D("-----------------------=======================================================================-----------------------");
339         _D("-----------------------=======================================================================-----------------------");
340         _D("-----------------------============================== APP %s %s ==============================-----------------------", __DATE__, __TIME__);
341         _D("-----------------------=======================================================================-----------------------");
342         _D("-----------------------=======================================================================-----------------------");
343
344         /*
345          * if you want to use default configuration,
346          * Do not need to call resource_set_motor_driver_L298N_configuration(),
347          *
348         */
349 #if ENABLE_MOTOR
350         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);
351         if (ret) {
352                 _E("resource_set_motor_driver_L298N_configuration()");
353                 service_app_exit();
354         }
355         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);
356         if (ret) {
357                 _E("resource_set_motor_driver_L298N_configuration()");
358                 service_app_exit();
359         }
360 #endif
361
362         _initialize_components(ad);
363         resource_lap_counter_init();
364         cloud_communication_start(CLOUD_REQUESTS_FREQUENCY);
365
366         controller_connection_manager_set_command_received_cb(__command_received_cb);
367         controller_connection_manager_set_user_name_received_cb(__user_name_received_cb);
368
369         return true;
370 }
371
372 static void service_app_control(app_control_h app_control, void *data)
373 {
374
375 #if ENABLE_MOTOR
376         /* set speed 0, to reduce delay of initializing motor driver */
377         resource_set_motor_driver_L298N_speed(MOTOR_ID_1, 0);
378         resource_set_motor_driver_L298N_speed(MOTOR_ID_2, 0);
379         resource_set_servo_motor_value(s_info.stering_pin, STERING_SERVO_CENTER);
380         resource_set_servo_motor_value(s_info.elevation_pin, ELEVATION_MIN);
381         resource_set_servo_motor_value(s_info.azimuth_pin, (AZIMUTH_MIN + AZIMUTH_MAX) / 2);
382 #endif
383
384         return;
385 }
386
387 static void service_app_terminate(void *data)
388 {
389         app_data *ad = data;
390
391         resource_set_servo_motor_value(s_info.stering_pin, STERING_SERVO_CENTER);
392         resource_set_servo_motor_value(s_info.elevation_pin, ELEVATION_MIN);
393         resource_set_servo_motor_value(s_info.azimuth_pin, (AZIMUTH_MIN + AZIMUTH_MAX) / 2);
394
395         resource_lap_counter_destroy();
396
397         if (ad->idle_h)
398                 g_source_remove(ad->idle_h);
399
400         lap_counter_shutdown();
401         controller_connection_manager_release();
402         message_manager_shutdown();
403
404         cloud_communication_stop();
405         cloud_communication_fini();
406         config_shutdown();
407         net_util_fini();
408
409         resource_close_all();
410         log_file_close();
411
412         _D("Bye ~");
413
414         return;
415 }
416
417 int main(int argc, char* argv[])
418 {
419         app_data *ad = NULL;
420         int ret = 0;
421         service_app_lifecycle_callback_s event_callback;
422         app_event_handler_h handlers[5] = {NULL, };
423
424         log_type_set(LOG_TYPE_DLOG);
425
426         ad = calloc(1, sizeof(app_data));
427         retv_if(!ad, -1);
428
429         event_callback.create = service_app_create;
430         event_callback.terminate = service_app_terminate;
431         event_callback.app_control = service_app_control;
432
433         service_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY],
434                 APP_EVENT_LOW_BATTERY, service_app_low_battery, &ad);
435         service_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY],
436                 APP_EVENT_LOW_MEMORY, service_app_low_memory, &ad);
437         service_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED],
438                 APP_EVENT_LANGUAGE_CHANGED, service_app_lang_changed, &ad);
439         service_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED],
440                 APP_EVENT_REGION_FORMAT_CHANGED, service_app_region_changed, &ad);
441
442         ret = service_app_main(argc, argv, &event_callback, ad);
443         if (ret)
444                 _E("failed to start app");
445
446         return 0;
447 }