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

文章目录

    • 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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据库界的科技与狠活: 创邻科技Galaxybase X英特尔SGX数据加密解决方案正式发布

引言 近日&#xff0c;创邻科技入选与英特尔合作&#xff0c;在基于第四代英特尔至强处理器的支持下&#xff0c;利用软件防护扩展&#xff08;Software Guard Extension,SGX&#xff09; 技术&#xff0c;打造出了具备可信执行环境的图数据库产品&#xff0c;保护企业释放关联…

nodejs进阶(4)—读取图片到页面

我们先实现从指定路径读取图片然后输出到页面的功能。 先准备一张图片imgs/dog.jpg。 file.js里面继续添加readImg方法&#xff0c;在这里注意读写的时候都需要声明binary。&#xff08;file.js 在上一篇文章nodejs进阶3-路由处理中有完整的内容&#xff09; readImg:functi…

03)FastDFS配置nginx 服务,使用http方式访问图片

FastDFS是没有文件访问功能的,需要借助其他工具实现图片HTTP访问的。 没安装nginx时比如前端html网页想获取 FastDFS的一张图片显示,需要java写个controller,然后使用 FastDFS-java client客户端调用文件获取api,HttpServletResponre在返回图片流.给前端显示。 安装了nginx…

计算机图形学-GAMES101-9

前言 材质和光的相互作用很重要。VertexShader和FragmentShader。纹理贴图Texture mapping。 一、在三角形中插值 为什么要在三角形内部插值&#xff1f;虽然我们的操作很多是在三角形顶点上进行计算的&#xff0c;但是对于三角形内部我们也希望每个像素点能得到一个值&…

ChatGPT的兴起的时代,国内chatgpt产品大盘点

在人工智能技术的不断发展和应用下&#xff0c;自然语言处理技术成为了研究的热点之一。而其中最受关注的就是“聊天机器人”技术&#xff0c;而GPT&#xff08;Generative Pre-trained Transformer&#xff09;模型则是目前最流行的聊天机器人生成模型之一。 随着 ChatGPT 技…

模板类与友元

目录 分类 一、非模板友元&#xff1a;友元函数不是模板函数&#xff0c;而是利用模板类参数生成的函数&#xff1b; 代码 分析 运行结果 二、约束模板友元&#xff1a;模板类实例化时&#xff0c;每个实例化的类对应一个友元函数&#xff1b;并且这个模板友元适用多种类模…

pg事务:事务ID

事务ID pg中每个事务都会分配事务ID&#xff0c;事务ID分为虚拟事务ID和持久化事务ID&#xff08;transactionID&#xff09;。pg的事务ID非常重要&#xff0c;是理解事务、数据可见性、事务ID回卷等等的重要知识点。 虚拟事务ID 只读事务不会分配事务ID&#xff0c;事务ID是…

Chrome Performance 页面性能分析

Chrome Performance 页面性能分析 背景介绍 性能优化是前端开发一个非常重要的组成部分&#xff0c;如何更好地进行网络传输&#xff0c;如何优化浏览器渲染过程&#xff0c;来定位项目中存在的问题。Chrome DevTools给我们提供了2种常用方式 Audits和Performance&#xff0c…

三分钟看懂JDK、JRE和JVM的区别和联系

节选自JavaGuide(Github 标星 134k star!「Java学习 + 面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识) JVM Java 虚拟机(JVM)是运行 Java 字节码的虚拟机。JVM 有针对不同系统的特定实现(Windows,Linux,macOS),目的是使用相同的字节码,它们都会给出相同…

【C++】21年精通C++之泛型编程和模板初阶知识

❤️前言 大家好&#xff01;今天和大家一起学习关于C泛型编程和模板初阶的相关知识。 正文 我们之前已经学习了C中非常重要的一个特性——函数重载&#xff0c;函数重载很好地提高了我们代码的可读性。但是对于适配多种参数的某种函数来说&#xff0c;我们如果使用函数重载就…

Maven安装和配置(详细版)

Maven安装和配置 Maven安装1、安装链接&#xff1a;2、配置环境变量&#xff1a; Maven配置1、修改Maven仓库下载镜像及修改仓库位置&#xff1a;2、在Idea上配置Maven&#xff1a; 测试Maven安装能否安装jar包 Maven安装 1、安装链接&#xff1a; Maven – Download Apache …

阿里云服务器 之 mqtt服务器搭建及使用

本文主要是对mqtt的学习使用&#xff0c;其中服务器是基于阿里云服务器的mqtt功能&#xff0c;客户端使用的是mqttx软件。 一、服务器部分搭建说明 1、如果是首次使用&#xff0c;则需要经过注册与认证的步骤。 2、找到"产品与服务"-->"物联网平台"&…

【MySQL】多表查询

上一篇介绍了外键约束,外键约束是用于连接两张数据表的,所以在此基础上就有了多表查询 之前的查询都是单表查询,这里我们会将多个数据表的数据结果返回在一张表上 文章目录 1.多表关系2.多表查询2.1 多表查询分类2.2 内连接2.3 外连接2.4 自连接2.5 联合查询2.6子查询 1.多表关…

微信小程序nodejs+vue+uniapp超市网上购物商城系统

超市购物系统用户端要求在系统的安卓手机上可以运行&#xff0c;主要实现了管理端&#xff1b;首页、个人中心、用户管理、商品分类管理、商品信息管理、商品入库管理、订单信息管理、订单配送管理、订单评价管理、退货申请管理、换货申请管理、系统管理&#xff0c;用户端&…

【大数据学习篇7】小试牛刀统计并且分析天猫数据

本项目基于搭建大数据环境&#xff0c;通过将数据存放在HDFS上&#xff0c;从HDFS中获取数据&#xff0c;然后根据实际需求通过Spark或Spark SQL对数据进行读取分析&#xff0c;将分析结果存储到HBase表中&#xff0c;最终通过 ECharts数据可视化工具基于Python Web平台实现数据…

docker-compose 实现Seata Server高可用部署 | Spring Cloud 51

一、前言 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 TC (Transaction Coordinator) - 事务协调者 维护全局和分支事…

看模型、做技术交底、做项目汇报,图新说数字化汇报平台引领交互式汇报新模式

现场汇报效果不好&#xff0c;导致丢了一个项目&#xff01; 项目汇报平淡无奇&#xff0c;方案屡次被毙&#xff01; 面对专家质疑&#xff0c;回答苍白无力&#xff01; 估计大家都有过这种经历和感受。 详细分析一下&#xff0c;基本上有以下几个方面的原因&#xff1a; …

虚幻or现实?堆区、栈区真实存在吗?是操作系统在骗你罢了...

文章目录 &#x1f490;专栏导读&#x1f490;文章导读&#x1f427;引例 &#x1f426;进程地址空间&#x1f426;虚拟地址与物理内存的联系&#x1f514;回答引例中的问题&#x1f513;写时拷贝 &#x1f426;虚拟地址存在的意义&#x1f513;malloc的本质 &#x1f490;专栏…

装饰者设计模式解读

问题引进 星巴克咖啡订单项目&#xff08;咖啡馆&#xff09;&#xff1a; 1) 咖啡种类/单品咖啡&#xff1a;Espresso(意大利浓咖啡)、ShortBlack、LongBlack(美式咖啡)、Decaf(无因咖啡) 2) 调料&#xff1a;Milk、Soy(豆浆)、Chocolate 3) 要求在扩展新的咖啡种类时&#x…

接口测试全流程扫盲,让我看看有哪些漏网之鱼

目录 扫盲内容&#xff1a; 1.什么是接口&#xff1f; 2.接口都有哪些类型&#xff1f; 3.接口的本质及其工作原理是什么&#xff1f; 4.什么是接口测试&#xff1f; 5.问什么要做接口测试&#xff1f; 6.怎样做接口测试&#xff1f; 7.接口测测试点是什么&#xff1f;…