IS_REACHABLE

本文介绍了Linux内核配置中几个关键宏定义的作用,包括IS_BUILTIN、IS_MODULE、IS_ENABLED及IS_REACHABLE,并解释了它们如何区分内建模块与加载模块的不同状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IS_BUILTIN(CONFIG_FOO):如果CONFIG_FOO=y的话,就返回1,否则返回0
IS_MODULE(CONFIG_FOO):如果CONFIG_FOO=m的话,就返回1,否则返回0
而IS_ENABLED(CONFIG_FOO) 的定义如下,就只要CONFIG_FOO=y/m 都返回1,否则返回0
#define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))

 IS_REACHABLE(CONFIG_FOO)的定义如下:
#define IS_REACHABLE(option) __or(IS_BUILTIN(option), \
                __and(IS_MODULE(option), __is_defined(MODULE)))
IS_REACHABLE 和 IS_ENABLED 大部分情况这两者的情况是一样的,只有当CONFIG_FOO=m且在buildin的时候IS_REACHABLE 返回0.因为只有在build
ko的时候才会定义MODULE.
具体可以看kernel 根目录下的makefile中的定义
KBUILD_AFLAGS_MODULE  := -DMODULE
KBUILD_CFLAGS_MODULE  := -DMODULE
%% 修复后的机械臂PTP轨迹控制 - 完整解决方案 clear; clc; close all; % =========================================== % 1. 机械臂参数重新定义 (Modified D-H) % =========================================== % D-H参数表 (单位: mm) - 修正参数确保可达性 a = [0, 0, 500, 500, 0, 0]; % 连杆长度 alpha = [0, -pi/2, 0, -pi/2, pi/2, -pi/2]; % 连杆扭角 d = [400, 0, 0, 0, 0, 100]; % 连杆偏移 % 关节角度范围 (弧度) - 放宽限制 joint_limits = [ -pi, pi; % 关节1 (-180° to 180°) -pi/2, pi/2; % 关节2 (-90° to 90°) -pi/2, pi/2; % 关节3 (-90° to 90°) -pi, pi; % 关节4 (-180° to 180°) 0, pi; % 关节5 (0° to 180°) -pi, pi % 关节6 (-180° to 180°) ]; % 工作空间参数 min_reach = sqrt((min([a(2), a(3)]))^2 + d(1)^2); max_reach = sqrt((a(2)+a(3))^2 + (d(1)+d(6))^2); fprintf('机械臂工作空间范围: %.2f mm 到 %.2f mm\n', min_reach, max_reach); % =========================================== % 2. 增强的逆运动学求解 % =========================================== % 工作空间检查函数 function reachable = is_reachable(position, min_r, max_r) distance = norm(position(1:2)); height = position(3); radial_distance = sqrt(distance^2 + height^2); reachable = (radial_distance >= min_r) && (radial_distance <= max_r); end % 改进的逆运动学求解 (带工作空间检查) function solutions = enhanced_inverse_kinematics(T_target, a, alpha, d, joint_limits, min_r, max_r) % 初始化解集 solutions = []; % 目标位姿分解 P_target = T_target(1:3, 4); R_target = T_target(1:3, 1:3); % 检查工作空间可达性 if ~is_reachable(P_target, min_r, max_r) warning('目标位置 (%.1f, %.1f, %.1f) 超出工作空间范围!', ... P_target(1), P_target(2), P_target(3)); return; end % 计算腕部中心 (Wrist Center) P_wc = P_target - d(6)*R_target(:,3); % --- 关节1求解 --- theta1 = atan2(P_wc(2), P_wc(1)); theta1_alt = theta1 + pi; % 另一解 % --- 关节3求解 --- for j1 = [theta1, theta1_alt] % 计算关节2位置 x = P_wc(1)*cos(j1) + P_wc(2)*sin(j1); z = P_wc(3) - d(1); % 几何关系计算关节3 D = (x^2 + z^2 - a(2)^2 - a(3)^2)/(2*a(2)*a(3)); % 处理超出范围的情况 if abs(D) > 1 % 找到最接近的可达点 D = sign(D); % 取边界值 fprintf('关节3求解超出范围, 使用边界值: %.2f\n', D); end theta3 = acos(D); theta3_alt = -theta3; % 另一解 % --- 关节2求解 --- for j3 = [theta3, theta3_alt] denom = a(2)^2 + a极(3)^2 + 2*a(2)*a(3)*cos(j3); % 避免除零错误 if abs(denom) < 1e-6 fprintf('分母接近零, 跳过当前解\n'); continue; end sin_theta2 = ((a(2)+a(3)*cos(j3))*z - a(3)*sin(j3)*x)/denom; cos_theta2 = ((a(2)+a(3)*cos(j3))*x + a(3)*sin(j3)*z)/denom; j2 = atan2(sin_theta2, cos_theta2); % --- 关节4,5,6求解 --- % 计算前三关节变换矩阵 T01 = dh_transform(0, alpha(1), d(1), j1); T12 = dh_transform(a(2), alpha(2), d(2), j2); T23 = dh_transform(a(3), alpha(3), d(3), j3); T03 = T01 * T12 * T23; % 计算腕部姿态 R36 = T03(1:3,1:3)' * R_target; % 欧拉角解(Z-Y-Z) theta5 = atan2(sqrt(R36(1,3)^2 + R36(2,3)^2), R36(3,3)); theta5_alt = -theta5; for j5 = [theta5, theta5_alt] if abs(j5) > 1e-3 % 避免奇异 theta4 = atan2(R36(2,3)/sin(j5), R36(1,3)/sin(j5)); theta6 = atan2(R36(3,2)/sin(j5), -R36(3,1)/sin(j5)); else % 奇异处理 theta4 = 0; theta6 = atan2(R36(1,2), R36(1,1)); end % 保存解(即使超出限制,用于后续优化) q = [j1, j2, j3, theta4, j5, theta6]; solutions = [solutions; q]; end end end end % 数值优化逆解 function [q_opt, error] = numerical_ik(T_target, a, alpha, d, joint_limits, initial_guess) options = optimoptions('fmincon', 'Display', 'final', ... 'Algorithm', 'sqp', ... 'MaxIterations', 200, ... 'StepTolerance', 1e-6, ... 'OptimalityTolerance', 1e-6); % 定义优化目标函数 cost_func = @(q) norm(forward_kinematics(q, a, alpha, d) - T_target, 'fro'); % 设置约束 (关节限位) lb = joint_limits(:,1)'; ub = joint_limits(:,2)'; % 使用初始猜测或随机初始值 if nargin < 5 || isempty(initial_guess) q0 = mean(joint_limits, 2)'; % 关节范围中值 else q0 = initial_guess; end % 执行优化 q_opt = fmincon(cost_func, q0, [], [], [], [], lb, ub, [], options); % 计算最终误差 T_actual = forward_kinematics(q_opt, a, alpha, d); error = norm(T_target(1:3,4) - T_actual(1:3,4)); end % =========================================== % 3. 主程序 - 增强的PTP轨迹控制 % =========================================== % 定义起始点和目标点 (笛卡尔坐标) P_start = [600; 200; 500]; % mm P_target = [400; -300; 600]; % mm % 目标姿态 (假设相同) R_target = [1, 0, 0; 0, 1, 0; 0, 0, 1]; % 单位矩阵 % 构建目标位姿矩阵 T_start = [R_target, P_start; 0, 0, 0, 1]; T_target = [R_target, P_target; 0, 0, 0, 1]; % 检查起始点可达性 if ~is_reachable(P_start, min_reach, max_reach) % 自动调整到最近可达点 direction = P_start/norm(P_start); adjusted_distance = min(max(norm(P_start(1:2)), min_reach), max_reach); P_start_adjusted = [direction(1:2)*adjusted_distance; P_start(3)]; fprintf('调整起始点位置: [%.1f, %.1f, %.1f] -> [%.1f, %.1f, %.1f]\n', ... P_start(1), P_start(2), P_start(3), ... P_start_adjusted(1), P_start_adjusted(2), P_start_adjusted(3)); P_start = P_start_adjusted; T_start = [R_target, P_start; 0, 0, 0, 1]; end % 使用增强逆运动学求解起始点 fprintf('使用增强逆运动学求解起始点...\n'); solutions_start = enhanced_inverse_kinematics(T_start, a, alpha, d, joint_limits, min_reach, max_reach); fprintf('找到 %d 个候选解\n', size(solutions_start,1)); % 选择有效解或使用数值方法 valid_solutions = []; for i = 1:size(solutions_start,1) q = solutions_start(i,:); if is_valid_solution(q, joint_limits) valid_solutions = [valid_solutions; q]; end end if ~isempty(valid_solutions) fprintf('其中 %d 个解满足关节限制\n', size(valid_solutions,1)); q_start = valid_solutions(1,:)'; else fprintf('无满足关节限制的解析解, 使用数值优化...\n'); [q_start, start_error] = numerical_ik(T_start, a, alpha, d, joint_limits); fprintf('数值优化解误差: %.4f mm\n', start_error); end fprintf('起始关节角度: [%.2f, %.2f, %.2f, %.2f, %.2f, %.2f] rad\n', q_start); % 目标点求解(类似过程) % ... [省略类似代码] ... % 后续轨迹生成和控制代码保持不变 % ... [使用之前提供的轨迹生成和控制代码] ...
最新发布
06-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值