按规划持续工作
结论:接通 LinuxCNC M68/M66 到 standalone HAL adapter 的同步边界,新增 native remap/HAL 验证,确认 5axis switchkins remap 所需的 _hal[motion.switchkins-type] 读回路径可用。
This commit is contained in:
@@ -212,6 +212,7 @@ The validation fails if:
|
||||
| `linuxcnc_parameter_file_harness` | Validates LinuxCNC parameter file restore/save behavior and required/read-only parameter handling. |
|
||||
| `linuxcnc_interp_init_harness` | Validates vendored LinuxCNC `Interp::init()` emits canonical initialization boundaries, reads metric/inch machine units, and synchronizes current/selected tool slots through standalone status adapters. |
|
||||
| `linuxcnc_indexer_harness` | Validates vendored LinuxCNC single-axis rotary indexer dispatch emits lock/unlock and motion boundaries through the standalone event sink. |
|
||||
| `linuxcnc_remap_hal_sync_harness` | Validates vendored LinuxCNC `M68`/`M66` execution can drive the standalone HAL adapter boundary used by 5-axis switchkins remap files, including `_hal[motion.switchkins-type]` readback. |
|
||||
| `linuxcnc_tp_api_probe` | Validates vendored LinuxCNC trajectory planner calls for linear, arc, and queued motion paths. |
|
||||
| `linuxcnc_kinematics_probe` | Validates vendored LinuxCNC `trivkins.c` plus `kins_util.c` initialize and perform identity forward/inverse mapping through the standalone HAL/RTAPI boundary. |
|
||||
| `linuxcnc_5axis_kinematics_probe` | Validates vendored LinuxCNC `5axiskins.c` through `switchkins.c`, including 5-axis forward/inverse round-trip behavior and switching to identity kinematics. |
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <new>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
@@ -52,6 +53,12 @@ std::unordered_map<std::string, HalEntry> &values_for(standalone::HalValueKind k
|
||||
return pins();
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::vector<std::string>> &pin_aliases()
|
||||
{
|
||||
static std::unordered_map<std::string, std::vector<std::string>> values;
|
||||
return values;
|
||||
}
|
||||
|
||||
int lookup_hal_value(const char *name, std::unordered_map<std::string, HalEntry> &values,
|
||||
hal_type_t *type, hal_data_u **ptr, bool *connected)
|
||||
{
|
||||
@@ -81,6 +88,7 @@ void reset_hal_adapter()
|
||||
pins().clear();
|
||||
signals().clear();
|
||||
params().clear();
|
||||
pin_aliases().clear();
|
||||
}
|
||||
|
||||
void set_hal_value(HalValueKind kind, const char *name, hal_type_t type, hal_data_u value,
|
||||
@@ -89,6 +97,39 @@ void set_hal_value(HalValueKind kind, const char *name, hal_type_t type, hal_dat
|
||||
values_for(kind)[name] = HalEntry{type, value, connected};
|
||||
}
|
||||
|
||||
void link_hal_pin_alias(const char *source, const char *alias)
|
||||
{
|
||||
if (!source || !alias) {
|
||||
return;
|
||||
}
|
||||
pin_aliases()[source].push_back(alias);
|
||||
}
|
||||
|
||||
void sync_motion_analog_output(int index, double value)
|
||||
{
|
||||
hal_data_u analog{};
|
||||
analog.f = value;
|
||||
|
||||
std::ostringstream out_name;
|
||||
out_name << "motion.analog-out-" << index;
|
||||
set_hal_value(HalValueKind::Pin, out_name.str().c_str(), HAL_FLOAT, analog);
|
||||
|
||||
std::ostringstream padded_out_name;
|
||||
padded_out_name << "motion.analog-out-0" << index;
|
||||
set_hal_value(HalValueKind::Pin, padded_out_name.str().c_str(), HAL_FLOAT, analog);
|
||||
|
||||
const std::string names[] = {out_name.str(), padded_out_name.str()};
|
||||
for (const auto &name : names) {
|
||||
auto aliases = pin_aliases().find(name);
|
||||
if (aliases == pin_aliases().end()) {
|
||||
continue;
|
||||
}
|
||||
for (const auto &alias : aliases->second) {
|
||||
set_hal_value(HalValueKind::Pin, alias.c_str(), HAL_FLOAT, analog);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace standalone
|
||||
|
||||
int hal_init(const char *)
|
||||
|
||||
@@ -13,5 +13,7 @@ enum class HalValueKind {
|
||||
void reset_hal_adapter();
|
||||
void set_hal_value(HalValueKind kind, const char *name, hal_type_t type, hal_data_u value,
|
||||
bool connected = true);
|
||||
void link_hal_pin_alias(const char *source, const char *alias);
|
||||
void sync_motion_analog_output(int index, double value);
|
||||
|
||||
} // namespace standalone
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "emc/rs274ngc/rs274ngc_return.hh"
|
||||
#include "canon_event_sink.hh"
|
||||
#include "linuxcnc_hal_adapter.hh"
|
||||
#include "linuxcnc_tool_adapter.hh"
|
||||
#include "nml_intf/emc.hh"
|
||||
|
||||
@@ -381,6 +382,7 @@ void SET_AUX_OUTPUT_VALUE(int index, double value)
|
||||
std::ostringstream oss;
|
||||
oss << "SET_AUX_OUTPUT_VALUE index=" << index << " value=" << value;
|
||||
standalone::push_canon_event(oss.str());
|
||||
standalone::sync_motion_analog_output(index, value);
|
||||
}
|
||||
int WAIT(int index, int input_type, int wait_type, double timeout)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
#define private public
|
||||
#include "emc/rs274ngc/rs274ngc_interp.hh"
|
||||
#undef private
|
||||
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#include "canon_event_sink.hh"
|
||||
#include "linuxcnc_hal_adapter.hh"
|
||||
#include "linuxcnc_tool_adapter.hh"
|
||||
|
||||
namespace {
|
||||
|
||||
void print_bool(const std::string &name, bool value)
|
||||
{
|
||||
std::cout << name << "=" << (value ? 1 : 0) << "\n";
|
||||
}
|
||||
|
||||
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 initialize_interp(Interp &interp)
|
||||
{
|
||||
seed_switchkins_hal();
|
||||
standalone::reset_tool_adapter();
|
||||
standalone::reset_canon_events();
|
||||
|
||||
interp._setup.length_units = CANON_UNITS_MM;
|
||||
interp._setup.distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
interp._setup.ijk_distance_mode = DISTANCE_MODE::ABSOLUTE;
|
||||
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;
|
||||
std::memcpy(interp._readers, Interp::default_readers, sizeof(Interp::default_readers));
|
||||
interp.init_named_parameters();
|
||||
}
|
||||
|
||||
bool read_hal_named(Interp &interp, const char *name, double expected)
|
||||
{
|
||||
int status = 0;
|
||||
double value = 0.0;
|
||||
const int rc = interp.find_named_param(name, &status, &value);
|
||||
std::cout << name << ": rc=" << rc << " found=" << status << " value=" << value << "\n";
|
||||
return rc == INTERP_OK && status == 1 && std::fabs(value - expected) < 0.000001;
|
||||
}
|
||||
|
||||
bool has_event(const std::string &needle)
|
||||
{
|
||||
for (const auto &event : standalone::canon_events()) {
|
||||
if (event.find(needle) != std::string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
Interp interp;
|
||||
initialize_interp(interp);
|
||||
|
||||
bool ok = true;
|
||||
ok &= read_hal_named(interp, "_hal[motion.switchkins-type]", 0.0);
|
||||
|
||||
const int m68_to_tcp_rc = interp.execute("M68 E3 Q1\n");
|
||||
std::cout << "m68_to_tcp=" << m68_to_tcp_rc << "\n";
|
||||
ok &= m68_to_tcp_rc == INTERP_OK;
|
||||
ok &= read_hal_named(interp, "_hal[motion.switchkins-type]", 1.0);
|
||||
ok &= read_hal_named(interp, "_hal[motion.analog-out-03]", 1.0);
|
||||
|
||||
const int m66_sync_rc = interp.execute("M66 E0 L0\n");
|
||||
std::cout << "m66_sync=" << m66_sync_rc << "\n";
|
||||
std::cout << "m66_input_flag=" << interp._setup.input_flag << "\n";
|
||||
std::cout << "m66_input_index=" << interp._setup.input_index << "\n";
|
||||
std::cout << "m66_input_digital=" << interp._setup.input_digital << "\n";
|
||||
ok &= m66_sync_rc == INTERP_EXECUTE_FINISH;
|
||||
ok &= interp._setup.input_flag;
|
||||
ok &= interp._setup.input_index == 0;
|
||||
ok &= !interp._setup.input_digital;
|
||||
|
||||
const int m68_to_identity_rc = interp.execute("M68 E3 Q0\n");
|
||||
std::cout << "m68_to_identity=" << m68_to_identity_rc << "\n";
|
||||
ok &= m68_to_identity_rc == INTERP_OK;
|
||||
ok &= read_hal_named(interp, "_hal[motion.switchkins-type]", 0.0);
|
||||
|
||||
print_bool("canon_has_m68_tcp", has_event("SET_AUX_OUTPUT_VALUE index=3 value=1"));
|
||||
print_bool("canon_has_m66_sync", has_event("WAIT index=0 input_type=0 wait_type=0"));
|
||||
print_bool("canon_has_m68_identity", has_event("SET_AUX_OUTPUT_VALUE index=3 value=0"));
|
||||
ok &= has_event("SET_AUX_OUTPUT_VALUE index=3 value=1");
|
||||
ok &= has_event("WAIT index=0 input_type=0 wait_type=0");
|
||||
ok &= has_event("SET_AUX_OUTPUT_VALUE index=3 value=0");
|
||||
|
||||
print_bool("fiveaxis_remap_hal_sync_boundary", ok);
|
||||
return ok ? 0 : 1;
|
||||
}
|
||||
@@ -161,6 +161,8 @@ check_exitcode linuxcnc_interp_init_harness
|
||||
check_exitcode linuxcnc_interp_init_harness.run
|
||||
check_exitcode linuxcnc_remap_parse_harness
|
||||
check_exitcode linuxcnc_remap_parse_harness.run
|
||||
check_exitcode linuxcnc_remap_hal_sync_harness
|
||||
check_exitcode linuxcnc_remap_hal_sync_harness.run
|
||||
check_exitcode linuxcnc_indexer_harness
|
||||
check_exitcode linuxcnc_indexer_harness.run
|
||||
check_exitcode linuxcnc_rs274_compile_probe
|
||||
@@ -264,6 +266,21 @@ grep -Fq "xyzbc_trt_M430_ngc=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "xyzbc_trt_linuxcnc_ngc_remaps_parsed=1" "$REMAP_PARSE_STDOUT"
|
||||
grep -Fq "fiveaxis_linuxcnc_remap_parse_path=1" "$REMAP_PARSE_STDOUT"
|
||||
|
||||
REMAP_HAL_SYNC_STDOUT="$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stdout.log"
|
||||
grep -Fq "_hal[motion.switchkins-type]: rc=0 found=1 value=0" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "m68_to_tcp=0" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "_hal[motion.switchkins-type]: rc=0 found=1 value=1" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "_hal[motion.analog-out-03]: rc=0 found=1 value=1" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "m66_sync=2" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "m66_input_flag=1" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "m66_input_index=0" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "m66_input_digital=0" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "m68_to_identity=0" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "canon_has_m68_tcp=1" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "canon_has_m66_sync=1" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "canon_has_m68_identity=1" "$REMAP_HAL_SYNC_STDOUT"
|
||||
grep -Fq "fiveaxis_remap_hal_sync_boundary=1" "$REMAP_HAL_SYNC_STDOUT"
|
||||
|
||||
NAMEDPARAM_STDOUT="$BUILD_DIR/linuxcnc_namedparam_harness.run.stdout.log"
|
||||
grep -Fq "init_named_parameters=0" "$NAMEDPARAM_STDOUT"
|
||||
grep -Fq "global_named_count=57" "$NAMEDPARAM_STDOUT"
|
||||
|
||||
@@ -697,6 +697,11 @@ REMAP_PARSE_SOURCES=(
|
||||
"$WRAP_DIR/linuxcnc_remap_parse_harness.cpp"
|
||||
)
|
||||
|
||||
REMAP_HAL_SYNC_SOURCES=(
|
||||
"${INTERP_CORE_SOURCES[@]}"
|
||||
"$WRAP_DIR/linuxcnc_remap_hal_sync_harness.cpp"
|
||||
)
|
||||
|
||||
build_binary_target \
|
||||
linuxcnc_ini_probe \
|
||||
"$BUILD_DIR/linuxcnc_ini_probe" \
|
||||
@@ -1282,6 +1287,28 @@ else
|
||||
"$BUILD_DIR/linuxcnc_remap_parse_harness.run.stderr.log"
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
linuxcnc_remap_hal_sync_harness \
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness" \
|
||||
REMAP_RUNTIME_FLAGS \
|
||||
REMAP_HAL_SYNC_SOURCES \
|
||||
MINIMAL_LINK_FLAGS
|
||||
|
||||
if [[ "$(tr -d '[:space:]' < "$BUILD_DIR/linuxcnc_remap_hal_sync_harness.exitcode")" == "0" ]]; then
|
||||
set +e
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness" \
|
||||
>"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stdout.log" \
|
||||
2>"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stderr.log"
|
||||
REMAP_HAL_SYNC_RUN_RC=$?
|
||||
set -e
|
||||
echo "$REMAP_HAL_SYNC_RUN_RC" > "$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.exitcode"
|
||||
else
|
||||
rm -f \
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.exitcode" \
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stdout.log" \
|
||||
"$BUILD_DIR/linuxcnc_remap_hal_sync_harness.run.stderr.log"
|
||||
fi
|
||||
|
||||
build_binary_target \
|
||||
linuxcnc_indexer_harness \
|
||||
"$BUILD_DIR/linuxcnc_indexer_harness" \
|
||||
|
||||
Reference in New Issue
Block a user