mardi 31 octobre 2023

How to prevent core dump in C++ using YAML-CPP and ImGui and converting data types correctly?

enter image description here

Here, my code:

#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include <GLFW/glfw3.h>
#include <yaml-cpp/yaml.h>
#include <iostream>
#include <fstream>
#include <vector>
// convert from YAML to datatypes
bool ConvertYAMLToInt(const YAML::Node& node, int& output) {
    if (node.IsScalar() && node.Type() == YAML::NodeType::Scalar) {
        try {
            output = node.as<int>();
            return true;
        } catch (const YAML::BadConversion& e) {
            // Handle conversion error if needed
        }
    }
    return false;
}

bool ConvertYAMLToDouble(const YAML::Node& node, double& output) {
    if (node.IsScalar() && node.Type() == YAML::NodeType::Scalar) {
        try {
            output = node.as<double>();
            return true;
        } catch (const YAML::BadConversion& e) {
            // Handle conversion error if needed
        }
    }
    return false;
}

bool ConvertYAMLToBool(const YAML::Node& node, bool& output) {
    if (node.IsScalar()) {
        std::string value = node.as<std::string>();
        if (value == "true") {
            output = true;
            return true;
        } else if (value == "false") {
            output = false;
            return true;
        }
    }
    return false;
}
//global variables
std::string file_path = "/home/user/robot/imgui/config/behaviors.yaml";
YAML::Node config;
YAML::Node copy_config;
YAML::Node LoadYAML(const std::string& filename)
{
    return YAML::LoadFile(filename);
}
void attributeYAML(YAML::Node& attribute_native){
    for (const auto& attributeNode: attribute_native){
        if (attributeNode.IsScalar()){
            int loadInt; double loadDouble; bool loadBool; 

            if (ConvertYAMLToInt(attributeNode, loadInt)){
                attribute_native = loadInt;
            }
            else if (ConvertYAMLToDouble(attributeNode, loadDouble)){
                attribute_native = loadDouble;
            }
            else if (ConvertYAMLToBool(attributeNode, loadBool)){
                attribute_native = loadBool;      
            }
            else{
                std::string name = attributeNode.as<std::string>();
                ImGui::Text("%s", name.c_str());
            }
        }
        else if (attributeNode.IsMap()){
            for (const auto& attribute_second : attributeNode){
                std::string memberName = attribute_second.first.as<std::string>();
                ImGui::Text("%s:", memberName.c_str());
                ImGui::Indent();
                attributeYAML(const_cast<YAML::Node&>(attribute_second.second)); // Menghilangkan const
                //attributeYAML(attribute_second.second);
                ImGui::Unindent();
            }
        }
   
        else if (attributeNode.IsSequence()){
            ImGui::Indent();
            for (auto attribute_third = attributeNode.begin(); attribute_third != attributeNode.end(); ++attribute_third){
                YAML::Node newNode = *attribute_third;
                attributeYAML(newNode);
            }
            ImGui::Unindent();
        }
    }
}
void renderButton(YAML::Node& config){
    for (const auto& behaviorsNode: config){
        std::string topicNode = behaviorsNode.first.as<std::string>();

        bool isButtonPressed = ImGui::Button(topicNode.c_str()); 
        if (isButtonPressed) {
            ImGui::OpenPopup(topicNode.c_str()); // open popup when button is clicked
        }
        
        ImGui::SetNextWindowSize(ImVec2(500,500));
        if (ImGui::BeginPopup(topicNode.c_str())){ // begin popup
            ImGui::Text("Behaviors: %s", topicNode.c_str());
            ImGui::Separator();

         
            for (const auto& secondTopic : behaviorsNode.second)
            {
                std::string secondName = secondTopic.first.as<std::string>();
                attributeYAML(const_cast<YAML::Node&>(secondTopic.second));
            }

            ImGui::EndPopup(); // end popup
        }
    }
}
int main(int, char**)
{
    if (!glfwInit())
        return 1;

    const char* glsl_version = "#version 130"; // GL 3.0 + GLSL 130

    GLFWwindow* window = glfwCreateWindow(1280, 640, "Welcome to App", nullptr, nullptr);
    if (window == nullptr)
        return 1;
    glfwMakeContextCurrent(window);
    glfwSwapInterval(1); // Enable vsync

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    ImGuiIO& io = ImGui::GetIO();
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;

    ImGui::StyleColorsDark();

    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init(glsl_version);

    ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

    //outside while loop  
    config = LoadYAML(file_path);
    copy_config = config;

    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        //the starting of code
        ImGui::Text("The available functions of the robot.");
        ImGui::Separator();

        renderButton(config);

        //rendering
        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

        glfwSwapBuffers(window);
    }

    //clean up
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    glfwDestroyWindow(window);
    glfwTerminate();

    return 0;
}
standstill:
    type: "standstill"
    control:
        control_horizon:
            - {duration: 1.0, num_of_controls: 4}

        max_acc: {x: 1.0, y: 1.0, theta: 1.0}

    required_inputs:
        velocity: "velocity"

    outputs:
        markers: "behavior_markers"

slow_standstill:
    type: "standstill"
    control:
        control_horizon:
            - {duration: 1.0, num_of_controls: 1}

        max_acc: {x: 1.0, y: 1.0, theta: 1.0}

    required_inputs:
        velocity: "velocity"

    outputs:
        markers: "behavior_markers"

joypad:
    type: "joypad"
    control:
        control_horizon:
            - {duration: 2.0, num_of_controls: 20}

        max_acc: {x:  0.5, y:  0.5, theta:  1.0}
        max_vel: {x:  0.5, y:  0.3, theta:  1.0}
        min_vel: {x: -0.3, y: -0.3, theta: -1.0}

        skip_vel_ramp: false

        footprint:
            - {x:  0.426, y:  0.326}
            - {x: -0.7,   y:  0.326}
            - {x: -0.7,   y: -0.326}
            - {x:  0.426, y: -0.326}
        footprint_padding: 0.3

    required_inputs:
        velocity: "velocity"
        laser: "combined_laser"
        joypad: "joypad"

    outputs:
        markers: "behavior_markers"

ptp:
    type: "ptp"
    control:
        control_horizon:
            - {duration: 1.0, num_of_controls: 5}
            - {duration: 2.0, num_of_controls: 6}
            - {duration: 1.0, num_of_controls: 2}

        max_acc: {x: 0.5, y:  0.5, theta:  1.0}
        max_vel: {x: 0.5, y:  0.3, theta:  0.75}
        min_vel: {x: -0.25, y: -0.3, theta: -0.75}

        is_unicycle: false # if unicycle make goal_state_intercept_angle non zero

        weights:
            goal_state:
                pos: {x: 20.0, y: 20.0, theta: 10.0}
                vel: {x: 10.0, y: 10.0, theta: 10.0}
            goal_state_intercept_angle: 0.0

            acc_limit: {x: 10000.0, y: 10000.0, theta: 10000.0}
            vel_limit: {x: 1000.0, y: 1000.0, theta: 1000.0}

            laser_pts_repulsion: 100.0

        footprint: {min_x: -0.7, max_x: 0.43, min_y: -0.33, max_y: 0.33}
        min_inflation_dist: 0.21
        max_inflation_dist: 1.0

        initial_guess:
            num_of_vel_x_samples: 4
            num_of_vel_y_samples: 5
            num_of_vel_theta_samples: 11
            quadratic_theta_samples: true
            apply_elliptical_filter: false
            num_of_controls: 1
            sample_time: 4.0
            states_per_control: 4
            frequency: 2

        shorten_control_horizon: true

    required_inputs:
        laser: "combined_laser"
        velocity: "velocity"
        localization: "mcl_optimal_raycast"

    outputs:
        markers: "behavior_markers"

standstill_to_lane_following_transition:
    type: "ptp"
    control:
        control_horizon:
            - {duration: 1.0, num_of_controls: 5}
            - {duration: 2.0, num_of_controls: 6}
            - {duration: 1.0, num_of_controls: 2}

        max_acc: {x: 0.5, y:  0.5, theta:  1.0}
        max_vel: {x: 0.5, y:  0.3, theta:  0.75}
        min_vel: {x: 0.0, y: -0.3, theta: -0.75}

        is_unicycle: false # if unicycle make goal_state_intercept_angle non zero

        weights:
            goal_state:
                pos: {x: 10.0, y: 10.0, theta: 20.0}
                vel: {x: 10.0, y: 10.0, theta: 10.0}
            goal_state_intercept_angle: 0.0

            acc_limit: {x: 10000.0, y: 10000.0, theta: 10000.0}
            vel_limit: {x: 1000.0, y: 1000.0, theta: 1000.0}

            laser_pts_repulsion: 100.0

        footprint: {min_x: -0.7, max_x: 0.43, min_y: -0.33, max_y: 0.33}
        min_inflation_dist: 0.25
        max_inflation_dist: 0.95

        initial_guess:
            num_of_vel_x_samples: 3
            num_of_vel_y_samples: 5
            num_of_vel_theta_samples: 11
            quadratic_theta_samples: false
            apply_elliptical_filter: true
            num_of_controls: 1
            sample_time: 4.0
            states_per_control: 4
            frequency: 4

        shorten_control_horizon: false

        reverse_motion_goal_threshold_linear: 0.3
        reverse_motion_goal_threshold_heading: 1.0

    required_inputs:
        laser: "combined_laser"
        velocity: "velocity"
        localization: "mcl_optimal_raycast"

    outputs:
        markers: "behavior_markers"

lane_following_to_standstill_transition:
    type: "ptp"
    control:
        control_horizon:
            - {duration: 1.0, num_of_controls: 5}
            - {duration: 2.0, num_of_controls: 6}
            - {duration: 1.0, num_of_controls: 2}

        max_acc: {x: 0.5, y:  0.5, theta:  1.0}
        max_vel: {x:  0.5, y:  0.3, theta:  0.75}
        min_vel: {x: -0.25, y: -0.3, theta: -0.75}

        is_unicycle: false # if unicycle make goal_state_intercept_angle non zero

        weights:
            goal_state:
                pos: {x: 10.0, y: 10.0, theta: 10.0}
                vel: {x: 20.0, y: 10.0, theta: 10.0}
            normal_state:
                pos: {x: 0.0, y: 0.0, theta: 0.0}
                vel: {x: 0.0, y: 0.0, theta: 0.0}
            goal_state_intercept_angle: 0.0

            acc_limit: {x: 10000.0, y: 10000.0, theta: 10000.0}
            vel_limit: {x: 1000.0, y: 1000.0, theta: 1000.0}

            laser_pts_repulsion: 300.0

        footprint: {min_x: -0.7, max_x: 0.43, min_y: -0.33, max_y: 0.33}
        min_inflation_dist: 0.28
        max_inflation_dist: 0.95

        initial_guess:
            num_of_vel_x_samples: 4
            num_of_vel_y_samples: 5
            num_of_vel_theta_samples: 11
            quadratic_theta_samples: true
            apply_elliptical_filter: true
            num_of_controls: 1
            sample_time: 4.0
            states_per_control: 4
            frequency: 3

        shorten_control_horizon: true

        reverse_motion_goal_threshold_linear: 0.3
        reverse_motion_goal_threshold_heading: 1.0

    required_inputs:
        laser: "combined_laser"
        velocity: "velocity"
        localization: "mcl_optimal_raycast"

    outputs:
        markers: "behavior_markers"

lane_following:
    type: "lane_following"
    control:
        control_horizon:
            - {duration: 0.6, num_of_controls: 3}
            - {duration: 1.4, num_of_controls: 4}
            - {duration: 2.0, num_of_controls: 4}

        max_acc: {x: 0.5, y:  0.5, theta:  1.0}
        max_vel: {x: 1.25, y:  0.2, theta:  0.8}
        min_vel: {x: 0.0, y: -0.2, theta: -0.8}

        normal_target_vel: 1.25
        slow_target_vel: 0.25

        weights:
            goal_state:
                pos: {x: 0.0, y: 0.0, theta: 20.0}
                vel: {x: 10.0, y: 5.0, theta: 5.0}
            ideal_path_perp_dist: 20.0
            lane_wall_repulsion: 100.0

            acc_limit: {x: 10000.0, y: 10000.0, theta: 10000.0}
            vel_limit: {x: 1000.0, y: 1000.0, theta: 1000.0}

            laser_pts_repulsion: 100.0

        footprint: {min_x: -0.7, max_x: 0.7, min_y: -0.33, max_y: 0.33}
        inflation_dist: 0.27

        initial_guess:
            custom:
                kp_vel: {x: 1.0, y: 0.5, theta: 1.0}
                num_of_samples: 8
                sample_time: 0.5

    perception:
        laser_filter_box: {min_x: -1.0, max_x: 100.0, min_y: -5.0, max_y: 5.0}
        corner_pt_spline_offset_dist: 2.0
        corner_pt_spline_resolution_dist: 0.1
        lane_wall_dist: 0.2
        lane_index_lookahead: 20

    transition_condition:
        pre:
            goal_tolerance_linear: 1.0
            goal_tolerance_angular: 0.5
            max_vel: {x: 1.0, y: 0.2, theta: 0.1}
            forward_tf_x_min: 0.5
            forward_tf_x_max: 1.0
        post:
            goal_tolerance_linear: 1.5
            goal_tolerance_heading: 0.8

    required_inputs:
        laser: "combined_laser"
        velocity: "velocity"
        localization: "mcl_optimal_raycast"
        kelojson_map: "kelojson_map"

    outputs:
        markers: "behavior_markers"
        traffic_request: "traffic_request"
        alarm: "alarm"

enter_transfer_station:
    type: "transfer_station"
    control:
        control_horizon:
            - {duration: 0.2, num_of_controls: 2}
            - {duration: 0.8, num_of_controls: 4}

        max_acc: {x: 0.5, y:  0.5, theta:  1.0}
        max_vel: {x: 0.3, y:  0.1, theta:  0.2}
        min_vel: {x: 0.0, y: -0.1, theta: -0.2}

        mockup: false

        p_controller_states:
            - success_box: {min_x: -1.2, max_x: -0.8, min_y: -0.02, max_y:  0.02}
              success_theta_tolerance: 0.02
              valid_box: {min_x: -2.0, max_x: -0.7, min_y: -0.4, max_y:  0.4}
              valid_theta_tolerance: 0.5
              kp_vel: {x: 0.4, y: 1.0, theta: 1.0}
              max_acc: {x: 0.5, y:  0.5, theta:  1.0}
              max_vel: {x: 0.15, y:  0.1, theta:  0.5}
              min_vel: {x: 0.0, y: -0.1, theta: -0.5}
            - success_box: {min_x: -0.02, max_x: 0.05, min_y: -0.03, max_y:  0.03}
              success_theta_tolerance: 0.02
              valid_box: {min_x: -1.25, max_x: 0.06, min_y: -0.05, max_y:  0.05}
              valid_theta_tolerance: 0.1
              kp_vel: {x: 0.75, y: 0.5, theta: 0.5}
              max_acc: {x: 0.2, y:  0.2, theta:  0.5}
              max_vel: {x: 0.15, y:  0.1, theta:  0.2}
              min_vel: {x: 0.02, y: -0.1, theta: -0.2}

        footprint:
            - {x:  0.426, y:  0.326}
            - {x: -0.7,   y:  0.326}
            - {x: -0.7,   y: -0.326}
            - {x:  0.426, y: -0.326}
        footprint_padding: -0.015

    perception:
        laser_filter_box: {min_x: -1.0, max_x: 5.0, min_y: -2.0, max_y: 2.0}
        station_polygon_inflation_dist: 0.5
        # clustering params
        cluster_distance_threshold: 0.05
        min_cluster_size: 5
        regression_error_threshold: 0.1
        # line filtering params
        min_line_angle: 1.1
        max_line_angle: 2.1
        min_line_length: 0.6
        max_line_length: 1.1
        # post processing
        prev_pose_linear_tolerance: 0.2
        prev_pose_angular_tolerance: 0.2
        pose_buffer_max_size: 5
        perception_pose_to_goal_tf: {x: -0.46, y: -0.005, theta: -0.0}

    transition_condition:
        pre:
            bounding_box: {min_x: -1.5, max_x: -0.8, min_y: -0.3, max_y: 0.3}
            angular_tolerance: 0.1
            goal_tf: {x: 1.23, y: 0.0, theta: 0.0}

    perception_retry_counter_threshold: 30
    control_retry_counter_threshold: 30

    required_inputs:
        velocity: "velocity"
        localization: "mcl_optimal_raycast"
        front_laser: "front_laser"
        back_laser: "back_laser"

    outputs:
        markers: "behavior_markers"
        robot_pose: "robot_pose_in_goal_frame"

exit_transfer_station:
    type: "transfer_station"
    control:
        control_horizon:
            - {duration: 0.2, num_of_controls: 2}
            - {duration: 0.8, num_of_controls: 4}

        max_acc: {x:  0.5, y:  0.5, theta:  1.0}
        max_vel: {x:  0.05, y:  0.1, theta:  0.2}
        min_vel: {x: -0.3, y: -0.1, theta: -0.2}

        mockup: false

        p_controller_states:
            - success_box: {min_x: 0.3, max_x: 0.7, min_y: -0.02, max_y:  0.02}
              success_theta_tolerance: 0.02
              valid_box: {min_x: 0.2, max_x: 2.0, min_y: -0.05, max_y:  0.05}
              valid_theta_tolerance: 0.15
              kp_vel: {x: 0.2, y: 0.2, theta: 1.0}
              max_acc: {x:  0.05, y:  0.2, theta:  0.5}
              max_vel: {x:  0.0, y:  0.1, theta:  0.2}
              min_vel: {x: -0.2, y: -0.1, theta: -0.2}
            - success_box: {min_x: -0.1, max_x: 0.1, min_y: -0.1, max_y:  0.1}
              success_theta_tolerance: 0.1
              valid_box: {min_x: -0.15, max_x: 1.0, min_y: -0.2, max_y:  0.2}
              valid_theta_tolerance: 0.2
              kp_vel: {x: 0.75, y: 1.0, theta: 1.0}
              max_acc: {x:  0.5, y:  0.1, theta:  1.0}
              max_vel: {x:  0.0, y:  0.02, theta:  0.5}
              min_vel: {x: -0.2, y: -0.02, theta: -0.5}

        footprint:
            - {x:  0.356, y:  0.326}
            - {x: -1.0,   y:  0.326}
            - {x: -1.0,   y: -0.326}
            - {x:  0.356, y: -0.326}
        footprint_padding: -0.03

    perception:
        laser_filter_box: {min_x: -5.0, max_x: 5.0, min_y: -2.0, max_y: 2.0}
        station_polygon_inflation_dist: 0.5
        # clustering params
        cluster_distance_threshold: 0.1
        min_cluster_size: 5
        regression_error_threshold: 0.1
        # line filtering params
        min_line_angle: 1.1
        max_line_angle: 2.1
        min_line_length: 0.5
        max_line_length: 1.1
        # post processing
        prev_pose_linear_tolerance: 0.2
        prev_pose_angular_tolerance: 0.2
        pose_buffer_max_size: 5
        perception_pose_to_goal_tf: {x: -1.8, y: 0.0, theta: -0.0}

    transition_condition:
        pre:
            bounding_box: {min_x: -0.5, max_x: 0.8, min_y: -0.3, max_y: 0.3}
            angular_tolerance: 0.3
            goal_tf: {x: 0.52, y: 0.0, theta: 0.0}

    perception_retry_counter_threshold: 30
    control_retry_counter_threshold: 30

    required_inputs:
        velocity: "velocity"
        localization: "mcl_optimal_raycast"
        front_laser: "front_laser"
        back_laser: "back_laser"

    outputs:
        markers: "behavior_markers"
        robot_pose: "robot_pose_in_goal_frame"

gripper_close:
    type: "gripper"
    open: false
    control:
        control_horizon:
            - {duration: 1.0, num_of_controls: 2}

        max_acc: {x: 0.1, y: 0.1, theta: 0.1}

        mockup: false

    required_inputs:
        velocity: "velocity"
        gripper: "gripper"

    outputs:
        markers: "behavior_markers"
        gripper: "gripper"

gripper_open:
    type: "gripper"
    open: true
    control:
        control_horizon:
            - {duration: 1.0, num_of_controls: 2}

        max_acc: {x: 0.1, y: 0.1, theta: 0.1}

        mockup: false

    required_inputs:
        velocity: "velocity"
        gripper: "gripper"

    outputs:
        markers: "behavior_markers"
        gripper: "gripper"

robile_charging:
    type: "robile_charging"
    mockup: false
    ignore_input: true

    wait_duration_before_start_charge: 1.0
    wait_duration_after_stop_charge: 1.0

    control:
        control_horizon:
            - {duration: 1.0, num_of_controls: 2}

        max_acc: {x: 0.1, y: 0.1, theta: 0.1}

    required_inputs:
        velocity: "velocity"
        # robile_master_battery: "robile_master_battery"

    outputs:
        markers: "behavior_markers"
        robile_master_battery: "robile_master_battery"

In the ImGui picture provided, there is a button labeled 'behaviors corresponding to behavior.yaml' in the image. Clicking this button should ideally open a new window, but when compiled, it results in a core dump. Where is the wrong in my code?

Also, the code shown seems to have difficulties when converting YAML input data to various data types, such as int, double, and bool. It should be that the conversions must strictly match the data types, meaning int should be converted to int, double to double, and bool to bool. However, in my case, it will convert int to double or double to int. How to resolve this issue, ensure that the data type conversions are consistent and correctly handled?

Aucun commentaire:

Enregistrer un commentaire