按规划持续工作

结论:WASM interpreter 已链接 vendored LinuxCNC interp_remap.cc,并通过 SDK C ABI 运行 vendored xyzac/xyzbc switchkins remap demo;Node/host/browser smoke 均通过,未新增 JavaScript M428/M429/M430 或运动学语义。
This commit is contained in:
2026-06-08 18:04:09 +08:00
parent 567f72d35f
commit 149095274c
7 changed files with 292 additions and 15 deletions

View File

@@ -11,6 +11,7 @@
#include <emscripten/emscripten.h>
#include "canon_event_sink.hh"
#include "emc/ini/inifile.hh"
#include "linuxcnc_hal_adapter.hh"
#include "linuxcnc_tool_adapter.hh"
#include "nml_intf/emc.hh"
@@ -58,6 +59,19 @@ void seed_hal_values()
HAL_FLOAT, disconnected, false);
}
void seed_switchkins_hal()
{
standalone::reset_hal_adapter();
hal_data_u switchkins{};
switchkins.f = 0.0;
standalone::set_hal_value(standalone::HalValueKind::Pin, "motion.switchkins-type",
HAL_FLOAT, switchkins);
standalone::set_hal_value(standalone::HalValueKind::Pin, "motion.analog-out-03",
HAL_FLOAT, switchkins);
standalone::link_hal_pin_alias("motion.analog-out-03", "motion.switchkins-type");
}
void seed_tool_values()
{
standalone::reset_tool_adapter();
@@ -92,6 +106,29 @@ void initialize_minimal_interp(Interp &interp)
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
}
void initialize_fiveaxis_remap_interp(Interp &interp)
{
seed_switchkins_hal();
seed_tool_values();
interp._setup.length_units = CANON_UNITS_MM;
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
interp._setup.ijk_distance_mode = DISTANCE_MODE::INCREMENTAL;
interp._setup.feed_mode = FEED_MODE::UNITS_PER_MINUTE;
interp._setup.plane = CANON_PLANE::XY;
interp._setup.motion_mode = G_0;
interp._setup.percent_flag = false;
interp._setup.sequence_number = 0;
interp._setup.parameter_occurrence = 0;
interp._setup.num_spindles = 1;
interp._setup.feature_set = FEATURE_INI_VARS | FEATURE_HAL_PIN_VARS;
interp._setup.parameter_g73_peck_clearance = 1.0;
interp._setup.parameter_g83_peck_clearance = 1.0;
interp._setup.parameters[5599] = 1.0;
interp.load_tool_table();
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
interp.init_named_parameters();
}
void initialize_indexer_interp(Interp &interp)
{
standalone::reset_hal_adapter();
@@ -220,6 +257,51 @@ void append_named_value(std::ostringstream &output, Interp &interp, const char *
output << name << ": rc=" << rc << " found=" << status << " value=" << value << "\n";
}
std::string parent_path(const char *path)
{
std::string value = path ? path : "";
const std::string::size_type slash = value.find_last_of('/');
if (slash == std::string::npos) {
return ".";
}
if (slash == 0) {
return "/";
}
return value.substr(0, slash);
}
bool parse_machine_remaps(Interp &interp, std::ostringstream &output, const char *ini_path)
{
const std::string machine_dir = parent_path(ini_path);
const std::string remap_dir = machine_dir + "/remap_subs";
linuxcnc::IniFile ini(ini_path ? ini_path : "");
const bool opened = static_cast<bool>(ini);
output << "fiveaxis_ini_open=" << (opened ? 1 : 0) << "\n";
if (!opened) {
return false;
}
std::snprintf(interp._setup.program_prefix, sizeof(interp._setup.program_prefix), "%s",
machine_dir.c_str());
interp._setup.subroutines[0] = strstore(remap_dir.c_str());
bool ok = true;
int remap_count = 0;
while (auto remap = ini.findString(++remap_count, "REMAP", "RS274NGC")) {
const int line_number = ini.lineOf(remap_count, "REMAP", "RS274NGC").second;
const int rc = interp.parse_remap(remap->c_str(), line_number);
output << "fiveaxis_parse_remap_" << remap_count << "=" << rc << "\n";
ok &= rc == INTERP_OK;
}
remap_count -= 1;
output << "fiveaxis_parsed_remap_count=" << remap_count << "\n";
ok &= remap_count == 3;
output << "fiveaxis_remaps_ready=" << (ok ? 1 : 0) << "\n";
return ok;
}
void apply_parameter_assignments(Interp &interp, const char *assignments)
{
std::istringstream input(assignments ? assignments : "");
@@ -368,6 +450,102 @@ char *lcinterp_run_file(const char *path)
return lcinterp_run_file_with_ini(path, nullptr);
}
EMSCRIPTEN_KEEPALIVE
char *lcinterp_run_fiveaxis_remap_file(const char *path, const char *ini_path)
{
if (ini_path && ini_path[0] != '\0') {
setenv("INI_FILE_NAME", ini_path, 1);
} else {
unsetenv("INI_FILE_NAME");
}
Interp interp;
standalone::reset_canon_events();
initialize_fiveaxis_remap_interp(interp);
std::ostringstream output;
bool ok = parse_machine_remaps(interp, output, ini_path);
const int open_rc = interp.open(path);
output << "fiveaxis_file_open=" << open_rc << "\n";
if (open_rc != INTERP_OK) {
append_error_text(output, interp, "fiveaxis_file_error_text=", open_rc);
output << "fiveaxis_linuxcnc_remap_file_execute=0\n";
unsetenv("INI_FILE_NAME");
return copy_result(output.str());
}
constexpr int max_file_steps = 4096;
int file_read_count = 0;
int file_execute_count = 0;
int file_finish_count = 0;
int final_rc = INTERP_OK;
bool reached_exit = false;
while ((file_read_count < max_file_steps) && (file_execute_count < max_file_steps)) {
const int read_rc = interp.read();
if (read_rc == INTERP_ENDFILE) {
output << "fiveaxis_file_read_eof=" << read_rc << "\n";
final_rc = read_rc;
break;
}
++file_read_count;
if ((read_rc != INTERP_OK) && (read_rc != INTERP_EXECUTE_FINISH)) {
output << "fiveaxis_file_read_" << file_read_count << "=" << read_rc << "\n";
append_error_text(output, interp, "fiveaxis_file_error_text=", read_rc);
final_rc = read_rc;
ok = false;
break;
}
const int execute_rc = interp.execute();
++file_execute_count;
final_rc = execute_rc;
if (execute_rc == INTERP_EXECUTE_FINISH) {
++file_finish_count;
}
if ((execute_rc != INTERP_OK) && (execute_rc != INTERP_EXIT) &&
(execute_rc != INTERP_EXECUTE_FINISH)) {
output << "fiveaxis_file_execute_" << file_execute_count << "="
<< execute_rc << "\n";
append_error_text(output, interp, "fiveaxis_file_error_text=", execute_rc);
ok = false;
break;
}
if (execute_rc == INTERP_EXIT) {
reached_exit = true;
break;
}
}
int hal_status = 0;
double switchkins_type = 0.0;
const int hal_rc =
interp.find_named_param("_hal[motion.switchkins-type]", &hal_status, &switchkins_type);
output << "fiveaxis_file_read_count=" << file_read_count << "\n";
output << "fiveaxis_file_execute_count=" << file_execute_count << "\n";
output << "fiveaxis_file_finish_count=" << file_finish_count << "\n";
output << "fiveaxis_file_final_rc=" << final_rc << "\n";
output << "fiveaxis_file_reached_exit=" << (reached_exit ? 1 : 0) << "\n";
output << "fiveaxis_hal_switchkins: rc=" << hal_rc << " found=" << hal_status
<< " value=" << switchkins_type << "\n";
ok &= reached_exit;
ok &= file_read_count > 0;
ok &= file_execute_count > 0;
ok &= file_read_count < max_file_steps;
ok &= file_execute_count < max_file_steps;
ok &= hal_rc == INTERP_OK && hal_status == 1 && switchkins_type == 0.0;
output << "fiveaxis_linuxcnc_remap_file_execute=" << (ok ? 1 : 0) << "\n";
unsetenv("INI_FILE_NAME");
return copy_result(output.str());
}
EMSCRIPTEN_KEEPALIVE
char *lcinterp_restore_parameters(const char *path)
{

View File

@@ -74,6 +74,10 @@ export async function createLinuxCncInterpSdk(moduleOptions = {}) {
return callStringResult(mod, "lcinterp_run_file_with_ini", path, iniPath);
},
runFiveAxisRemapFile(path, iniPath) {
return callStringResult(mod, "lcinterp_run_fiveaxis_remap_file", path, iniPath);
},
restoreParameters(path) {
return callStringResult(mod, "lcinterp_restore_parameters", path);
},