NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes

news2024/11/23 8:32:32

文章目录

    • NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes
    • 概述
    • 实验结论
    • 补充
    • END

NXP MCUXPresso - cc1plus.exe: out of memory allocating 65536 bytes

概述

在尝试迁移 openpnp - Smoothieware project 从gcc命令行 + MRI调试方式 到NXP MCUXpresso工程.
遇到了编译器错误 cc1plus.exe: out of memory allocating
在这里插入图片描述
错误后面的字节数, 根据代码实现的不同, 也可能是其他数字.

查到资料上说的原始资料 cc1plus.exe: out of memory allocating 65536 bytes

尝试对MCUXPresso的cc1plus.exe做修改.
我的环境为win10x64工作站版

bcdedit /set IncreaseUserVa 3072

先查一下, editbin在哪里?
我计算机上装了vs2022
在这里插入图片描述
进入命令行, 到达editbin的目录

C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.32215\bin\Hostx86\arm>

看看MCUXPresso用的cc1plus在哪里? 还好, 就一个.
在这里插入图片描述
执行官方资料的第2步修改.

C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.35.32215\bin\Hostx86\arm>
editbin /LARGEADDRESSAWARE "D:\nxp\MCUXpressoIDE_11.7.1_9221\ide\plugins\com.nxp.mcuxpresso.tools.win32_11.7.1.202301190959\tools\lib\gcc\arm-none-eabi\10.3.1\cc1plus.exe"

Microsoft (R) COFF/PE Editor Version 14.35.32215.0
Copyright (C) Microsoft Corporation.  All rights reserved.

查看修改后的cc1plus

D:\nxp\MCUXpressoIDE_11.7.1_9221\ide\plugins\com.nxp.mcuxpresso.tools.win32_11.7.1.202301190959\tools\lib\gcc\arm-none-eabi\10.3.1>dumpbin -headers cc1plus.exe | more
Microsoft (R) COFF/PE Dumper Version 14.29.30148.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file cc1plus.exe

PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
             14C machine (x86)
               7 number of sections
               0 time date stamp
               0 file pointer to symbol table
               0 number of symbols
              E0 size of optional header
             32F characteristics
                   Relocations stripped
                   Executable
                   Line numbers stripped
                   Symbols stripped
                   Application can handle large (>2GB) addresses // 这里已经修改过来了.
                   32 bit word machine
                   Debug information stripped

OPTIONAL HEADER VALUES
             10B magic # (PE32)
            2.30 linker version
-- More  --

再尝试编译迁移中的工程, cc1plus 内存不够的报错还有.
尝试关掉MCUXpresso, 再打开工程编译. 还是报错.

最后根据提示信息, 定位到 路径 /my_Smoothieware_best-for-pnp/src/src/modules/robot/Robot.cpp 编译不过.

cc1plus.exe: out of memory allocating 65536 bytes
Building file: ../src/mbed/src/cpp/Timeout.cpp
Finished building: ../src/mbed/src/cpp/Serial.cpp
Finished building: ../src/mbed/src/cpp/Stream.cpp
Invoking: MCU C++ Compiler
Invoking: MCU C++ Compiler
 
make[1]: *** [src/src/modules/robot/subdir.mk:30: src/src/modules/robot/Robot.o] Error 1
arm-none-eabi-c++ -DDEBUG -DMRI_INIT_PARAMETERS=\"MRI_UART_3\" -DWRITE_BUFFER_DISABLE=1 -DMRI_BREAK_ON_INIT=0 -DMRI_SEMIHOST_STDIO=0 -DSTACK_SIZE=1024 -DMRI_ENABLE=1 -DDEFAULT_SERIAL_BAUD_RATE=115200 -D__CODE_RED -D__NEWLIB__ -DCORE_M3 -DCPP_NO_HEAP -D__LPC17XX__ -I"D:\my_dev\my_local_git_prj\hardware\LS_openpnp_hardware\src\my_Smoothieware_best-for-pnp\my_Smoothieware_best-for-pnp\inc" -I"D:\my_dev\my_local_git_prj\hardware\LS_openpnp_hardware\src\my_Smoothieware_best-for-pnp\my_Smoothieware_best-for-pnp\src\src\libs" -I"D:\my_dev\my_local_git_prj\hardware\LS_openpnp_hardware\src\my_Smoothieware_best-for-pnp\my_Smoothieware_best-for-pnp\src\src" -I"D:\my_dev\my_local_git_prj\hardware\LS_openpnp_hardware\src\my_Smoothieware_best-for-pnp\my_Smoothieware_best-for-pnp\src\mbed\src" -O0 -fno-common -g3 -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fmerge-constants -fmacro-prefix-map="../src/mbed/src/cpp/"= -mcpu=cortex-m3 -mthumb -D__NEWLIB__ -fstack-usage -MMD -MP -MF"src/mbed/src/cpp/Ticker.d" -MT"src/mbed/src/cpp/Ticker.o" -MT"src/mbed/src/cpp/Ticker.d" -o "src/mbed/src/cpp/Ticker.o" "../src/mbed/src/cpp/Ticker.cpp"
make[1]: *** Waiting for unfinished jobs....

去查看src/src/modules/robot/subdir.mk

################################################################################
# Automatically-generated file. Do not edit!
################################################################################

# Add inputs and outputs from these tool invocations to the build variables 
CPP_SRCS += \
../src/src/modules/robot/Block.cpp \
../src/src/modules/robot/BlockQueue.cpp \
../src/src/modules/robot/Conveyor.cpp \
../src/src/modules/robot/Planner.cpp \
../src/src/modules/robot/Robot.cpp 

CPP_DEPS += \
./src/src/modules/robot/Block.d \
./src/src/modules/robot/BlockQueue.d \
./src/src/modules/robot/Conveyor.d \
./src/src/modules/robot/Planner.d \
./src/src/modules/robot/Robot.d 

OBJS += \
./src/src/modules/robot/Block.o \
./src/src/modules/robot/BlockQueue.o \
./src/src/modules/robot/Conveyor.o \
./src/src/modules/robot/Planner.o \
./src/src/modules/robot/Robot.o 


# Each subdirectory must supply rules for building sources it contributes
src/src/modules/robot/%.o: ../src/src/modules/robot/%.cpp src/src/modules/robot/subdir.mk
	@echo 'Building file: $<'
	@echo 'Invoking: MCU C++ Compiler'
	arm-none-eabi-c++ -DDEBUG -DMRI_INIT_PARAMETERS=\"MRI_UART_3\" -DWRITE_BUFFER_DISABLE=1 -DMRI_BREAK_ON_INIT=0 -DMRI_SEMIHOST_STDIO=0 -DSTACK_SIZE=1024 -DMRI_ENABLE=1 -DDEFAULT_SERIAL_BAUD_RATE=115200 -D__CODE_RED -D__NEWLIB__ -DCORE_M3 -DCPP_NO_HEAP -D__LPC17XX__ -I"D:\my_dev\my_local_git_prj\hardware\LS_openpnp_hardware\src\my_Smoothieware_best-for-pnp\my_Smoothieware_best-for-pnp\inc" -I"D:\my_dev\my_local_git_prj\hardware\LS_openpnp_hardware\src\my_Smoothieware_best-for-pnp\my_Smoothieware_best-for-pnp\src\src\libs" -I"D:\my_dev\my_local_git_prj\hardware\LS_openpnp_hardware\src\my_Smoothieware_best-for-pnp\my_Smoothieware_best-for-pnp\src\src" -I"D:\my_dev\my_local_git_prj\hardware\LS_openpnp_hardware\src\my_Smoothieware_best-for-pnp\my_Smoothieware_best-for-pnp\src\mbed\src" -O0 -fno-common -g3 -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fmerge-constants -fmacro-prefix-map="$(<D)/"= -mcpu=cortex-m3 -mthumb -D__NEWLIB__ -fstack-usage -MMD -MP -MF"$(@:%.o=%.d)" -MT"$(@:%.o=%.o)" -MT"$(@:%.o=%.d)" -o "$@" "$<"
	@echo 'Finished building: $<'
	@echo ' '


clean: clean-src-2f-src-2f-modules-2f-robot

clean-src-2f-src-2f-modules-2f-robot:
	-$(RM) ./src/src/modules/robot/Block.d ./src/src/modules/robot/Block.o ./src/src/modules/robot/BlockQueue.d ./src/src/modules/robot/BlockQueue.o ./src/src/modules/robot/Conveyor.d ./src/src/modules/robot/Conveyor.o ./src/src/modules/robot/Planner.d ./src/src/modules/robot/Planner.o ./src/src/modules/robot/Robot.d ./src/src/modules/robot/Robot.o

.PHONY: clean-src-2f-src-2f-modules-2f-robot


查看生成的.o, 发现robot.o没有生成出来.
在这里插入图片描述
尝试单独编译robot.cpp, 还是编译不过, 报错信息同样是cc1plus.exe …
在这里插入图片描述

12:02:10 **** Building Selected Files of configuration Debug for project my_Smoothieware_best-for-pnp ****
Info: Internal Builder is used for build
arm-none-eabi-c++ -DDEBUG "-DMRI_INIT_PARAMETERS=\\MRI_UART_3\\" -DWRITE_BUFFER_DISABLE=1 -DMRI_BREAK_ON_INIT=0 -DMRI_SEMIHOST_STDIO=0 -DSTACK_SIZE=1024 -DMRI_ENABLE=1 -DDEFAULT_SERIAL_BAUD_RATE=115200 -D__CODE_RED -D__NEWLIB__ -DCORE_M3 -DCPP_NO_HEAP -D__LPC17XX__ "-ID:\\my_dev\\my_local_git_prj\\hardware\\LS_openpnp_hardware\\src\\my_Smoothieware_best-for-pnp\\my_Smoothieware_best-for-pnp\\inc" "-ID:\\my_dev\\my_local_git_prj\\hardware\\LS_openpnp_hardware\\src\\my_Smoothieware_best-for-pnp\\my_Smoothieware_best-for-pnp\\src\\src\\libs" "-ID:\\my_dev\\my_local_git_prj\\hardware\\LS_openpnp_hardware\\src\\my_Smoothieware_best-for-pnp\\my_Smoothieware_best-for-pnp\\src\\src" "-ID:\\my_dev\\my_local_git_prj\\hardware\\LS_openpnp_hardware\\src\\my_Smoothieware_best-for-pnp\\my_Smoothieware_best-for-pnp\\src\\mbed\\src" -O0 -fno-common -g3 -Wall -c -fmessage-length=0 -fno-builtin -ffunction-sections -fdata-sections -fno-rtti -fno-exceptions -fmerge-constants -fmacro-prefix-map=$(<D)/= -mcpu=cortex-m3 -mthumb -D__NEWLIB__ -fstack-usage -o "src\\src\\modules\\robot\\Robot.o" "..\\src\\src\\modules\\robot\\Robot.cpp" 

cc1plus.exe: out of memory allocating 65536 bytes

12:02:44 Build Finished. 0 errors, 0 warnings. (took 33s.373ms)

不知道cc1plus.exe内部哪里内存开小了. 找一下解决方法.
打开cc1plus.exe看了一下, 报错信息的提示引用处, 都是给了一个size, 如果分配失败, 就打印报错信息.
分配内存的函数调用点很多, 而且给的size各种各样的大小. 可以确定, 不是cc1plus.exe实现的问题.

是不是robot.cpp写的不合适?

从定位到的robot.cpp的实现上, 用排除法看看, 到底是哪里引起cc1plus报错.
将robot.cpp分为2个文件. robot_A.cpp, robot_B.cpp.
2个实现, 都包含同样的头内容.
然后用二分法, 将实现拆开. 尝试编译2个实现.
发现, 其中一个是能编译过的, 一个是编译不过的.
将实现函数向能编译过的.cpp转移. 直到定位到编译不过的函数实现为止.
最后确定, 是Robot::load_config()函数编译不过, 引起cc1plus.exe报错.
将Robot::load_config()函数从下到上开始注释(用2分法), 最后确定, 是函数尾部几行实现引起编译报错.
在类中, 新添了一个函数void Robot::load_config_next1(), 将报错函数引起报错的语句, 改为调用load_config_next1().
在load_config_next1()中, 将引起报错的多余实现丢进去.
再编译, 编译通过! 搞定:)

void Robot::load_config()
{
    // Arm solutions are used to convert positions in millimeters into position in steps for each stepper motor.
    // While for a cartesian arm solution, this is a simple multiplication, in other, less simple cases, there is some serious math to be done.
    // To make adding those solution easier, they have their own, separate object.
    // Here we read the config to find out which arm solution to use
    if (this->arm_solution) delete this->arm_solution;
    int solution_checksum = get_checksum(THEKERNEL->config->value(arm_solution_checksum)->by_default("cartesian")->as_string());
    // Note checksums are not const expressions when in debug mode, so don't use switch
    if(solution_checksum == hbot_checksum || solution_checksum == corexy_checksum) {
        this->arm_solution = new HBotSolution(THEKERNEL->config);

    } else if(solution_checksum == corexz_checksum) {
        this->arm_solution = new CoreXZSolution(THEKERNEL->config);

    } else if(solution_checksum == rostock_checksum || solution_checksum == kossel_checksum || solution_checksum == delta_checksum || solution_checksum ==  linear_delta_checksum) {
        this->arm_solution = new LinearDeltaSolution(THEKERNEL->config);

    } else if(solution_checksum == rotatable_cartesian_checksum) {
        this->arm_solution = new RotatableCartesianSolution(THEKERNEL->config);

    } else if(solution_checksum == rotary_delta_checksum) {
        this->arm_solution = new RotaryDeltaSolution(THEKERNEL->config);

    } else if(solution_checksum == morgan_checksum) {
        this->arm_solution = new MorganSCARASolution(THEKERNEL->config);

    } else if(solution_checksum == cartesian_checksum) {
        this->arm_solution = new CartesianSolution(THEKERNEL->config);

    } else {
        this->arm_solution = new CartesianSolution(THEKERNEL->config);
    }

    // 以上可以编译过

    this->feed_rate           = THEKERNEL->config->value(default_feed_rate_checksum   )->by_default(  100.0F)->as_number();
    this->seek_rate           = THEKERNEL->config->value(default_seek_rate_checksum   )->by_default(  100.0F)->as_number();
    this->mm_per_line_segment = THEKERNEL->config->value(mm_per_line_segment_checksum )->by_default(    0.0F)->as_number();
    this->delta_segments_per_second = THEKERNEL->config->value(delta_segments_per_second_checksum )->by_default(0.0f   )->as_number();
    this->mm_per_arc_segment  = THEKERNEL->config->value(mm_per_arc_segment_checksum  )->by_default(    0.0f)->as_number();
    this->mm_max_arc_error    = THEKERNEL->config->value(mm_max_arc_error_checksum    )->by_default(   0.01f)->as_number();
    this->arc_correction      = THEKERNEL->config->value(arc_correction_checksum      )->by_default(    5   )->as_number();

    // in mm/sec but specified in config as mm/min
    this->max_speeds[X_AXIS]  = THEKERNEL->config->value(x_axis_max_speed_checksum    )->by_default(60000.0F)->as_number() / 60.0F;
    this->max_speeds[Y_AXIS]  = THEKERNEL->config->value(y_axis_max_speed_checksum    )->by_default(60000.0F)->as_number() / 60.0F;
    this->max_speeds[Z_AXIS]  = THEKERNEL->config->value(z_axis_max_speed_checksum    )->by_default(  300.0F)->as_number() / 60.0F;
    this->max_speed           = THEKERNEL->config->value(max_speed_checksum           )->by_default(  -60.0F)->as_number() / 60.0F;

    this->segment_z_moves     = THEKERNEL->config->value(segment_z_moves_checksum     )->by_default(true)->as_bool();
    this->save_g92            = THEKERNEL->config->value(save_g92_checksum            )->by_default(false)->as_bool();
    this->save_g54            = THEKERNEL->config->value(save_g54_checksum            )->by_default(THEKERNEL->is_grbl_mode())->as_bool();
    string g92                = THEKERNEL->config->value(set_g92_checksum             )->by_default("")->as_string();
    if(!g92.empty()) {
        // optional setting for a fixed G92 offset
        std::vector<float> t= parse_number_list(g92.c_str());
        if(t.size() == 3) {
            g92_offset[0] = t[0];
            g92_offset[1] = t[1];
            g92_offset[2] = t[2];
        }
    }

    // 以上可以编译过

    // default s value for laser
    this->s_value             = THEKERNEL->config->value(laser_module_default_power_checksum)->by_default(0.8F)->as_number();


    // 以上编译过了

    // default acceleration setting, can be overriden with newer per axis settings
    this->default_acceleration= THEKERNEL->config->value(acceleration_checksum)->by_default(100.0F )->as_number(); // Acceleration is in mm/s^2

    // make each motor
    for (size_t a = 0; a < MAX_ROBOT_ACTUATORS; a++) {
        Pin pins[3]; //step, dir, enable
        for (size_t i = 0; i < 3; i++) {
            pins[i].from_string(THEKERNEL->config->value(motor_checksums[a][i])->by_default("nc")->as_string())->as_output();
        }

        if(!pins[0].connected() || !pins[1].connected()) { // step and dir must be defined, but enable is optional
            if(a <= Z_AXIS) {
                THEKERNEL->streams->printf("FATAL: motor %c is not defined in config\n", 'X'+a);
                n_motors= a; // we only have this number of motors
                return;
            }
            break; // if any pin is not defined then the axis is not defined (and axis need to be defined in contiguous order)
        }

        StepperMotor *sm = new StepperMotor(pins[0], pins[1], pins[2]);
        // register this motor (NB This must be 0,1,2) of the actuators array
        uint8_t n= register_motor(sm);
        if(n != a) {
            // this is a fatal error
            THEKERNEL->streams->printf("FATAL: motor %d does not match index %d\n", n, a);
            return;
        }

        actuators[a]->change_steps_per_mm(THEKERNEL->config->value(motor_checksums[a][3])->by_default(a == 2 ? 2560.0F : 80.0F)->as_number());
        actuators[a]->set_max_rate(THEKERNEL->config->value(motor_checksums[a][4])->by_default(30000.0F)->as_number()/60.0F); // it is in mm/min and converted to mm/sec
        actuators[a]->set_acceleration(THEKERNEL->config->value(motor_checksums[a][5])->by_default(NAN)->as_number()); // mm/secs²
    }

    check_max_actuator_speeds(); // check the configs are sane

    // if we have not specified a z acceleration see if the legacy config was set
    if(isnan(actuators[Z_AXIS]->get_acceleration())) {
        float acc= THEKERNEL->config->value(z_acceleration_checksum)->by_default(NAN)->as_number(); // disabled by default
        if(!isnan(acc)) {
            actuators[Z_AXIS]->set_acceleration(acc);
        }
    }

    // initialise actuator positions to current cartesian position (X0 Y0 Z0)
    // so the first move can be correct if homing is not performed
    ActuatorCoordinates actuator_pos;
    arm_solution->cartesian_to_actuator(machine_position, actuator_pos);
    for (size_t i = X_AXIS; i <= Z_AXIS; i++) {
        actuators[i]->change_last_milestone(actuator_pos[i]);
    }

    #if MAX_ROBOT_ACTUATORS > 3
    // initialize any extra axis to machine position
    for (size_t i = A_AXIS; i < n_motors; i++) {
         actuators[i]->change_last_milestone(machine_position[i]);
    }
    #endif

    // 以上编译过

    //this->clearToolOffset(); // 这句原来就注释了

    load_config_next1(); // 函数的size有限制(根据编译器而不同), 分成多个小函数搞定:)

}

void Robot::load_config_next1()
{
    soft_endstop_enabled= THEKERNEL->config->value(soft_endstop_checksum, enable_checksum)->by_default(false)->as_bool();
    soft_endstop_halt= THEKERNEL->config->value(soft_endstop_checksum, halt_checksum)->by_default(true)->as_bool();

    soft_endstop_min[X_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, xmin_checksum)->by_default(NAN)->as_number();
    soft_endstop_min[Y_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, ymin_checksum)->by_default(NAN)->as_number();
    soft_endstop_min[Z_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, zmin_checksum)->by_default(NAN)->as_number();
    soft_endstop_max[X_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, xmax_checksum)->by_default(NAN)->as_number();
    soft_endstop_max[Y_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, ymax_checksum)->by_default(NAN)->as_number();
    soft_endstop_max[Z_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, zmax_checksum)->by_default(NAN)->as_number();

}

实验结论

通过这次排错, 可以猜测到, 编译器对一个函数实现编译后的大小是有限制的, 具体是多少, 根据目标平台和编译器的实现而定.
函数太大就会引起报错.

同样的代码, 换用特定的编译器, 就能直接编译过. 但是换用另外一种IDE自带的编译器, 就可能报错.

Smoothieware作者在文档中还特意说了, 只能用他们命令行安装的工具链才能编译过, 如果用其他工具链, 可能有各种各样的编译问题.
Smoothieware作者整的不规范, 能看出来, 他们不想带小白玩.
如果想膜拜Smoothieware的实现, 只能像我这样, 自己迁移Smoothieware工程, 从命令行到其他嵌入式开发的IDE. 这活, 不是随便拉一个项目小白就能搞的, 有点门槛.

如果编译不过, 出现cc1plus的报错, 可以试试排除法, 将引起的报错的函数找到, 然后将报错函数拆成几个较小的函数, 然后在报错点调用这几个小函数, 问题就解决了.

这个问题头一次遇到, 当网上公版的方法不好使的时候, 还可以依靠自己以前积累下来的调试感觉, 不断折腾, 终于搞定:) 机智!

补充

在正式工程中搞了一下, 有一些细节出入. 总体思路是对的.
文件还是一个robot.cpp
添加了一个函数load_config_next1(), 用来放装不下的实现 然后load_config()尾部上调用load_config_next1().
常量数组不能放在函数中间, 这个数组是一个常量数组(相当于一个常量数组), 可以放到函数外面.
数组的大小是根据宏来实现的, 需要设置预定义宏 MAX_ROBOT_ACTUATORS 为确定的值, 否则编译器可能将数组的size搞错, 导致编译不过.

感觉原始工程这块的编码不规范, 引起好多不必要的麻烦.
依然已经使用了类, 这个数组又是常量的, 放在类里作为成员. 在类初始化函数中赋值就好了. 为啥要放在函数中间, 将编译器搞懵逼呢?
C++的高级特性和编译器有关系, 不是不得已就不用. 使用C++简单一些好, 就像使用带类的C那样简单的使用C++就挺好. 即使换了编译器(或者换了C++标准), 也没啥影响.

如果在非必要场景下, 使用了C++高级特性, 纯粹在给自己找麻烦.

// 在工程设置中, 添加预定义宏  MAX_ROBOT_ACTUATORS=5
// 给这个宏一个确定的值, 因为这个宏的值影响这个常量数组的大小. 否则编译器不知道这个数组多大. 会导致编译不过.
     // Make our Primary XYZ StepperMotors, and potentially A B C
    uint16_t const motor_checksums[][6] = {
        ACTUATOR_CHECKSUMS("alpha"), // X
        ACTUATOR_CHECKSUMS("beta"),  // Y
        ACTUATOR_CHECKSUMS("gamma"), // Z
        #if MAX_ROBOT_ACTUATORS > 3
        ACTUATOR_CHECKSUMS("delta"),   // A
        #if MAX_ROBOT_ACTUATORS > 4
        ACTUATOR_CHECKSUMS("epsilon"), // B
        #if MAX_ROBOT_ACTUATORS > 5
        ACTUATOR_CHECKSUMS("zeta")     // C
        #endif
        #endif
        #endif
    };

void Robot::load_config()
{
    // Arm solutions are used to convert positions in millimeters into position in steps for each stepper motor.
    // While for a cartesian arm solution, this is a simple multiplication, in other, less simple cases, there is some serious math to be done.
    // To make adding those solution easier, they have their own, separate object.
    // Here we read the config to find out which arm solution to use
    if (this->arm_solution) delete this->arm_solution;
    int solution_checksum = get_checksum(THEKERNEL->config->value(arm_solution_checksum)->by_default("cartesian")->as_string());
    // Note checksums are not const expressions when in debug mode, so don't use switch
    if(solution_checksum == hbot_checksum || solution_checksum == corexy_checksum) {
        this->arm_solution = new HBotSolution(THEKERNEL->config);

    } else if(solution_checksum == corexz_checksum) {
        this->arm_solution = new CoreXZSolution(THEKERNEL->config);

    } else if(solution_checksum == rostock_checksum || solution_checksum == kossel_checksum || solution_checksum == delta_checksum || solution_checksum ==  linear_delta_checksum) {
        this->arm_solution = new LinearDeltaSolution(THEKERNEL->config);

    } else if(solution_checksum == rotatable_cartesian_checksum) {
        this->arm_solution = new RotatableCartesianSolution(THEKERNEL->config);

    } else if(solution_checksum == rotary_delta_checksum) {
        this->arm_solution = new RotaryDeltaSolution(THEKERNEL->config);

    } else if(solution_checksum == morgan_checksum) {
        this->arm_solution = new MorganSCARASolution(THEKERNEL->config);

    } else if(solution_checksum == cartesian_checksum) {
        this->arm_solution = new CartesianSolution(THEKERNEL->config);

    } else {
        this->arm_solution = new CartesianSolution(THEKERNEL->config);
    }

    this->feed_rate           = THEKERNEL->config->value(default_feed_rate_checksum   )->by_default(  100.0F)->as_number();
    this->seek_rate           = THEKERNEL->config->value(default_seek_rate_checksum   )->by_default(  100.0F)->as_number();
    this->mm_per_line_segment = THEKERNEL->config->value(mm_per_line_segment_checksum )->by_default(    0.0F)->as_number();
    this->delta_segments_per_second = THEKERNEL->config->value(delta_segments_per_second_checksum )->by_default(0.0f   )->as_number();
    this->mm_per_arc_segment  = THEKERNEL->config->value(mm_per_arc_segment_checksum  )->by_default(    0.0f)->as_number();
    this->mm_max_arc_error    = THEKERNEL->config->value(mm_max_arc_error_checksum    )->by_default(   0.01f)->as_number();
    this->arc_correction      = THEKERNEL->config->value(arc_correction_checksum      )->by_default(    5   )->as_number();

    // in mm/sec but specified in config as mm/min
    this->max_speeds[X_AXIS]  = THEKERNEL->config->value(x_axis_max_speed_checksum    )->by_default(60000.0F)->as_number() / 60.0F;
    this->max_speeds[Y_AXIS]  = THEKERNEL->config->value(y_axis_max_speed_checksum    )->by_default(60000.0F)->as_number() / 60.0F;
    this->max_speeds[Z_AXIS]  = THEKERNEL->config->value(z_axis_max_speed_checksum    )->by_default(  300.0F)->as_number() / 60.0F;
    this->max_speed           = THEKERNEL->config->value(max_speed_checksum           )->by_default(  -60.0F)->as_number() / 60.0F;

    this->segment_z_moves     = THEKERNEL->config->value(segment_z_moves_checksum     )->by_default(true)->as_bool();
    this->save_g92            = THEKERNEL->config->value(save_g92_checksum            )->by_default(false)->as_bool();
    this->save_g54            = THEKERNEL->config->value(save_g54_checksum            )->by_default(THEKERNEL->is_grbl_mode())->as_bool();
    string g92                = THEKERNEL->config->value(set_g92_checksum             )->by_default("")->as_string();
    if(!g92.empty()) {
        // optional setting for a fixed G92 offset
        std::vector<float> t= parse_number_list(g92.c_str());
        if(t.size() == 3) {
            g92_offset[0] = t[0];
            g92_offset[1] = t[1];
            g92_offset[2] = t[2];
        }
    }

    // default s value for laser
    this->s_value             = THEKERNEL->config->value(laser_module_default_power_checksum)->by_default(0.8F)->as_number();

    // 下面这个数组放在这里, 编译不过
    // cc1plus.exe: out of memory allocating 65536 bytes
    // 只是一个常量数组, 移到函数外面

//     // Make our Primary XYZ StepperMotors, and potentially A B C
//    uint16_t const motor_checksums[][6] = {
//        ACTUATOR_CHECKSUMS("alpha"), // X
//        ACTUATOR_CHECKSUMS("beta"),  // Y
//        ACTUATOR_CHECKSUMS("gamma"), // Z
//        #if MAX_ROBOT_ACTUATORS > 3
//        ACTUATOR_CHECKSUMS("delta"),   // A
//        #if MAX_ROBOT_ACTUATORS > 4
//        ACTUATOR_CHECKSUMS("epsilon"), // B
//        #if MAX_ROBOT_ACTUATORS > 5
//        ACTUATOR_CHECKSUMS("zeta")     // C
//        #endif
//        #endif
//        #endif
//    };

    // default acceleration setting, can be overriden with newer per axis settings
    this->default_acceleration= THEKERNEL->config->value(acceleration_checksum)->by_default(100.0F )->as_number(); // Acceleration is in mm/s^2

    // make each motor
    for (size_t a = 0; a < MAX_ROBOT_ACTUATORS; a++) {
        Pin pins[3]; //step, dir, enable
        for (size_t i = 0; i < 3; i++) {
            pins[i].from_string(THEKERNEL->config->value(motor_checksums[a][i])->by_default("nc")->as_string())->as_output();
        }

        if(!pins[0].connected() || !pins[1].connected()) { // step and dir must be defined, but enable is optional
            if(a <= Z_AXIS) {
                THEKERNEL->streams->printf("FATAL: motor %c is not defined in config\n", 'X'+a);
                n_motors= a; // we only have this number of motors
                return;
            }
            break; // if any pin is not defined then the axis is not defined (and axis need to be defined in contiguous order)
        }

        StepperMotor *sm = new StepperMotor(pins[0], pins[1], pins[2]);
        // register this motor (NB This must be 0,1,2) of the actuators array
        uint8_t n= register_motor(sm);
        if(n != a) {
            // this is a fatal error
            THEKERNEL->streams->printf("FATAL: motor %d does not match index %d\n", n, a);
            return;
        }

        actuators[a]->change_steps_per_mm(THEKERNEL->config->value(motor_checksums[a][3])->by_default(a == 2 ? 2560.0F : 80.0F)->as_number());
        actuators[a]->set_max_rate(THEKERNEL->config->value(motor_checksums[a][4])->by_default(30000.0F)->as_number()/60.0F); // it is in mm/min and converted to mm/sec
        actuators[a]->set_acceleration(THEKERNEL->config->value(motor_checksums[a][5])->by_default(NAN)->as_number()); // mm/secs²
    }

    check_max_actuator_speeds(); // check the configs are sane

    // if we have not specified a z acceleration see if the legacy config was set
    if(isnan(actuators[Z_AXIS]->get_acceleration())) {
        float acc= THEKERNEL->config->value(z_acceleration_checksum)->by_default(NAN)->as_number(); // disabled by default
        if(!isnan(acc)) {
            actuators[Z_AXIS]->set_acceleration(acc);
        }
    }

    load_config_next1();

}

void Robot::load_config_next1()
{
	    // initialise actuator positions to current cartesian position (X0 Y0 Z0)
	    // so the first move can be correct if homing is not performed
	    ActuatorCoordinates actuator_pos;
	    arm_solution->cartesian_to_actuator(machine_position, actuator_pos);
	    for (size_t i = X_AXIS; i <= Z_AXIS; i++) {
	        actuators[i]->change_last_milestone(actuator_pos[i]);
	    }

	    #if MAX_ROBOT_ACTUATORS > 3
	    // initialize any extra axis to machine position
	    for (size_t i = A_AXIS; i < n_motors; i++) {
	         actuators[i]->change_last_milestone(machine_position[i]);
	    }
	    #endif

	    //this->clearToolOffset();

	    soft_endstop_enabled= THEKERNEL->config->value(soft_endstop_checksum, enable_checksum)->by_default(false)->as_bool();
	    soft_endstop_halt= THEKERNEL->config->value(soft_endstop_checksum, halt_checksum)->by_default(true)->as_bool();

	    soft_endstop_min[X_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, xmin_checksum)->by_default(NAN)->as_number();
	    soft_endstop_min[Y_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, ymin_checksum)->by_default(NAN)->as_number();
	    soft_endstop_min[Z_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, zmin_checksum)->by_default(NAN)->as_number();
	    soft_endstop_max[X_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, xmax_checksum)->by_default(NAN)->as_number();
	    soft_endstop_max[Y_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, ymax_checksum)->by_default(NAN)->as_number();
	    soft_endstop_max[Z_AXIS]= THEKERNEL->config->value(soft_endstop_checksum, zmax_checksum)->by_default(NAN)->as_number();

}

END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/540663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

iscsi删除已失效的链路

有套rac环境&#xff0c;主机连接存储使用的iscsi方式&#xff0c;使用了一段时间&#xff0c;客户感觉网络设计不合理&#xff0c;需要调整网段vlan和ip地址 首先关闭实例和集群&#xff0c;调整存储端和主机端的ip地址和vlan&#xff0c;调整后可以ping通&#xff0c;使用如…

隐藏自己的真实ip

本文转载于&#xff1a; https://blog.csdn.net/csdnmmd/article/details/126952312 1.ip查看 https://mp.weixin.qq.com/s/zs2clrxQts9f7pK6CQ2oOw 1.1 无隧道的情况 当前从138和请求ipinof.io上可以查到目前我的ip地址为真实的ip&#xff1a; 访问下面这个地址之后&#xff…

SVG矢量图怎么做?

SVG 矢量图是一种可缩放的图像格式&#xff0c;基于 XML 的标记语言。它可以用于描述二维矢量图形&#xff0c;并且具有数百种功能&#xff0c;能够帮助你创建出色的网站。SVG矢量图怎么做&#xff1f;在本教程中&#xff0c;我们将学习如何使用SVG矢量图编辑器——即时设计制作…

一种基于非均匀分簇和建立簇间路由的算法的无线传感器网络路由协议(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 本文准备了一种路由方法&#xff0c;该方法使传感器通过有效地使用能量将数据从发送方加载到接收器&#xff0c;因为它在 LEAC…

安装Ubuntu18.04双系统、干净卸载,并在Ubuntu系统中安装CARLA模拟器

Ubuntu系统安装 Ubuntu系统安装参照流程 Ubuntu 双系统安装流程_ubuntu双系统_地球被支点撬走啦的博客-CSDN博客 Ubuntu系统卸载 1.将开机启动项设置默认为Windows&#xff0c;进入BIOS设置界面调整BootDevice中Windows和Ubuntu的顺序&#xff0c;将Windows调整在Ubuntu前边…

封神之作!超火Java面试突击手册一周内转发2.4W次,最终被所有大厂封杀

前言 本文是为了帮大家快速回顾了Java中知识点&#xff0c;这套面试手册涵盖了诸多Java技术栈的面试题和答案&#xff0c;相信可以帮助大家在最短的时间内用作面试复习&#xff0c;能达到事半功倍效果。 本来想将文件上传到github上&#xff0c;但由于文件太大有的都无法显示…

OpenPCDet系列 | 5.4.1 DenseHead中的AnchorGenerator锚框生成模块

文章目录 AnchorGenerator模块AnchorGenerator.generate_anchors函数 AnchorGenerator模块 首先&#xff0c;根据点云场景将其划分为一个个grid&#xff0c;这个grid size是可以通过配置文件设定的点云场景方位和voxel大小计算出来的。 POINT_CLOUD_RANGE: [0, -39.68, -3, 6…

研发工程师玩转Kubernetes——部署应用

Kubernetes是容器的管理编排工具&#xff0c;而容器则是程序的载体。我们先在Docker上部署应用&#xff0c;然后再在kubernetes上部署&#xff0c;并对它们进行对比学习。 Docker部署应用 查看运行中的容器 docker ps可以看到下面的表头&#xff0c;此时没有一个运行中的容器…

图片压缩指定大小,让您的图片高效而优美

在现代社会中&#xff0c;图片是我们不可或缺的一部分&#xff0c;在各行业中都有着非常重要的作用。但是&#xff0c;大尺寸的图片不仅会占用过多的存储空间&#xff0c;还会导致网页或应用程序的加载速度变慢。因此&#xff0c;将图片压缩到指定大小是一个必要的步骤。 图片…

文档管理-gitlab+markdown网页插件

特点 使用git进行版本管理&#xff0c;本地编辑使用Typora。使用gitlab进行权限管理可以在线阅读通过Markdown在线阅读插件实现&#xff0c;可显示目录显示与链接跳转&#xff0c;界面优于自带的wiki。 与其他方式对比 gitlab的wiki&#xff1a;显示界面效果不好&#xff0c…

书籍《脆弱的繁华》读后感

前几周看完了《脆弱的繁华》这本书&#xff0c;这本书当时是公司组织的一次活动&#xff0c;邀请书籍原作者&#xff0c;张程对书籍进行了讲解&#xff0c;同时这本书也是在此次活动中免费赠送的&#xff0c;作者对于书籍做了一些说明&#xff0c;并且对一些问题也进行了探讨&a…

Azkaban 集群模式部署

文章目录 Azkaban 集群模式部署一、配置Mysql Azkaban 集群模式部署 将这三个包&#xff0c;上传到hadoop102&#xff0c;第一个是azkaban需要的建表语句 这三个解压到 /opt 目录下 输入命令&#xff1a;tar -zxvf azkaban-db-3.84.4.tar.gz -C /opt/ 输入命令&#xff1a;ta…

spring注册beanDefinition

代码使用springboot测试 1.ConfigurationClassPostProcessor 构造context时会创建reader。 构造reader时会创建processor。 最关键是第一个&#xff0c;类型是ConfigurationClassPostProcessor。 AbstractApplicationContext类的refresh方法的invokeBeanFactoryPostProcesso…

Node输出日志的正确姿势

背景 每个程序员都喜欢在有问题的代码中插入一些日志的方法来帮助调试程序&#xff0c;比如System.out.println或console.log。解决后&#xff0c;就会将这些语句删除&#xff0c;周而复始。 但是通过系统日志输出的日志格式都是这种&#xff1a; // output console.log(&quo…

TensoRF-张量辐射场论文笔记

TensoRF-张量辐射场论文笔记_什度学习的博客-CSDN博客 注释代码: https://github.com/xunull/read-TensoRF 官方源码&#xff1a;https://github.com/apchenstu/TensoRF Install environment conda create -n TensoRF python3.8 conda activate TensoRF pip install torch t…

HTTPTomcatServlet学习

HTTP&Tomcat 今日目标&#xff1a; 了解JavaWeb开发的技术栈理解HTTP协议和HTTP请求与响应数据的格式掌握Tomcat的使用掌握在IDEA中使用Tomcat插件理解Servlet的执行流程和生命周期掌握Servlet的使用和相关配置 1. Web概述 1.1 Web和JavaWeb的概念 Web是全球广域网&…

正点原子串口算法解析-定时器+数组长度判断

源码 片段1 片段2 片段3 解析 片段1的作用 开启一个10ms的定时器 片段2的作用 每10毫秒置位接收标志位且关闭定时器 片段3的作用和详解 代码第38行 用res变量接收数据 从代码第39行开始看 接收标志位不允许接收(不为0) 下面的所有代码都不会运行 如果接收标志为允许接收…

CRM管理系统如何选型?分别有什么作用?

CRM管理系统通常指CRM系统&#xff0c;中文名称是客户关系管理&#xff0c;起源于上世纪80年代的“接触管理”&#xff0c;它能确保客户在销售、营销、服务上的每一步交互都顺利高效&#xff0c;带动业绩的提升。今天就来说一说CRM管理系统是什么&#xff08;从使用到选型&…

【HarmonyOS】元服务混淆打包以及反混淆mapping文件生成

大家所知的Android中的“混淆”可以分为两部分&#xff0c;一部分是 Java 代码的优化与混淆&#xff0c;依靠 proguard 混淆器来实现&#xff1b;另一部分是资源压缩&#xff0c;从而可以减少包体积。 一般应用release发布的时候都会选择开启混淆&#xff0c;防止应用被反编译…

OpenPCDet系列 | 5.4.3 DenseHead中的AxisAlignedTargetAssigner正负样本分配模块

文章目录 AxisAlignedTargetAssigner模块assign_targets处理流程1. 提取有效gt信息2. 提取需要处理的类别信息3. 帧信息整合4. 批信息整合 assign_targets_single处理流程1. 构建每个anchor的正负样本label分配2. 构建每个anchor的正负样本编码信息bbox_targets分配3. 构建每个…