新增曲柄滑块批量仿真接口

This commit is contained in:
zhangshun
2026-06-16 11:17:25 +08:00
parent c9e76d0850
commit a66952e636
6 changed files with 310 additions and 73 deletions

View File

@@ -122,7 +122,8 @@ json KinematicsWebAPI::dispatchCommand(const std::string &req_cmd, const json &r
return handleSpcCommand(req_cmd, req_param);
}
if (req_cmd == "Cmd_FourBar_CrankSlider")
if (req_cmd == "Cmd_FourBar_CrankSlider" ||
req_cmd == "Cmd_FourBar_CrankSlider_Simulate")
{
return handleFourBarCommand(req_cmd, req_param);
}

View File

@@ -1,5 +1,82 @@
#include "KinematicsWebAPI.h"
#include "FourBarMechanism/CrankSliderMechanism.h"
#include <cmath>
namespace
{
// 将机构点位转换为接口统一 JSON。
json buildPointsJson(const MechanismState &state)
{
json points_json;
for (const auto &point_pair : state.Points)
{
points_json[point_pair.first] = {
{"x", point_pair.second.X},
{"y", point_pair.second.Y}};
}
return points_json;
}
// 将机构姿态转换为接口统一 JSON。
json buildPosesJson(const MechanismState &state)
{
json poses_json;
for (const auto &pose_pair : state.Poses)
{
poses_json[pose_pair.first] = {
{"tx", pose_pair.second.tx},
{"ty", pose_pair.second.ty},
{"tz", pose_pair.second.tz},
{"qx", pose_pair.second.qx},
{"qy", pose_pair.second.qy},
{"qz", pose_pair.second.qz},
{"qw", pose_pair.second.qw}};
}
return poses_json;
}
// 将机构角度数据转换为接口统一 JSON。
json buildAnglesJson(const MechanismState &state)
{
json angles_json;
for (const auto &angle_pair : state.Angles)
{
angles_json[angle_pair.first] = angle_pair.second;
}
return angles_json;
}
// 将二维点列表转换为轨迹 JSON 数组。
json buildTrajectoryJson(const std::vector<Vector2D> &points)
{
json trajectory_json = json::array();
for (const auto &point : points)
{
trajectory_json.push_back({
{"x", point.X},
{"y", point.Y}});
}
return trajectory_json;
}
// 组装单帧机构状态,供实时接口和批量仿真接口复用。
json buildFrameJson(const MechanismState &state, int frame, double time, double angleDeg)
{
json frame_json;
frame_json["frame"] = frame;
frame_json["time"] = time;
frame_json["angleDeg"] = angleDeg;
frame_json["input_value"] = state.InputValue;
frame_json["points"] = buildPointsJson(state);
frame_json["poses"] = buildPosesJson(state);
frame_json["angles"] = buildAnglesJson(state);
if (state.hasWarning())
{
frame_json["warning"] = state.WarningMessage;
}
return frame_json;
}
} // namespace
json KinematicsWebAPI::handleFourBarCommand(const std::string &req_cmd, const json &req_param)
{
@@ -11,11 +88,19 @@ json KinematicsWebAPI::handleFourBarCommand(const std::string &req_cmd, const js
double L_BS = req_param.value("L_BS", 2.0);
double S_OFS = req_param.value("S_OFS", 0.0);
double angleDeg = req_param.value("angleDeg", 0.0);
double startAngleDeg = req_param.value("startAngleDeg", 0.0);
double endAngleDeg = req_param.value("endAngleDeg", 360.0);
double duration = req_param.value("duration", 2.0);
double stepTime = req_param.value("stepTime", 0.02);
log("Parameters: L_AB=" + std::to_string(L_AB) +
", L_BS=" + std::to_string(L_BS) +
", S_OFS=" + std::to_string(S_OFS) +
", angleDeg=" + std::to_string(angleDeg));
", angleDeg=" + std::to_string(angleDeg) +
", startAngleDeg=" + std::to_string(startAngleDeg) +
", endAngleDeg=" + std::to_string(endAngleDeg) +
", duration=" + std::to_string(duration) +
", stepTime=" + std::to_string(stepTime));
std::unique_ptr<CrankSliderMechanism> mechanism(createCrankSliderMechanism());
mechanism->setL_AB(L_AB);
@@ -32,6 +117,78 @@ json KinematicsWebAPI::handleFourBarCommand(const std::string &req_cmd, const js
{"validation_warnings", validation.Warnings}};
}
if (req_cmd == "Cmd_FourBar_CrankSlider_Simulate")
{
if (duration <= 0.0)
{
return {
{"success", false},
{"error", "Invalid simulation parameters"},
{"validation_errors", json::array({"duration 必须大于 0"})},
{"validation_warnings", json::array()}};
}
if (stepTime <= 0.0 || stepTime > duration)
{
return {
{"success", false},
{"error", "Invalid simulation parameters"},
{"validation_errors", json::array({"stepTime 必须大于 0 且不能大于 duration"})},
{"validation_warnings", json::array()}};
}
const int frameCount = static_cast<int>(std::ceil(duration / stepTime)) + 1;
if (frameCount < 2 || frameCount > 1000)
{
return {
{"success", false},
{"error", "Invalid simulation parameters"},
{"validation_errors", json::array({"仿真帧数必须在 2 到 1000 之间"})},
{"validation_warnings", json::array()}};
}
json frames_json = json::array();
for (int frame = 0; frame < frameCount; ++frame)
{
const double currentTime = frame == frameCount - 1 ? duration : stepTime * frame;
const double progress = duration <= 0.0 ? 0.0 : currentTime / duration;
const double currentAngleDeg = startAngleDeg + (endAngleDeg - startAngleDeg) * progress;
MechanismState state = mechanism->calculate(currentAngleDeg);
if (state.hasError())
{
return {
{"success", false},
{"error", state.ErrorMessage},
{"failed_frame", frame},
{"failed_time", currentTime},
{"failed_angleDeg", currentAngleDeg}};
}
frames_json.push_back(buildFrameJson(state, frame, currentTime, currentAngleDeg));
}
json result;
result["success"] = true;
result["frames"] = frames_json;
result["frame_count"] = frameCount;
result["duration"] = duration;
result["stepTime"] = stepTime;
result["startAngleDeg"] = startAngleDeg;
result["endAngleDeg"] = endAngleDeg;
result["trajectory"] = buildTrajectoryJson(mechanism->getTrajectoryPoints());
result["slider_trajectory"] = buildTrajectoryJson(mechanism->getSliderTrajectory());
result["parameters"] = {
{"L_AB", L_AB},
{"L_BS", L_BS},
{"S_OFS", S_OFS},
{"startAngleDeg", startAngleDeg},
{"endAngleDeg", endAngleDeg},
{"duration", duration},
{"stepTime", stepTime}};
return result;
}
MechanismState state = mechanism->calculate(angleDeg);
if (state.hasError())
{
@@ -43,35 +200,9 @@ json KinematicsWebAPI::handleFourBarCommand(const std::string &req_cmd, const js
json result;
result["success"] = true;
json points_json;
for (const auto &point_pair : state.Points)
{
points_json[point_pair.first] = {
{"x", point_pair.second.X},
{"y", point_pair.second.Y}};
}
result["points"] = points_json;
json poses_json;
for (const auto &pose_pair : state.Poses)
{
poses_json[pose_pair.first] = {
{"tx", pose_pair.second.tx},
{"ty", pose_pair.second.ty},
{"tz", pose_pair.second.tz},
{"qx", pose_pair.second.qx},
{"qy", pose_pair.second.qy},
{"qz", pose_pair.second.qz},
{"qw", pose_pair.second.qw}};
}
result["poses"] = poses_json;
json angles_json;
for (const auto &angle_pair : state.Angles)
{
angles_json[angle_pair.first] = angle_pair.second;
}
result["angles"] = angles_json;
result["points"] = buildPointsJson(state);
result["poses"] = buildPosesJson(state);
result["angles"] = buildAnglesJson(state);
result["input_value"] = state.InputValue;
if (state.hasWarning())
@@ -79,23 +210,8 @@ json KinematicsWebAPI::handleFourBarCommand(const std::string &req_cmd, const js
result["warning"] = state.WarningMessage;
}
json trajectory_json = json::array();
for (const auto &point : mechanism->getTrajectoryPoints())
{
trajectory_json.push_back({
{"x", point.X},
{"y", point.Y}});
}
result["trajectory"] = trajectory_json;
json slider_trajectory_json = json::array();
for (const auto &point : mechanism->getSliderTrajectory())
{
slider_trajectory_json.push_back({
{"x", point.X},
{"y", point.Y}});
}
result["slider_trajectory"] = slider_trajectory_json;
result["trajectory"] = buildTrajectoryJson(mechanism->getTrajectoryPoints());
result["slider_trajectory"] = buildTrajectoryJson(mechanism->getSliderTrajectory());
result["parameters"] = {
{"L_AB", L_AB},