GRBL运动控制算法(二)圆弧插补
前言
GRBL 是一款高性能、开源的嵌入式 CNC(计算机数控)控制器固件,专为 Arduino 平台优化,广泛应用于雕刻机、激光切割机、3D 打印机及其他精密运动控制场景。自 2009 年发布以来,GRBL 凭借其高效的运动规划算法、稳定的实时控制性能和紧凑的代码结构,成为创客、工程师和制造商的首选解决方案。
本文深入剖析 GRBL1.1 的圆弧插补实现原理,从参数解析、误差控制逐层拆解,帮助读者理解其底层逻辑与设计思想,为开发者优化运动算法或用户调参提供理论参考。
一.GRBL圆弧插补流程
1 .函数定义部分
#ifdef USE_LINE_NUMBERSvoid mc_arc(float *position, float *target, float *offset, float radius, float feed_rate, uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc, int32_t line_number)
#elsevoid mc_arc(float *position, float *target, float *offset, float radius, float feed_rate,uint8_t invert_feed_rate, uint8_t axis_0, uint8_t axis_1, uint8_t axis_linear, uint8_t is_clockwise_arc)
#endif
这是一个条件编译的函数定义,根据是否定义了USE_LINE_NUMBERS宏决定是否包含line_number参数
参数说明:
position: 当前位置坐标数组
target: 目标位置坐标数组
**offset: **从起点到圆心的偏移量
radius: 圆弧半径
**feed_rate: **进给速率
invert_feed_rate: 是否反转进给速率标志
**axis_0: **第一个圆弧平面轴(X/Y/Z中的某一个)
axis_1: 第二个圆弧平面轴
**axis_linear: **线性轴(垂直于圆弧平面的轴)
**is_clockwise_arc: **是否为顺时针圆弧标志
**line_number: **(可选)行号,用于调试或G代码解析
2 .流程图
以下是圆弧插补流程图
二.GRBL圆弧插补算法
1 .圆心坐标计算
根据 gc_execute_line()函数, 对G02,G03代码进行解析,通过向量几何和勾股定理,将G代码中的两点+半径参数转换为圆心坐标。
uint8_t gc_execute_line(char *line)
{
...// 如果当前单位为英寸模式,将半径值转换为毫米if (gc_block.modal.units == UNITS_MODE_INCHES) { gc_block.values.r *= MM_PER_INCH; }// 计算中间变量 h_x2_div_d = 4*r² - x² - y²float h_x2_div_d = 4.0 * gc_block.values.r*gc_block.values.r - x*x - y*y;// 如果计算结果为负,说明圆弧半径错误(无法构成有效圆弧)if (h_x2_div_d < 0) { FAIL(STATUS_GCODE_ARC_RADIUS_ERROR); } // [圆弧半径错误]// 完成 h_x2_div_d 的计算:-sqrt(h_x2_div_d)/hypot(x,y) // 等价于 -(h * 2 / d)h_x2_div_d = -sqrt(h_x2_div_d)/hypot_f(x,y); // 如果是逆时针圆弧(CCW),反转 h_x2_div_d 的符号(参见下方示意图)if (gc_block.modal.motion == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; } // 处理负半径情况if (gc_block.values.r < 0) { h_x2_div_d = -h_x2_div_d; gc_block.values.r = -gc_block.values.r; // 将半径取正值} // 通过计算得出圆弧的实际中心坐标(完成操作)gc_block.values.ijk[axis_0] = 0.5*(x-(y*h_x2_div_d)); // 计算x轴的圆心坐标gc_block.values.ijk[axis_1] = 0.5*(y+(x*h_x2_div_d)); // 计算y轴的圆心坐标
}
圆心坐标求解图
由距离公式:
d = x 2 + y 2 \begin{align*} d = \sqrt{x^2 + y^2} \end{align*} d=x2+y2
由勾股定理:
h = r 2 − ( d 2 ) 2 = 4 r 2 − x 2 − y 2 2 \begin{align*} h &= \sqrt{r^2 - \left(\frac{d}{2}\right)^2} = \frac{\sqrt{4r^2 - x^2 - y^2}}{2} \end{align*} h=r2−(2d)2=24r2−x2−y2
由△ADO 和△TBC 相似:
∣ A D ∣ = y d ⋅ h ∣ D O ∣ = x d ⋅ h \begin{align*} |AD| &= \frac{y}{d} \cdot h \\[10pt] |DO| &= \frac{x}{d} \cdot h \end{align*} ∣AD∣∣DO∣=dy⋅h=dx⋅h
P(0,0)为当前位置,T(x,y)为目标位置,圆心坐标(向量推导):
A 的坐标 ( x 2 , y 2 ) (\frac{x}{2} ,\frac{y}{2}) (2x,2y)
i = x 2 − ∣ A D ∣ = x 2 − y d ⋅ h j = y 2 + ∣ D O ∣ = y 2 + x d ⋅ h % 圆心坐标计算公式 \begin{align*} i &= \frac{x}{2}-|AD|= \frac{x}{2} - \frac{y}{d} \cdot h \\[10pt] % X轴圆心坐标(i = x/2 - (y/d)*h) j &=\frac{y}{2}+|DO|= \frac{y}{2} + \frac{x}{d} \cdot h % Y轴圆心坐标(j = y/2 + (x/d)*h) \end{align*} ij=2x−∣AD∣=2x−dy⋅h=2y+∣DO∣=2y+dx⋅h
半径有效性检查:
计算 4 r 2 − x 2 − y 2 4r^2 - x^2 - y^2 4r2−x2−y2,若为负说明半径太小(无法通过两点)
触发错误条件: r < d 2 r < \frac{d}{2} r<2d(即半径小于两点距离的一半)
2.半径向量计算
调用mc_arc()函数进行半径向量计算
float center_axis0 = position[axis_0] + offset[axis_0];
float center_axis1 = position[axis_1] + offset[axis_1];
float r_axis0 = -offset[axis_0]; // 圆心到起点的向量
float r_axis1 = -offset[axis_1];
float rt_axis0 = target[axis_0] - center_axis0; // 圆心到终点的向量
float rt_axis1 = target[axis_1] - center_axis1;
半径坐标求解图
圆心坐标计算:
x c = x p + i y c = y p + j \begin{align*} x_c &= x_p + i \\ y_c &= y_p + j \\ \end{align*} xcyc=xp+i=yp+j
半径向量计算:
r ⃗ = ( − i , − j ) r ⃗ t = ( x t − x c , y t − y c ) \begin{align*} \vec{r} &= (-i, -j) \\ \vec{r}_t &= (x_t - x_c, y_t - y_c) \end{align*} rrt=(−i,−j)=(xt−xc,yt−yc)
3.角度行程计算
求解angular_travel的大小,即圆心指向起点向量与圆心指向终点向量间的夹角
float angular_travel = atan2(r_axis0*rt_axis1 - r_axis1*rt_axis0, r_axis0*rt_axis0 + r_axis1*rt_axis1);
if (is_clockwise_arc) { if (angular_travel >= -EPSILON) angular_travel -= 2*M_PI; // 顺时针补全负角度
} else {if (angular_travel <= EPSILON) angular_travel += 2*M_PI; // 逆时针补全正角度
}
角度行程求解图
反正切函数的加减法公式:
arctan A + arctan B = arctan ( A + B 1 − A B ) arctan A − arctan B = arctan ( A − B 1 + A B ) \begin{align*} \arctan A + \arctan B &= \arctan\left(\frac{A+B}{1-AB}\right) \\ \arctan A - \arctan B &= \arctan\left(\frac{A-B}{1+AB}\right) \end{align*} arctanA+arctanBarctanA−arctanB=arctan(1−ABA+B)=arctan(1+ABA−B)
给定两点:
A ( x 0 , y 0 ) , B ( x 1 , y 1 ) A(x_0,y_0), \quad B(x_1,y_1) A(x0,y0),B(x1,y1)
它们的极角分别为:
∠ A = arctan ( y 0 x 0 ) , ∠ B = arctan ( y 1 x 1 ) \angle A = \arctan\left(\frac{y_0}{x_0}\right), \quad \angle B = \arctan\left(\frac{y_1}{x_1}\right) ∠A=arctan(x0y0),∠B=arctan(x1y1)
根据反正切减法公式,两角之差为:
∠ B − ∠ A = arctan ( y 1 x 1 ) − arctan ( y 0 x 0 ) = arctan ( y 1 x 1 − y 0 x 0 1 + y 1 x 1 ⋅ y 0 x 0 ) (应用反正切减法公式) = arctan ( x 0 y 1 − x 1 y 0 x 0 x 1 + y 0 y 1 ) (分子分母同乘 x 0 x 1 ) \begin{align*} \angle B - \angle A &= \arctan\left(\frac{y_1}{x_1}\right) - \arctan\left(\frac{y_0}{x_0}\right) \\ &= \arctan\left(\frac{\frac{y_1}{x_1} - \frac{y_0}{x_0}}{1 + \frac{y_1}{x_1} \cdot \frac{y_0}{x_0}}\right) \quad \text{(应用反正切减法公式)} \\ &= \arctan\left(\frac{x_0 y_1 - x_1 y_0}{x_0 x_1 + y_0 y_1}\right) \quad \text{(分子分母同乘 $x_0 x_1$)} \end{align*} ∠B−∠A=arctan(x1y1)−arctan(x0y0)=arctan(1+x1y1⋅x0y0x1y1−x0y0)(应用反正切减法公式)=arctan(x0x1+y0y1x0y1−x1y0)(分子分母同乘 x0x1)
4.分段数计算(几何逼近)
将圆弧插补成足够多的小线段,arc_tolerance为圆弧上任意两点连接而成的小线段到圆弧的最大距离arc_tolerance越小,则圆弧微分成的小线段越多,插补精度也越高。
uint16_t segments = floor(fabs(0.5 * angular_travel * radius) / sqrt(settings.arc_tolerance * (2 * radius - settings.arc_tolerance));
数学推导图
弦高误差 at(即 arc_tolerance)与 半弦长 k 的关系:
k = r 2 − ( r − a t ) 2 = a t ( 2 r − a t ) \begin{align*} k &= \sqrt{r^2 - (r - at)^2 }= \sqrt{at(2r - at)} \\ \end{align*} k=r2−(r−at)2=at(2r−at)
总弧长 arc 和分段数 s 的关系:
a r c = r ⋅ ∣ θ ∣ s = a r c 2 k \begin{align*} arc&=r\cdot |\theta| \\ s&=\frac{arc}{2k} \\ \end{align*} arcs=r⋅∣θ∣=2karc
代入后得到
s = a r c 2 k = 0.5 ∣ θ ∣ ⋅ r a t ( 2 r − a t ) \begin{align*} s &= \frac{a r c}{2 k} = \frac{0.5 |\theta| \cdot r}{\sqrt{at(2r - at)}} \\ \end{align*} s=2karc=at(2r−at)0.5∣θ∣⋅r
5.小角度近似优化(泰勒展开)
三角函数的泰勒展开
float theta_per_segment = angular_travel/segments;//每个线段对应的圆心角
// axis_linear,除了圆弧平面之外的第三个轴,即与圆弧平面垂直的轴
float linear_per_segment = (target[axis_linear] - position[axis_linear])/segments;
float cos_T = 2.0 - theta_per_segment * theta_per_segment; // 2 - θ²
// θ*(1 - θ²/6) (sin的三阶泰勒近似)
float sin_T = theta_per_segment * 0.16666667 * (cos_T + 4.0);
cos_T *= 0.5; // → 1 - θ²/2 (cos的二阶泰勒近似)
数学推导图
每个线段对应的圆心角:
θ p = θ n s \begin{align*} \theta_p &= \frac{\theta_n}{s} \end{align*} θp=sθn
泰勒展开式:
s i n x = x − x 3 3 ! + o ( x 3 ) c o s x = 1 − x 2 2 ! + o ( x 2 ) \begin{align*} sin x &= x - \frac{x^3}{3!} + o(x^3) \\ cos x &= 1 - \frac{x^2}{2!} + o(x^2) \end{align*} sinxcosx=x−3!x3+o(x3)=1−2!x2+o(x2)
cosx 公式取前两项,sinx 公式取前三项得:
cos θ p ≈ 1 − θ p 2 2 sin θ p ≈ θ p − θ p 3 6 ≈ 1 6 ⋅ θ p ⋅ ( 2 − θ p 2 + 4 ) \begin{align*} \cos\theta_p &\approx 1 - \frac{\theta_p^2}{2} \\ \sin\theta_p &\approx \theta_p - \frac{\theta_p^3}{6} \approx \frac{1}{6}\cdot\theta_p \cdot(2 - \theta_p^2 +4) \end{align*} cosθpsinθp≈1−2θp2≈θp−6θp3≈61⋅θp⋅(2−θp2+4)
6.位置计算
通过混合近似与精确计算来优化圆弧插补的精度和效率:快速近似法(旋转矩阵增量更新,40μs/次)用于多数计算,而高精度修正(直接三角函数计算,375μs/次)每隔N_ARC_CORRECTION次执行一次,既避免累积误差,又维持整体速度;对于微小圆弧(分段数少),仅用近似计算也能保证误差可控,实现速度与精度的最佳平衡。
float sin_Ti; // 临时存储当前角度的正弦值
float cos_Ti; // 临时存储当前角度的余弦值
float r_axisi; // 旋转后的临时半径向量(用于中间计算)
uint16_t i; // 循环计数器
uint8_t count = 0; // 圆弧修正计数器(控制修正频率)for (i = 1; i < segments; i++) { // 遍历每个线段(共 segments-1 次)// 如果未达到修正间隔(N_ARC_CORRECTION),使用增量旋转矩阵近似计算if (count < N_ARC_CORRECTION) {// 应用旋转矩阵更新半径向量(约 40 微秒/次)r_axisi = r_axis0 * sin_T + r_axis1 * cos_T; // 计算旋转后的新半径分量r_axis0 = r_axis0 * cos_T - r_axis1 * sin_T; // 更新x轴半径分量r_axis1 = r_axisi; // 更新y轴半径分量count++; // 递增修正计数器} // 达到修正间隔时,进行精确的圆弧半径修正(约 375 微秒/次)else {// 通过初始半径向量(=-offset)和变换矩阵计算精确位置cos_Ti = cos(i * theta_per_segment); // 计算当前角度的余弦sin_Ti = sin(i * theta_per_segment); // 计算当前角度的正弦r_axis0 = -offset[axis_0] * cos_Ti + offset[axis_1] * sin_Ti; //精确计算x轴半径分量r_axis1 = -offset[axis_0] * sin_Ti - offset[axis_1] * cos_Ti; //精确计算y轴半径分量count = 0; // 重置修正计数器}// 更新圆弧目标位置坐标position[axis_0] = center_axis0 + r_axis0; // x轴坐标 = 圆心坐标 + x半径分量position[axis_1] = center_axis1 + r_axis1; // y轴坐标 = 圆心坐标 + y半径分量position[axis_linear] += linear_per_segment; // 线性轴(如Z轴)按分段增量移动
}
快速近似法:
通过叠加半径分量得到当前点坐标:
P 0 = { r cos φ = r _ a x i s 0 r sin φ = r _ a x i s 1 \begin{align*} P_0 &= \begin{cases} r \cos \varphi = \mathrm{r\_axis}_0 \\ r \sin \varphi = \mathrm{r\_axis}_1 \end{cases} \\ \end{align*} P0={rcosφ=r_axis0rsinφ=r_axis1
P 1 = { r cos ( φ + θ p ) = r cos φ cos θ p − r sin φ sin θ p = r _ a x i s 0 ⋅ cos θ p − r _ a x i s 1 ⋅ sin θ p r sin ( φ + θ p ) = r sin φ cos θ p + r cos φ sin θ p = r _ a x i s 1 ⋅ cos θ p + r _ a x i s 0 ⋅ sin θ p \begin{align*} P_1 &= \begin{cases} r \cos (\varphi + \theta_p) = r\cos\varphi\cos\theta_p - r\sin\varphi\sin\theta_p = \mathrm{r\_axis}_0 \cdot \cos \theta_p - \mathrm{r\_axis}_1 \cdot \sin \theta_p \\ r \sin (\varphi + \theta_p) = r\sin\varphi\cos\theta_p + r\cos\varphi\sin\theta_p = \mathrm{r\_axis}_1 \cdot \cos \theta_p + \mathrm{r\_axis}_0 \cdot \sin \theta_p \end{cases} \end{align*} P1={rcos(φ+θp)=rcosφcosθp−rsinφsinθp=r_axis0⋅cosθp−r_axis1⋅sinθprsin(φ+θp)=rsinφcosθp+rcosφsinθp=r_axis1⋅cosθp+r_axis0⋅sinθp
P 2 = { r cos ( φ 1 + θ p ) = r cos φ 1 cos θ p − r sin φ 1 sin θ p = r _ a x i s 0 ⋅ cos θ p − r _ a x i s 1 ⋅ sin θ p r sin ( φ 1 + θ p ) = r sin φ 1 cos θ p + r cos φ 1 sin θ p = r _ a x i s 1 ⋅ cos θ p + r _ a x i s 0 ⋅ sin θ p \begin{align*} P_2 &= \begin{cases} r \cos (\varphi_1 + \theta_p) = r\cos\varphi_1\cos\theta_p - r\sin\varphi_1\sin\theta_p = \mathrm{r\_axis}_0 \cdot \cos \theta_p - \mathrm{r\_axis}_1 \cdot \sin \theta_p \\ r \sin (\varphi_1 + \theta_p) = r\sin\varphi_1\cos\theta_p + r\cos\varphi_1\sin\theta_p = \mathrm{r\_axis}_1 \cdot \cos \theta_p + \mathrm{r\_axis}_0 \cdot \sin \theta_p \end{cases} \end{align*} P2={rcos(φ1+θp)=rcosφ1cosθp−rsinφ1sinθp=r_axis0⋅cosθp−r_axis1⋅sinθprsin(φ1+θp)=rsinφ1cosθp+rcosφ1sinθp=r_axis1⋅cosθp+r_axis0⋅sinθp
高精度修正:
每隔N_ARC_CORRECTION次执行一次,既避免累积误差,又维持整体速度
P 0 = { r cos φ = r _ axis 0 = − offset [ axis 0 ] r sin φ = r _ axis 1 = − offset [ axis 1 ] \begin{align*} P_0 &= \begin{cases} r \cos \varphi = r\_{\text{axis}0} = -\text{offset}[\text{axis}_0] \\ r \sin \varphi = r\_{\text{axis}1} = -\text{offset}[\text{axis}_1] \end{cases} \end{align*} P0={rcosφ=r_axis0=−offset[axis0]rsinφ=r_axis1=−offset[axis1]
P i = { r cos ( φ + i θ ) = r cos φ cos i θ − r sin φ sin i θ = − o f f s e t [ a x i s 0 ] ⋅ cos i θ + o f f s e t [ a x i s 1 ] ⋅ sin i θ r sin ( φ + i θ ) = r sin φ cos i θ + r cos φ sin i θ = − o f f s e t [ a x i s 1 ] ⋅ cos i θ − o f f s e t [ a x i s 0 ] ⋅ sin i θ \begin{align*} P_i &= \begin{cases} \begin{aligned} r \cos (\varphi + i\theta) &= r \cos \varphi \cos i\theta - r \sin \varphi \sin i\theta \\ &= -\mathrm{offset}[\mathrm{axis}_0] \cdot \cos i\theta + \mathrm{offset}[\mathrm{axis}_1] \cdot \sin i\theta \\[5pt] r \sin (\varphi + i\theta) &= r \sin \varphi \cos i\theta + r \cos \varphi \sin i\theta \\ &= -\mathrm{offset}[\mathrm{axis}_1] \cdot \cos i\theta - \mathrm{offset}[\mathrm{axis}_0] \cdot \sin i\theta \end{aligned} \end{cases} \end{align*} Pi=⎩ ⎨ ⎧rcos(φ+iθ)rsin(φ+iθ)=rcosφcosiθ−rsinφsiniθ=−offset[axis0]⋅cosiθ+offset[axis1]⋅siniθ=rsinφcosiθ+rcosφsiniθ=−offset[axis1]⋅cosiθ−offset[axis0]⋅siniθ
参考文章
参考CSDN文章:grbl源码解析——圆弧插补
相关文章:
GRBL运动控制算法(二)圆弧插补
前言 GRBL 是一款高性能、开源的嵌入式 CNC(计算机数控)控制器固件,专为 Arduino 平台优化,广泛应用于雕刻机、激光切割机、3D 打印机及其他精密运动控制场景。自 2009 年发布以来,GRBL 凭借其高效的运动规划算法、稳…...
《P1072 [NOIP 2009 提高组] Hankson 的趣味题》
题目描述 Hanks 博士是 BT(Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫 Hankson。现在,刚刚放学回家的 Hankson 正在思考一个有趣的问题。 今天在课堂上,老师讲解了如何求两个正整数 c1 和 c2 的最大公约数…...
矩阵分解中的梯度下降:详细实现方案(包含数学推导、代码实现和优化技巧)
矩阵分解中的梯度下降:详细实现方案(包含数学推导、代码实现和优化技巧) 矩阵分解是机器学习和数据科学中重要的技术,广泛应用于推荐系统、自然语言处理、图像处理等领域。梯度下降作为一种优化算法,在矩阵分解中常用于最小化目标函数以找到最佳的矩阵近似。本指南将详细…...
STM32F103C8T6实现 SG90 360 °电机转动
简介 基于上一篇 STM32F103C8T6实现 SG90 180 电机任意角度转动 本来想实现角度转动, 但靠舵机本身无法实现限位, 需要记录位置, 并且根据转速计算大概位置, 存在误差, 不实现角度转动了, 只实现正反转 代码 正向速度0.75为最大速度, 反向2.25, 接近1.5…...
RTDETR融合[CVPR2025]DnLUT中的MuLUTUnit模块
RT-DETR使用教程: RT-DETR使用教程 RT-DETR改进汇总贴:RT-DETR更新汇总贴 《DnLUT: Ultra-Efficient Color Image Denoising via Channel-Aware Lookup Tables》 一、 模块介绍 论文链接:https://arxiv.org/pdf/2503.15931 代码链接…...
大数据Spark(五十七):Spark运行架构与MapReduce区别
文章目录 Spark运行架构与MapReduce区别 一、Spark运行架构 二、Spark与MapReduce区别 Spark运行架构与MapReduce区别 一、Spark运行架构 Master:Spark集群中资源管理主节点,负责管理Worker节点。Worker:Spark集群中资源管理的从节点,负责任务的运行…...
二:python基础(黑马)
一:了解 1.1: python特点 python是完全面向对象的语言 函数,模块,数字,字符串都是对象,在python中一切皆对象 完全支持继承,重载,多重继承 支持重载运算符,也支持泛型设计 py…...
【马拉车 KMP 差分数组】P6216 回文匹配|省选-
本文涉及知识点 较难理解的字符串查找算法KMP C差分数组 马拉车算法 P6216 回文匹配 题目描述 对于一对字符串 ( s 1 , s 2 ) (s_1,s_2) (s1,s2),若 s 1 s_1 s1 的长度为奇数的子串 ( l , r ) (l,r) (l,r) 满足 ( l , r ) (l,r) (l,r) 是回文的&#…...
C/C++测试框架googletest使用示例
文章目录 文档编译安装示例参考文章 文档 https://github.com/google/googletest https://google.github.io/googletest/ 编译安装 googletest是cmake项目,可以用cmake指令编译 cmake -B build && cmake --build build将编译产物lib和include 两个文件夹…...
提高MCU的效率方法
要提高MCU(微控制器单元)的编程效率,需要从硬件特性、代码优化、算法选择、资源管理等多方面入手。以下是一些关键策略: 1. 硬件相关优化 时钟与频率: 根据需求选择合适的时钟源(内部/外部振荡器),避免过高的时钟频率导致功耗浪费。关闭未使用的外设时钟(如定时器、UA…...
Ansible 实战:Roles,运维的 “魔法函数”
一、介绍 你现在已经学过tasks和handlers,那么,最好的playbook组织方式是什么呢?答案很简单:使用roles!roles基于一种已知的文件结构,能够自动加载特定的vars_files、tasks以及handlers。通过roles对内容进…...
GO简单开发grpc
什么是grpc 首先我们需要了解,什么是grpc gRPC(全称:google remote procedure call)是由Google开发的一个高性能、开源的远程过程调用(RPC)框架。它基于 HTTP/2 协议,并且使用 Protocol Buffer…...
强引用,弱引用,软引用,虚引用,自旋锁,读写锁
强引用:强引用GC不会回收 软引用:内存够的话不回收,内存不够的话回收 弱引用:不管内存够不够,只要有GC就回收 虚引用:点get是null,但是GC后他会把引用放到引用队列里边 自旋锁:是指尝…...
C++异常处理 throw try catch
C 异常处理概述 C 异常处理机制提供了一种在程序运行时捕获错误或异常情况的方式。异常处理的目的是使得程序在遇到错误时能够优雅地终止或恢复,并防止程序出现崩溃。C 使用 try, throw, 和 catch 关键字来实现异常处理。 异常处理的基本结构: throw: …...
优化 Web 性能:管理第三方资源(Third-Party Summary)
在现代 Web 开发中,第三方资源(如分析工具、广告脚本、字体服务)为网站提供了丰富的功能,但也可能成为性能瓶颈。Google 的 Lighthouse 工具在性能审计中提供了“第三方资源概要”(Third-Party Summary)&am…...
第六章、 系统级 I/O
真题考点 考点一:Unix I/O 所有的 I/O 设备(例如网络、磁盘和终端)都被模型化为文件,而所有的输入和输出都被当作对相应文件的读和写来执行。这种将设备优雅地映射为文件的方式,允许 Linux 内核引出一个简单、低级的应用接口,称为…...
Jetpack Compose 自定义标题栏终极指南:从基础到高级实战
Jetpack Compose 自定义标题栏终极指南:从基础到高级实战 本文将带你彻底掌握 Compose 标题栏开发,涵盖 5 种专业级实现方案 性能优化技巧 完整可运行代码。 📚 核心方案对比 方案特点适用场景复杂度基础Row布局完全自定义,灵…...
晶晨S905-S905L-S905LB_S905M2通刷_安卓6.0.1_16S极速开机_线刷固件包
晶晨S905-S905L-S905LB_S905M2通刷_安卓6.0.1_16S极速开机_线刷固件包 线刷方法:(新手参考借鉴一下) 刷机工具版本请用2.2.0以上,导入固件后,刷机工具右侧两个擦除打勾,然后点开始。插上刷机神器…...
tkiner模块的初步学习
文章目录 一、前言二、概念2.1 安装2.2 窗口 三、小部件3.1 概述3.2 常用小部件3.2.1 Label3.2.2 Button3.2.3 Entry3.2.4 Text3.2.5 Listbox3.2.6 Checkbutton3.2.7 Radiobutton3.2.8 Scrollbar 3.3 更多小部件3.3.1 Scale3.3.2 Spinbox3.3.3. Progressbar 3.4 主题小部件 四、…...
Java常用数据结构操作方法全面总结
目录 一、List接口及其实现类二、Set接口及其实现类三、Map接口及其实现类四、Queue/Deque队列五、Stack栈六、树形结构七、注意事项与最佳实践总结 一、List接口及其实现类 核心实现类 ArrayList:基于动态数组LinkedList:基于双向链表 常用操作方法…...
Java的Selenium的特殊元素操作与定位之select下拉框
如果页面元素是一个下拉框,我们可以将此web元素封装为Select对象 Select selectnew Select(WebElement element); Select对象常用api select.getOptions();//获取所有选项select.selectBylndex(index);//根据索引选中对应的元素select.selectByValue(value);//选…...
STM32单片机入门学习——第15节: [6-3] TIM输出比较
写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难,但我还是想去做! 本文写于:2025.04.05 STM32开发板学习——第15节: [6-3] TIM输出比较 前言开发板说明引用解答和科普一…...
力扣经典算法篇-9-跳跃游戏(贪心算法,反向递推)
题干: 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 示例 …...
java面向对象 - 封装、继承和多态
1.封装 定义 封装是把对象的属性和操作(或服务)结合为一个独立的整体,并尽可能隐藏对象的内部实现细节。通过访问控制修饰符(如private、protected、public)对属性和方法的访问进行限制,以此提升代码的安全性与可维护性。 要点 访问控制:运用private修饰属性,防止外部直…...
铁电液晶(FLC)与反铁电液晶(AFLC)
### **铁电液晶(FLC)与反铁电液晶(AFLC)的原理、区别及应用** --- ## **1. 基本原理** ### **(1)铁电液晶(Ferroelectric Liquid Crystal, FLC)** - **分子结构**: …...
经典算法 a^b
原题目链接 问题描述 求 a 的 b 次方对 p 取模的值,即计算: a^b mod p输入格式 输入一行,包含三个整数 a、b 和 p,中间用空格隔开。 输出格式 输出一个整数,表示 a^b mod p 的值。 数据范围 0 ≤ a, b ≤ 10^91 …...
Python解决“组成字符串ku的最大次数”问题
Python解决“组成字符串ku的最大次数”问题 问题描述测试样例解题思路代码 问题描述 给定一个字符串 s,该字符串中只包含英文大小写字母。你需要计算从字符串中最多能组成多少个字符串 “ku”。每次可以随机从字符串中选一个字符,并且选中的字符不能再使…...
ubuntu22使用TrinityCore搭建魔兽世界服务器
目录 一、Ubuntu22工具下载二、服务端编译配置1. 从 git 上拉取服务端代码2. 编译客户端3. 修改配置文件4. 加载sql语句5. 下载客户端6. 下载必要sql文件 三、客户端连接配置四、游戏启动 一、Ubuntu22工具下载 下载所有需要的工具 sudo apt-get update sudo apt-get install…...
LeetCode - 739.每日温度问题单调栈解法
目录 问题描述 方法思路:单调栈 核心思想 为什么用单调栈? 算法步骤 代码实现与逐行解析 示例解析 复杂度分析 总结 问题描述 给定一个整数数组 temperatures,表示每天的温度,返回一个数组 answer,其中 answe…...
GESP:2025-3月等级8-T1-上学
时间限制 : 1 秒 内存限制 : 128 MB C 城可以视为由 n个结点与 m条边组成的无向图。这些结点依次以1,2,....n标号,边依次以 1,2...m标号。第i条边(1<i<m )连接编号为ui 与vi的结点,长度为li米。 小 A 的学校坐落在 C 城中…...
宏碁笔记本电脑擎7PRO搭载的 NVIDIA RTX 5080 显卡安装pytorch
宏碁笔记本电脑擎7PRO搭载的 NVIDIA RTX 5080 显卡是一款高性能移动 GPU,基于 NVIDIA 最新的 Blackwell 架构设计,通过修正架构(Blackwell)、显存类型与带宽(GDDR7、960GB/s)、Tensor Core 与 RT Core 全面…...
Qwen-7B-Chat 本地化部署使用
通义千问 简介 通义千问是阿里云推出的超大规模语言模型,以下是其优缺点: 优点 强大的基础能力:具备语义理解与抽取、闲聊、上下文对话、生成与创作、知识与百科、代码、逻辑与推理、计算、角色扮演等多种能力。可以续写小说、编写邮件、解…...
数据结构,顺序存储线性表
//线性表顺序存储 #include<stdio.h> #include<stdlib.h> #define MAXSIZE 100 #define ElemType int //定义结构体 typedef struct LinearList{ElemType elem[MAXSIZE];int last; }LinearList; //初始化链表 void InitList(LinearList &L){L.last-1; };…...
Matlab轴承故障信号仿真与故障分析
1.摘要 本文介绍了一个基于Matlab的轴承故障信号仿真与分析程序,旨在模拟和分析轴承内圈故障信号的特征。程序首先通过生成故障信号、共振信号和调制信号,添加噪声和离散化处理,构建模拟的振动信号,并保存相关数据。通过快速傅里…...
Git三剑客:工作区、暂存区、版本库深度解析
一、引言:为什么需要理解Git的核心区域? 作为开发者,Git是日常必备的版本控制工具。但你是否曾因以下问题感到困惑? 修改了文件,但 git status 显示一片混乱? git add 和 git commit 到底做了什么&#x…...
stack和queue
1.stack的使用 函数说明接口说明 stack() 构造空的栈 empty 检测stack是否为空 size 返回stack中元素的个数 top 返回栈顶元素的引用 push 将元素val压入stack中 pop 将stack中尾部的元素弹出 void test_stack() {stack<int> st;st.push(1);st.push(2);st.push(3);s…...
【补题】Codeforces Round 1011 (Div. 2) C. Serval and The Formula
题意:给两个数,问你存不存在k使nmn异或m 思路: 为了让nmn异或m成功,很明显有两个数在同一位上最多只能有1个1。因为如果有两个就会导致数字变小,很明显nm是不可能成功的,因为你怎么搞都会有至少一个一模一…...
基于javaweb的SpringBoot汉服文化bbs系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...
Vision_Robot
import time import tkinter as tk from tkinter import messagebox from PIL import Image, ImageTk import socket import threading from datetime import datetime import logging import subprocess # 确保导入 subprocess 库 import os import pyautogu…...
爬虫练习案例
案例1: 爬取菜鸟教程左侧导航栏的分类内容: 在pycharm中书写代码。 先倒入相关模块。 import requests from bs4 import BeautifulSoup import lxml.etree as le这个案例写两种写法。 第一种: urlhttps://www.runoob.com/html/html-tuto…...
大数据时代的隐私保护:区块链技术的创新应用
一、引言 在当今数字化时代,大数据已经成为推动社会发展的关键力量。从商业决策到社会治理,从医疗健康到金融服务,数据的价值日益凸显。然而,随着数据的大量收集和广泛使用,隐私保护问题也日益突出。如何在充分利用大…...
力扣刷题-热题100题-第31题(c++、python)
25. K 个一组翻转链表 - 力扣(LeetCode)https://leetcode.cn/problems/reverse-nodes-in-k-group/?envTypestudy-plan-v2&envIdtop-100-liked 常规模拟 根据翻转的长度找到头和尾,进入函数进行翻转 主程序里有循环不断找到头和尾并拼…...
(四)数据检索与增强生成——让对话系统更智能、更高效
上一篇:(三)链式工作流构建——打造智能对话的强大引擎 在前三个阶段,我们已经搭建了一个基础的智能对话,并深入探讨了输入输出处理和链式工作流构建的细节。今天,我们将进入智能对话系统的高级阶段——数…...
Turtle图形化编程知识点汇总:让编程更有趣
友情提示:本文内容由银河易创AI(https://ai.eaigx.com)创作平台gpt-4-turbo模型生成,仅供参考! 在学习编程的过程中,许多初学者会接触到Python的turtle图形库,它是一种图形化编程工具,通过简单的…...
Social GAN(CVPR2018)
文章目录 AbstractIntroductionRelated WorkHuman-Human InteractionRNNs for Sequence PredictionGenerative Modeling MethodProblem DefinitionGenerative Adversarial NetworksSocially-Aware GANPooling ModuleEncouraging Diverse Sample Generation Conclusion paper Ab…...
0201线性回归-机器学习-人工智能
文章目录 1 程序目标2 代码实现3 关键步骤解释4 示例输出5 注意事项结语 以下是一个使用 scikit-learn、pandas和 matplotlib 实现线性回归的完整程序示例。程序包含数据加载、模型训练、预测和可视化。 1 程序目标 加载数据(使用 pandas)数据预处理&am…...
2-Visual Studio 2022 NET开发Windows桌面软件并连接SQL Server数据库
引言 今天尝试Visual Studio 2022 NET开发一个NET桌面软件,并尝试连接SQL Server的数据库,此文章为开发笔记。 --------------------------------------------------------------------------------------------------------------------------------- …...
OpenGL学习笔记(简介、三角形、着色器、纹理、坐标系统、摄像机)
目录 简介核心模式与立即渲染模式状态机对象GLFW和GLAD Hello OpenGLTriangle 三角形顶点缓冲对象 VBO顶点数组对象 VAO元素缓冲对象 EBO/ 索引缓冲对象 IEO 着色器GLSL数据类型输入输出Uniform 纹理纹理过滤Mipmap 多级渐远纹理实际使用方式纹理单元 坐标系统裁剪空间 摄像机自…...
第二十九章:Python-mahotas库:图像处理的高效工具
一、mahotas库简介 mahotas是一个功能强大的Python图像处理库,提供了丰富的图像处理算法和工具,包括图像分割、特征提取、滤波、形态学操作等。它以简洁的API和高效的性能著称,特别适合处理大型图像。资源绑定附上完整资料供读者参考学习&…...
【网络安全】 防火墙技术
防火墙是网络安全防御的重要组成部分,它的主要任务是阻止或限制不安全的网络通信。在这篇文章中,我们将详细介绍防火墙的工作原理,类型以及如何配置和使用防火墙。我们将尽可能使用简单的语言和实例,以便于初学者理解。 一、什么…...