From a59b9a55382a9565ed21932b03b97e2829a62193 Mon Sep 17 00:00:00 2001 From: fanasina Date: Fri, 7 Nov 2025 12:55:43 +0100 Subject: [PATCH] y_nnn : change learn_to_drive and add some bash print --- .../src/deepQlearning/learn_to_drive.c | 18 +++- .../src/deepQlearning/learn_to_drive.h | 8 ++ deepQlearn_0/src/deepQlearning/vehicle.c | 3 +- deepQlearn_0/src/deepQlearning/vehicle.h | 4 + .../include/y_net_neur_net/y_nnn_manager.h | 16 +++ .../y_net_neur_net/y_nnn_screen_manager.h | 17 ++++ .../src/y_net_neur_net/y_nnn_manager.c | 94 +++++++++++++++++- .../src/y_net_neur_net/y_nnn_screen_manager.c | 89 +++++++++++++++++ y_network_neural_network_/test/is_good.c | 2 + y_socket_t/include/y_socket_t/y_socket_t.h | 4 +- y_socket_t/src/y_socket_t/y_socket_t.c | 8 +- ytest_t/libytest.so | Bin 955928 -> 940440 bytes 12 files changed, 247 insertions(+), 16 deletions(-) diff --git a/deepQlearn_0/src/deepQlearning/learn_to_drive.c b/deepQlearn_0/src/deepQlearning/learn_to_drive.c index 9655c36..a135b1e 100644 --- a/deepQlearn_0/src/deepQlearning/learn_to_drive.c +++ b/deepQlearn_0/src/deepQlearning/learn_to_drive.c @@ -130,6 +130,7 @@ struct print_params * create_print_params(float scale_x, float scale_y, struct pprint->delay = delay; pprint->string_space = malloc(LOG_LENTH+1); pthread_mutex_init(&(pprint->mut_printed), NULL); + pprint->go_on = 1; int i; for( i=0; imut_printed)); + ret=pprint->go_on; + pthread_mutex_unlock(&(pprint->mut_printed)); + + return ret; +} + void free_print_params (struct print_params *pprint){ free(pprint->string_space); pthread_mutex_destroy(&(pprint->mut_printed)); @@ -388,15 +398,15 @@ void learn_to_drive(struct RL_agent * rlAgent){ //struct print_params * pprint = rlAgent->pprint; char msg[100]; - pthread_t threadPrint; - pthread_create(&threadPrint, NULL, runPrint, (void*)rlAgent); + ////pthread_t threadPrint; + ////pthread_create(&threadPrint, NULL, runPrint, (void*)rlAgent); // while(true){ for(size_t index_episode = 0; index_episode < qlParams->number_episodes; ++index_episode){ reset(car); qlStatus->nb_training_after_updated_weight_in_target = 0; qlStatus->index_episode = index_episode; - while(true){ + while(!is_ending(qlStatus) /*true*/){ ++(qlStatus->nb_episodes); ++(qlStatus->nb_training_after_updated_weight_in_target); action = select_action(rlAgent); @@ -435,6 +445,6 @@ void learn_to_drive(struct RL_agent * rlAgent){ pthread_mutex_unlock(qlStatus->mut_ending); // } - pthread_join(threadPrint, NULL); + ////pthread_join(threadPrint, NULL); } diff --git a/deepQlearn_0/src/deepQlearning/learn_to_drive.h b/deepQlearn_0/src/deepQlearning/learn_to_drive.h index d92e4eb..27461a8 100644 --- a/deepQlearn_0/src/deepQlearning/learn_to_drive.h +++ b/deepQlearn_0/src/deepQlearning/learn_to_drive.h @@ -25,6 +25,7 @@ //float d_reLU(float x); +extern char *action_name[8]; struct qlearning_params { float gamma; @@ -67,8 +68,11 @@ struct print_params { float scale_y; struct delay_params *delay; char *string_space;//[LOG_LENTH]; + int go_on; }; +int check_go_on_print_params(struct print_params *pprint); + struct networks_qlearning { config_layers *config; neurons_TYPE_FLOAT *main_net; @@ -136,5 +140,9 @@ void train_qlearning(struct RL_agent * rlAgent, // long reward; void learn_to_drive(struct RL_agent * rlAgent); +int is_ending(struct status_qlearning *qlStatus); + +///char *fileNameDateScore(char * pre, char* post,size_t score); +///int select_action(struct RL_agent * rlAgent); #endif /* __LEARNING_VEHICLE__C_H____ */ diff --git a/deepQlearn_0/src/deepQlearning/vehicle.c b/deepQlearn_0/src/deepQlearning/vehicle.c index 1796c39..6f2049c 100644 --- a/deepQlearn_0/src/deepQlearning/vehicle.c +++ b/deepQlearn_0/src/deepQlearning/vehicle.c @@ -370,7 +370,8 @@ void goto_xy(int x, int y) } -static struct winsize w; +//static +struct winsize w; void init_win(){ ioctl(1, TIOCGWINSZ, &w); diff --git a/deepQlearn_0/src/deepQlearning/vehicle.h b/deepQlearn_0/src/deepQlearning/vehicle.h index 2657ca5..a0123de 100644 --- a/deepQlearn_0/src/deepQlearning/vehicle.h +++ b/deepQlearn_0/src/deepQlearning/vehicle.h @@ -130,4 +130,8 @@ float distance2_coordinate(coordinate *c0, coordinate *c1); void print2D_blocks(struct blocks *blk, float scale_x, float scale_y, char pad); void print2D_blocks_withPoint(struct blocks *blk, float scale_x, float scale_y, char pad, coordinate *coordPoint); +extern struct winsize w; +void init_win(); +struct blocks * block_neighbord_Point(coordinate *coord, float *radius ); + #endif /* __VEHICLE__C_H__ */ diff --git a/y_network_neural_network_/include/y_net_neur_net/y_nnn_manager.h b/y_network_neural_network_/include/y_net_neur_net/y_nnn_manager.h index 9469a57..3e0eed5 100644 --- a/y_network_neural_network_/include/y_net_neur_net/y_nnn_manager.h +++ b/y_network_neural_network_/include/y_net_neur_net/y_nnn_manager.h @@ -4,10 +4,26 @@ #include +#include "learn_to_drive.h" + #include "y_net_neur_net/y_nnn_screen_manager.h" #include "y_socket_t/y_socket_t.h" void y_nnn_manager_handle_input(char * buf, int len_buf, void *arg); +struct arg_run_qlearn_bprint{ + struct arg_bash *bash_arg; + struct RL_agent *rlAgent; +}; + +struct arg_run_qlearn_bprint * create_arg_run_qlearn_bprint( + struct arg_bash *bash_arg, + struct RL_agent *rlAgent +); + +void free_arg_run_qlearn_bprint(struct arg_run_qlearn_bprint *arg); + +void* runBashPrint(void *arg); + #endif /* Y_NETWORK_NEURAL_NETWORK__MANAGER__H_C */ diff --git a/y_network_neural_network_/include/y_net_neur_net/y_nnn_screen_manager.h b/y_network_neural_network_/include/y_net_neur_net/y_nnn_screen_manager.h index 386930b..dfb5bcc 100644 --- a/y_network_neural_network_/include/y_net_neur_net/y_nnn_screen_manager.h +++ b/y_network_neural_network_/include/y_net_neur_net/y_nnn_screen_manager.h @@ -16,6 +16,8 @@ #include "list_t/list_t.h" +#include "vehicle.h" + GENERATE_LIST_ALL(pid_t) #define SIZE_LOCAL_BUF 300 @@ -23,6 +25,16 @@ GENERATE_LIST_ALL(pid_t) #define GOTO_TOP_LEFT "\x1B[0;0f" #define LEN_GOTO_TOP_LEFT 6 +#define BASH_WRITE_IF_EXIST(bash,buf,len_buf) \ + do{\ + if(bash_arg->fd_new_bash_pid>0){\ + write(bash_arg->fd_new_bash_pid, buf, len_buf);\ + }\ + if(bash_arg->fd_current_bash_pid>0){\ + write(bash_arg->fd_current_bash_pid, buf, len_buf);\ + }\ + } while(0); + //#include "y_socket_t/y_list_var_tool.h" pid_t pidof(char *target, struct main_list_pid_t *m_pid_t); @@ -56,6 +68,7 @@ void free_arg_bash(struct arg_bash *arg); int write_duplicate_bash(int fd, char *content, size_t size_content); +int new_bash_exist(struct arg_bash *bash_arg); void* run_newbash(void *arg); void* wait_newbash(void *arg); @@ -69,4 +82,8 @@ void* launch_new_bash(void *arg); void* launch_wait_bash(void *arg); void* launch_sleep_wait_bash(void *arg); +void bash_print_vehicle_n_path(struct vehicle *v, float scale_x, float scale_y, struct arg_bash *bash_arg); +void bash_print2D_blocks_indexOne_withPoint(struct blocks *blk, float scale_x, float scale_y, coordinate *coordPoint, struct arg_bash *bash_arg); + + #endif /* Y_NETWORK_NEURAL_NETWORK__SCREEN_MANAGER__H_C */ diff --git a/y_network_neural_network_/src/y_net_neur_net/y_nnn_manager.c b/y_network_neural_network_/src/y_net_neur_net/y_nnn_manager.c index 01df2ca..6360950 100644 --- a/y_network_neural_network_/src/y_net_neur_net/y_nnn_manager.c +++ b/y_network_neural_network_/src/y_net_neur_net/y_nnn_manager.c @@ -2,18 +2,36 @@ #include "y_net_neur_net/y_nnn_manager.h" +struct arg_run_qlearn_bprint * create_arg_run_qlearn_bprint( + struct arg_bash *bash_arg, + struct RL_agent *rlAgent +){ + struct arg_run_qlearn_bprint *r_arg=malloc(sizeof(struct arg_run_qlearn_bprint)); + r_arg->bash_arg = bash_arg; + r_arg->rlAgent = rlAgent; + + return r_arg; +} + +void free_arg_run_qlearn_bprint(struct arg_run_qlearn_bprint *arg){ + free_RL_agent(arg->rlAgent); + free_arg_bash(arg->bash_arg); + free(arg); +} + void y_nnn_manager_handle_input(char * buf, int len_buf, void *arg){ - //struct arg_bash *bash_arg=(struct arg_bash*)arg; + struct arg_run_qlearn_bprint *run_arg=(struct arg_run_bash_print*)arg; + struct arg_bash *bash_arg=run_arg->bash_arg; if(arg && (len_buf>0)){ - printf("debug: %s #%d (%d)\n",buf,len_buf,((struct arg_bash*)arg)->old_bash_pid); + printf("debug: %s #%d (%d)\n",buf,len_buf,(bash_arg)->old_bash_pid); if(strncmp(buf,"newbash",7)==0){ - run_newbash(arg); + run_newbash(bash_arg); }else if(strncmp(buf,"waitbash",8)==0){ - launch_sleep_wait_bash(arg); + launch_sleep_wait_bash(bash_arg); }else if(strncmp(buf,"killbash",8)==0){ - kill_all_bash(arg); + kill_all_bash(bash_arg); }else{ printf("debug: %s is not handle\n",buf); } @@ -22,3 +40,69 @@ void y_nnn_manager_handle_input(char * buf, int len_buf, void *arg){ } + + +void* runBashPrint(void *arg){ + struct arg_run_bash_print *arg_run=(struct arg_run_bash_print*)arg; + struct RL_agent *rlAgent = arg_run->rlAgent; + struct arg_bash *bash_arg = arg_run->bash_arg; + + struct status_qlearning *qlStatus = rlAgent->status; + struct print_params * pprint = rlAgent->pprint; + struct vehicle *car = rlAgent->car; + size_t count_print = 0; + char buf[SIZE_LOCAL_BUF]; + int len_buf; + while((new_bash_exist(bash_arg)) && check_go_on_print_params(pprint) && !is_ending(qlStatus)){ + if(/*(qlStatus->nb_episodes %125 == 0) &&*/ pprint->printed){ + //pthread_mutex_lock(&(pprint->mut_printed)); + pthread_mutex_lock(&(car->mut_coord)); + bash_print_vehicle_n_path(car, pprint->scale_x, pprint->scale_y,bash_arg); + pthread_mutex_unlock(&(car->mut_coord)); + //pthread_mutex_unlock(&(pprint->mut_printed)); + ////printf("%s ",pprint->string_space); + len_buf=sprintf(buf,"%s ",pprint->string_space); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf) + + ////printf("ep: %ld\n",qlStatus->index_episode); + len_buf=sprintf(buf,"ep: %ld\n",qlStatus->index_episode); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf) + neurons_TYPE_FLOAT * net_main = rlAgent->networks->main_net; + neurons_TYPE_FLOAT * net_target = rlAgent->networks->target_net; + for(size_t i=0; (ioutput->dim->rank) && (new_bash_exist(bash_arg)); ++i) { + ////printf("{sensro[%s]:%f "" vs oldsens[%s]: %f}\n",action_name[i%COUNT_ACTION],net_target->output->x[i], + len_buf = sprintf(buf,"{sensro[%s]:%f "" vs oldsens[%s]: %f}\n",action_name[i%COUNT_ACTION],net_target->output->x[i],action_name[i%COUNT_ACTION],net_main->output->x[i]); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf) + + } + ////printf("\n< %5.2f > ( %s ) \n", car->direction, action_name[qlStatus->action % COUNT_ACTION]); + len_buf=sprintf(buf,"\n< %5.2f > ( %s ) \n", car->direction, action_name[qlStatus->action % COUNT_ACTION]); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf) + //print_weight_in_neurons_TYPE_FLOAT(net_main, "net_main_wei"); + //PRINT_ATTRIBUTE_TENS_IN_ALL_LAYERS(TYPE_FLOAT, net_main, weight_in, "net_main_we_in"); + ///PRINT_ATTRIBUTE_TENS_IN_ALL_LAYERS(TYPE_FLOAT, net_main, output, "net_main_out"); + //PRINT_ATTRIBUTE_TENS_IN_ALL_LAYERS(TYPE_FLOAT, net_target, output, "net_target_out"); + //PRINT_ATTRIBUTE_TENS_IN_ALL_LAYERS(TYPE_FLOAT, net_main, input, "net_main_input"); + ////printf(" action : %d , factor : %f nb_episodes : %ld \n",qlStatus->action,rlAgent->qlearnParams->exploration_factor, rlAgent->status->nb_episodes); + len_buf=sprintf(buf," action : %d , factor : %f nb_episodes : %ld \n",qlStatus->action,rlAgent->qlearnParams->exploration_factor, rlAgent->status->nb_episodes); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf) + + FOR_LIST_FORM_BEGIN(TYPE_L_INT, qlStatus->progress_best_cumul){ + ////printf(" | %ld |,",(qlStatus->progress_best_cumul)->current_list->value); + len_buf=sprintf(buf," | %ld |,",(qlStatus->progress_best_cumul)->current_list->value); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf) + } + ////printf("[%ld] %s ", rlAgent->car->status->cumulative_reward, pprint->string_space); + len_buf=sprintf(buf,"[%ld] %s ", rlAgent->car->status->cumulative_reward, pprint->string_space); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf) + + } + Sleep(pprint->delay->delay_between_games); + ++count_print; + if(count_print > 20){ + count_print = 0; + clear_screen(); + } + } + return NULL; +} diff --git a/y_network_neural_network_/src/y_net_neur_net/y_nnn_screen_manager.c b/y_network_neural_network_/src/y_net_neur_net/y_nnn_screen_manager.c index b5dceb8..38d07c1 100644 --- a/y_network_neural_network_/src/y_net_neur_net/y_nnn_screen_manager.c +++ b/y_network_neural_network_/src/y_net_neur_net/y_nnn_screen_manager.c @@ -133,6 +133,10 @@ void free_arg_bash(struct arg_bash *arg){ free(arg); } +int new_bash_exist(struct arg_bash *bash_arg){ + return ((bash_arg->fd_new_bash_pid>0) || (bash_arg->fd_current_bash_pid)); +} + /* run new bash terminal graphic, can be called directly or in a thread */ void* run_newbash(void* argg){ struct arg_bash *arg=(struct arg_bash*)argg; @@ -339,4 +343,89 @@ void* launch_wait_bash(void *b_arg){ return NULL; } +#define __BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf)\ + if(bash_arg->fd_new_bash_pid>0){\ + write(bash_arg->fd_new_bash_pid, buf , len_buf);\ + }\ + if(bash_arg->fd_current_bash_pid>0){\ + write(bash_arg->fd_current_bash_pid, buf, len_buf);\ + }\ + + +void bash_print_vehicle_n_path(struct vehicle *v, float scale_x, float scale_y, struct arg_bash *bash_arg){ + static bool first = true; + if(first){ + first = false; + init_win(); + char pad[w.ws_col+1]; + int i=0; + for(i=0; ipath, scale_x, scale_y, v->coord, bash_arg); + //printf("lines print : %d\n",lines); + char loggg[SIZE_LOCAL_BUF]; + int len_loggg=sprintf(loggg,"\nlog : %s \n",v->status->log); + BASH_WRITE_IF_EXIST(bash_arg, loggg, len_loggg); +} + + +void bash_print2D_blocks_indexOne_withPoint(struct blocks *blk, float scale_x, float scale_y, coordinate *coordPoint, struct arg_bash *bash_arg){ + if(blk->dimension_size == 2){ + update_bounds_limits_blocks(blk); + coordinate ** bounds_coord = blk->bounds_all_blocks; + + coordinate * coord = create_coordinate(2); + + float *radius = malloc(2 * sizeof(float)); + radius[0]=scale_x; + radius[1]=scale_y; + char buf[SIZE_LOCAL_BUF]; + int len_buf; + struct blocks * blk_point = block_neighbord_Point(coordPoint, radius); + for(coord->x[1] = bounds_coord[1]->x[1]; coord->x[1] > bounds_coord[0]->x[1]; coord->x[1]-=scale_y ){ + for(coord->x[0] = bounds_coord[0]->x[0]; coord->x[0] < bounds_coord[1]->x[0]; coord->x[0]+=scale_x ){ + if(is_in_blocks(blk_point, coord)){ + ////printf("\033[0;31m"); // red + BASH_WRITE_IF_EXIST(bash_arg, "\033[0;31m", 7); + } + int in = is_in_blocks(blk,coord); + if(in){ + if(in>9){ + int div=in%10; + ////printf("%d",div); + len_buf=sprintf(buf,"%d",div); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf); + }else{ + ////printf("%d",in); + len_buf=sprintf(buf,"%d",in); + BASH_WRITE_IF_EXIST(bash_arg, buf, len_buf); + } + }else{ + ////printf("."); //printf(" "); + BASH_WRITE_IF_EXIST(bash_arg, ".", 1); + } + + ////printf("\033[0;37m"); // white + BASH_WRITE_IF_EXIST(bash_arg, "\033[0;37m", 7); // white + } + ///printf("\n"); + BASH_WRITE_IF_EXIST(bash_arg,"\n",1); + } + + + free_coordinate(coord); + + free_blocks(blk_point); + free(radius); + } + +} + diff --git a/y_network_neural_network_/test/is_good.c b/y_network_neural_network_/test/is_good.c index 0dba008..ca2981a 100644 --- a/y_network_neural_network_/test/is_good.c +++ b/y_network_neural_network_/test/is_good.c @@ -215,6 +215,7 @@ void *func_bash(void* b_arg){ return NULL; } +#if 0 TEST(try_y_socket_manager){ struct arg_bash *bash_arg= create_arg_bash(); struct arg_var_ * var = create_arg_var_(y_nnn_manager_handle_input, bash_arg); @@ -239,6 +240,7 @@ TEST(try_y_socket_manager){ free_arg_bash(bash_arg); } +#endif int main(int argc, char **argv){ diff --git a/y_socket_t/include/y_socket_t/y_socket_t.h b/y_socket_t/include/y_socket_t/y_socket_t.h index 2796bd5..fffab2f 100644 --- a/y_socket_t/include/y_socket_t/y_socket_t.h +++ b/y_socket_t/include/y_socket_t/y_socket_t.h @@ -55,11 +55,11 @@ struct arg_var_{ struct main_list_y_ptr_HEADER_T *m_ok_head_l_t; pthread_mutex_t *mut_var; pthread_cond_t *cond_var; - void* bash_arg; + void* extern_arg; void (*extern_socket_handler)(char*,int, void*); }; -struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*), void* bash_arg); +struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*), void* extern_arg); void set_up_arg_var_init_(struct arg_var_ *var, struct y_socket_t * argSock, struct main_list_TYPE_PTR * list_arg, struct argExecTasQ *argx , struct main_list_y_ptr_HEADER_T *m_ok_head_l_t); void free_arg_var_(struct arg_var_ *var); void wait_var_set_up_value_not_equal(struct arg_var_ *var, int value_set_up); diff --git a/y_socket_t/src/y_socket_t/y_socket_t.c b/y_socket_t/src/y_socket_t/y_socket_t.c index 03b4754..10b309f 100644 --- a/y_socket_t/src/y_socket_t/y_socket_t.c +++ b/y_socket_t/src/y_socket_t/y_socket_t.c @@ -12,7 +12,7 @@ void handle_input_cmd(char * buf, int buf_len, struct arg_var_ *var); //struct y_socket_t * argSock, struct main_list_TYPE_PTR * list_arg, struct argExecTasQ *argx , struct main_list_y_ptr_HEADER_T *m_ok_head_l_t); -struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*), void *bash_arg){ +struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void*), void *extern_arg){ struct arg_var_ * new_var=malloc(sizeof(struct arg_var_)); new_var->set_up = 0; new_var->mut_var = malloc(sizeof(pthread_mutex_t)); @@ -26,7 +26,7 @@ struct arg_var_ * create_arg_var_(void (*extern_socket_handler)(char*,int, void* new_var->m_ok_head_l_t = NULL; new_var->extern_socket_handler = extern_socket_handler; - new_var->bash_arg=bash_arg; + new_var->extern_arg=extern_arg; return new_var; } @@ -602,7 +602,7 @@ if(buf_len>6){ }else{ printf("debug: call 1 extern_socket_handler\n"); if(var->extern_socket_handler){ - var->extern_socket_handler(buf,buf_len,var->bash_arg); + var->extern_socket_handler(buf,buf_len,var->extern_arg); }else{ printf("debug: No extern_socket_handler in var\n"); } @@ -616,7 +616,7 @@ if(buf_len>6){ }else{ printf("debug: call 2 extern_socket_handler\n"); if(var->extern_socket_handler){ - var->extern_socket_handler(buf,buf_len,var->bash_arg); + var->extern_socket_handler(buf,buf_len,var->extern_arg); }else{ printf("debug: No extern_socket_handler in var\n"); } diff --git a/ytest_t/libytest.so b/ytest_t/libytest.so index e54a8039c6ef9b8cce4e325635bc65d9a9986962..b0f16d54cd98e009efe8a45ada906254147e26fc 100755 GIT binary patch delta 633 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 D|6Zbk