Ubuntu 22.04下Eigen3、Ipopt与ifopt非线性优化环境完整配置指南
1. 项目概述与背景最近在折腾一个机器人轨迹优化的项目需要用到非线性优化求解器。IpoptInterior Point OPTimizer是开源领域里处理这类问题的“瑞士军刀”而ifopt则是一个优秀的C接口库能让你用Eigen矩阵这种更现代、更舒服的方式来定义问题。但说实话在Linux特别是像Ubuntu 22.04 LTS这样的新系统上把它们俩连同Eigen3一起配通过程里的小坑还真不少。官方文档往往只给个骨架很多依赖和编译选项的细节都得自己踩一遍才能摸清楚。这篇文章我就以Ubuntu 22.04为例手把手带你走一遍从零开始配置Eigen3、编译安装Ipopt、再到安装ifopt的全过程。目标很明确搭建一个稳定、可用于实际C项目开发的非线性优化环境。我会把重点放在那些容易出错的地方比如第三方依赖的版本选择、编译参数的调整、以及最后如何在自己的CMake项目中正确链接它们。无论你是做机器人、控制理论还是运筹学相关的研究与开发这套环境都是非常基础且强大的工具链。2. 环境准备与核心依赖解析2.1 系统基础环境确认首先确保你的Ubuntu 22.04系统是最新的。打开终端执行更新操作是一个好习惯sudo apt update sudo apt upgrade -y接下来我们需要安装一系列编译工具和基础库。这些是后续从源码编译Ipopt所必需的。以下命令会安装编译器、构建工具、版本控制工具以及一些通用的数学库sudo apt install -y build-essential gcc g gfortran git cmake pkg-config curl wget sudo apt install -y libblas-dev liblapack-dev libgsl-dev这里解释一下几个关键包build-essential, gcc, g, gfortran: 提供了C、C和Fortran编译器。Ipopt的部分底层依赖如线性求解器是用Fortran写的所以gfortran必不可少。cmake, pkg-config: 现代开源项目广泛使用的构建和配置工具ifopt和许多依赖库都使用CMake。libblas-dev, liblapack-dev: 线性代数计算的基础库。几乎所有数值计算软件都依赖于它们。安装开发版-dev才能获取头文件和链接库。libgsl-dev: GNU科学计算库。虽然不是Ipopt的核心强制依赖但一些辅助工具或测试用例可能会用到预先安装可以避免后续潜在问题。注意Ubuntu的包管理器apt安装的库通常是稳定版但版本可能不是最新的。对于科研或追求最新特性的开发有时需要从源码编译更新版本的依赖。我们这里以保证系统稳定和便捷为首要目标。2.2 Eigen3 安装与验证Eigen是一个纯头文件的C模板库这意味着安装它非常简单不需要编译。我们直接从官方源安装即可sudo apt install -y libeigen3-dev安装完成后如何验证你可以检查头文件位置并写一个简单的程序测试。查找头文件路径dpkg -L libeigen3-dev | grep -E /usr/include/eigen3$|/usr/lib/cmake/eigen3通常头文件会在/usr/include/eigen3而CMake配置文件会在/usr/lib/cmake/eigen3。编写测试程序创建一个文件test_eigen.cpp。#include iostream #include Eigen/Dense int main() { Eigen::MatrixXd A(2, 2); A 1, 2, 3, 4; Eigen::VectorXd b(2); b 5, 6; Eigen::VectorXd x A.colPivHouseholderQr().solve(b); std::cout Solution x \n x std::endl; return 0; }编译并运行g -I /usr/include/eigen3 test_eigen.cpp -o test_eigen ./test_eigen如果成功输出解向量x例如[-4, 4.5]的转置说明Eigen3安装成功。实操心得Eigen是头文件库在你的项目CMakeLists.txt中通常使用find_package(Eigen3 REQUIRED)和target_link_libraries(your_target Eigen3::Eigen)来链接。注意这里“链接”的只是一个导入的目标imported target它主要帮我们处理好包含路径include directories。3. Ipopt 求解器源码编译指南Ipopt的安装是整个过程里最复杂的一步因为它有多个第三方依赖并且编译选项众多。我们选择从源码编译以获得最大的灵活性和对系统的适配性。3.1 获取源码与第三方依赖Ipopt的源码托管在GitHub上。我们直接克隆稳定版本。同时Ipopt编译需要三个关键的第三方依赖ASL用于解析AMPL模型语言、HSL线性方程组求解器集合、和MUMPS另一个线性求解器。由于HSL是商业库对于开源用户我们通常使用MUMPS。# 1. 创建并进入一个工作目录 mkdir ~/ipopt_install cd ~/ipopt_install # 2. 克隆Ipopt源码 git clone https://github.com/coin-or/Ipopt.git cd Ipopt # 3. 下载第三方依赖脚本 ./scripts/get.Mumps ./scripts.get.ASL # 注意HSL需要单独申请这里我们略过使用MUMPS即可。 # ./scripts/get.HSL # 通常不执行这一条执行get.Mumps和get.ASL脚本后会在ThirdParty目录下下载并解压对应的源码。3.2 编译配置与关键参数解读Ipopt推荐使用build目录进行外部构建out-of-source build。我们先安装一些MUMPS可能需要的额外依赖sudo apt install -y libopenblas-dev libscotch-dev libmetis-devlibopenblas-dev: 提供优化的BLAS库比基础libblas-dev性能更好。libscotch-dev,libmetis-dev: 为MUMPS提供矩阵排序和分区库对于求解大规模稀疏矩阵问题至关重要能显著提升性能和稳定性。现在开始配置编译cd ~/ipopt_install/Ipopt mkdir build cd build # 运行configure脚本这里有几个关键选项 ../configure \ --prefix/usr/local \ # 安装路径设为/usr/local方便系统级调用 --with-openblas \ # 使用OpenBLAS代替默认BLAS性能更优 --with-mumps \ # 启用MUMPS线性求解器 --with-metis \ # 启用METIS排序库 --with-scotch \ # 启用Scotch排序库 --disable-shared \ # 不生成动态库只生成静态库。避免运行时库路径问题更稳定。 --enable-static \ # 生成静态库 CXXFLAGS-O3 -pipe # 优化编译选项关键参数解析--prefix/usr/local指定安装目录。安装后头文件会在/usr/local/include/coin库文件在/usr/local/lib。你需要确保/usr/local/lib在你的系统库路径中通常默认已在。--with-openblas强烈建议使用。OpenBLAS对多核CPU进行了大量优化能极大加速线性代数运算这是整个求解器最耗时的部分之一。--disable-shared --enable-static生成静态库.a文件。这样做的好处是你最终编译的可执行文件是自包含的分发时不需要担心目标机器上是否有特定版本的Ipopt动态库。缺点是文件体积会变大。对于学术研究和内部工具静态链接更省心。CXXFLAGS-O3 -pipe-O3是最高级别的编译器优化会牺牲一些编译时间换取运行速度。-pipe在编译过程中使用管道而非临时文件有时能加快编译速度。运行configure脚本后请仔细查看输出结尾。它会汇总所有检测到的功能和库。确保你关心的部分如MUMPS, OpenBLAS, Metis显示为yes。3.3 编译、测试与安装配置成功后就可以开始编译了。这个过程比较耗时取决于你的CPU核心数。# 使用所有可用的CPU核心进行并行编译显著缩短时间 make -j$(nproc) # 编译完成后运行自带的测试用例可选但推荐 make test # 如果测试通过使用sudo权限安装到系统目录 sudo make install安装完成后进行验证# 验证ipopt可执行文件是否在PATH中 which ipopt # 应该输出 /usr/local/bin/ipopt # 查看链接库是否安装成功 ls /usr/local/lib | grep ipopt # 应该能看到 libipopt.a 等静态库文件踩坑记录编译过程中最常见的错误是依赖库找不到。如果configure阶段报错请根据错误信息检查对应的开发包是否已安装例如报错libopenblas找不到可能需要检查libopenblas-dev是否安装正确。另一个常见问题是内存不足尤其是在-j参数值设得过高时如果编译进程被杀死Killed请减少并行任务数例如使用make -j2。4. ifopt 接口库的安装与集成ifopt是一个轻量级的C库它用Eigen类型作为变量和约束的容器并提供了向Ipopt描述问题的清晰接口。相比直接使用Ipopt的C接口ifopt的代码可读性和易用性要高得多。4.1 通过源码编译安装 ifoptifopt同样使用CMake构建。我们先安装它的一些额外依赖sudo apt install -y libboost-all-devBoost库为ifopt提供了程序选项解析等功能。接下来从GitHub克隆并编译ifopt# 回到工作目录或新建一个 cd ~/ipopt_install git clone https://github.com/ethz-adrl/ifopt.git cd ifopt # 创建构建目录并配置 mkdir build cd build cmake .. \ -DCMAKE_BUILD_TYPERelease \ -DCMAKE_INSTALL_PREFIX/usr/local # 编译并安装 make -j$(nproc) sudo make installCMake会自动寻找我们已经安装好的Ipopt和Eigen3。如果一切顺利ifopt的头文件和库文件也会被安装到/usr/local目录下。4.2 验证安装与一个简单示例为了验证整个工具链Eigen3, Ipopt, ifopt是否协同工作我们来创建一个经典的“求解二次规划”示例。创建项目文件结构~/test_ifopt/ ├── CMakeLists.txt └── src/ └── main.cpp编写CMakeLists.txtcmake_minimum_required(VERSION 3.10) project(TestIfopt) # 寻找必需的包 find_package(Eigen3 REQUIRED) find_package(ifopt REQUIRED) # Ipopt 通常通过 ifopt 间接链接但显式声明也无妨 # find_package(Ipopt REQUIRED) # 如果ifopt的Find脚本没处理好可能需要这个 # 设置C标准 set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 添加可执行文件 add_executable(test_qp src/main.cpp) # 链接库 target_link_libraries(test_qp ifopt::ifopt_core # ${IPOPT_LIBRARIES} # 如果上面显式find了Ipopt这里需要链接 ) # Eigen是头文件库通过目标属性包含路径 target_link_libraries(test_qp Eigen3::Eigen)编写一个简单的二次规划问题main.cpp#include ifopt/ipopt_solver.h #include ifopt/problem.h #include ifopt/constraint_set.h #include ifopt/cost_term.h #include Eigen/Dense using namespace ifopt; // 1. 定义成本项 class QuadraticCost : public CostTerm { public: QuadraticCost() : CostTerm(quadratic_cost) {} double GetCost() const override { Eigen::VectorXd x GetVariables()-GetComponent(var_set)-GetValues(); return x(0)*x(0) x(1)*x(1); // 最小化 x1^2 x2^2 } void FillJacobianBlock (std::string var_set, Jacobian jac) const override { if (var_set var_set) { Eigen::VectorXd x GetVariables()-GetComponent(var_set)-GetValues(); jac.coeffRef(0, 0) 2.0 * x(0); // dCost/dx1 jac.coeffRef(0, 1) 2.0 * x(1); // dCost/dx2 } } }; // 2. 定义约束项 class LinearConstraint : public ConstraintSet { public: LinearConstraint() : ConstraintSet(1, linear_constraint) {} Eigen::VectorXd GetValues() const override { Eigen::VectorXd x GetVariables()-GetComponent(var_set)-GetValues(); Eigen::VectorXd g(1); g(0) x(0) x(1) - 1.0; // 约束: x1 x2 1 return g; } Eigen::VectorXd GetBounds() const override { Eigen::VectorXd bounds(GetRows()); bounds(0) 0.0; // 等式约束的下界 bounds(1) 0.0; // 等式约束的上界 return bounds; } void FillJacobianBlock (std::string var_set, Jacobian jac) const override { if (var_set var_set) { jac.coeffRef(0, 0) 1.0; // dg/dx1 jac.coeffRef(0, 1) 1.0; // dg/dx2 } } }; int main() { // 3. 定义变量初始猜测值 VariablePtrVec variables; Eigen::Vector2d x_init(0.5, 0.5); auto var_set std::make_sharedVariable(2, var_set); var_set-SetValues(x_init); variables.push_back(var_set); // 4. 构建问题 Problem nlp; nlp.AddVariableSet(variables); nlp.AddCostSet(std::make_sharedQuadraticCost()); nlp.AddConstraintSet(std::make_sharedLinearConstraint()); // 5. 配置并运行求解器 IpoptSolver ipopt; ipopt.SetOption(linear_solver, mumps); // 使用我们编译的MUMPS求解器 ipopt.SetOption(jacobian_approximation, exact); // 使用精确雅可比 ipopt.SetOption(print_level, 5); // 输出详细程度 ipopt.Solve(nlp); // 6. 输出结果 Eigen::VectorXd x_opt nlp.GetOptVariables()-GetValues(); std::cout Optimal solution found: x1 x_opt(0) , x2 x_opt(1) std::endl; std::cout Cost at optimum: nlp.GetCost() std::endl; return 0; }编译与运行cd ~/test_ifopt mkdir build cd build cmake .. make ./test_qp如果配置一切正确程序应该能成功求解并输出近似解x1 0.5, x2 0.5成本为0.5。控制台会打印出Ipopt详细的迭代日志。5. 常见问题排查与性能调优即便按照步骤操作也可能会遇到各种问题。这里汇总了一些典型问题及其解决方法。5.1 编译与链接阶段错误问题现象可能原因解决方案configure失败提示缺少lapack/blas开发包未安装或版本冲突。运行sudo apt install libopenblas-dev liblapack-dev。如果已安装尝试--with-blas...和--with-lapack...参数显式指定库路径。make编译 Ipopt 时大量undefined reference错误。依赖库的链接顺序不对或静态库缺失。确保在编译Ipopt时--disable-shared --enable-static已设置。如果是链接自己的程序时出错请确保CMakeLists.txt中链接了所有必要的静态库顺序很重要ifopt - Ipopt - 其他数学库。CMake 找不到FindIpopt.cmake或Findifopt.cmake。ifopt 或自定义的Find模块未正确安装。将ifopt安装到系统目录/usr/local后其CMake配置文件通常会自动被找到。如果不行可以手动设置Ipopt_DIR或ifopt_DIR变量指向其lib/cmake子目录。运行程序时报错error while loading shared libraries: libipopt.so.1: cannot open shared object file动态库路径未在系统查找范围内。因为我们编译的是静态库理论上不应出现此问题。如果编译了动态库需要将/usr/local/lib添加到/etc/ld.so.conf或LD_LIBRARY_PATH环境变量并运行sudo ldconfig。更推荐静态链接。5.2 运行时求解失败与调优程序能编译运行但Ipopt求解失败或结果不理想。初始猜测值Initial Guess至关重要非线性优化对初始值非常敏感。一个糟糕的初始猜测可能导致求解器收敛到局部最优解甚至直接失败。尽量提供一个物理或数学意义上合理的初始值。检查约束的可行性确保你定义的约束本身不是矛盾的例如同时要求x 5和x 3。在设置初始猜测时也尽量让其满足约束至少是可行的。调整求解器选项在代码中通过IpoptSolver::SetOption进行调整。tol收敛容差。默认是1e-8对于某些问题可能太严格可以适当放宽到1e-6。max_iter最大迭代次数。如果求解器因迭代次数过多而停止可以适当增加此值。mu_strategy和mu_init内点法的屏障参数策略和初始值。对于数值困难的问题尝试adaptive策略。linear_solver我们编译时集成了MUMPS所以用mumps。如果问题规模很大且结构化可以研究使用HSL需申请或Pardiso商业等求解器性能可能更好。print_level设置为5或更高可以输出详细的迭代信息帮助诊断问题所在。缩放问题Scaling如果变量和约束的数值量级差异巨大例如一个变量是位置米级另一个是角度弧度制会导致数值计算困难。理想情况下应让所有变量和约束的量级都在1附近。Ipopt有自动缩放功能nlp_scaling_method选项但对于复杂问题手动缩放更可靠。5.3 在大型项目中的集成建议当你在一个大型的CMake项目中使用这套工具链时管理依赖的最佳实践是使用find_package正如示例所示优先使用CMake的find_package。对于Eigen3和ifopt这通常能直接工作。对于Ipoptifopt的Find模块通常会处理好。提供备用路径为了团队协作或CI/CD环境的便利可以在CMakeLists.txt中提供查找本地编译库的备选路径。# 先尝试系统查找 find_package(ifopt REQUIRED) if(NOT ifopt_FOUND) # 如果没找到尝试指定本地编译的路径 set(ifopt_DIR /path/to/your/ifopt/build/install/lib/cmake/ifopt) find_package(ifopt REQUIRED) endif()静态链接与可移植性由于我们编译的是静态库最终的可执行文件是独立的。这极大简化了部署。确保在编译你的项目时链接了所有必要的静态库如libipopt.a,libcoinasl.a,libcoinmumps.a等这些依赖关系可以通过查看ifopt的CMake文件或链接错误信息来逐步添加。整个配置过程虽然步骤不少但一旦搭建完成你就拥有了一个强大的、可用于解决复杂非线性优化问题的本地开发环境。从简单的轨迹规划到复杂的模型预测控制这套基于Eigen、Ipopt和ifopt的工具链都能提供坚实的数值计算基础。

相关新闻

AR3D-R1:强化学习驱动的3D生成技术突破

AR3D-R1:强化学习驱动的3D生成技术突破

1. AR3D-R1:强化学习在3D生成领域的革命性突破最近,一个名为AR3D-R1的模型在3D生成领域引起了广泛关注。这个由上海人工智能实验室、西北工业大学等多家机构联合研发的模型,首次将强化学习(RL)系统性地应用于文本到3D生…

2026/10/15 21:28:35 阅读更多 →
联盟营销传播价值评估与DNTS预测框架解析

联盟营销传播价值评估与DNTS预测框架解析

1. 联盟营销中的传播价值评估困境在当今数字营销领域,联盟营销(Affiliate Marketing)已成为连接商家、推广者和消费者的重要桥梁。作为一名长期关注营销技术发展的从业者,我深刻理解准确评估推广者价值对整个生态健康运转的重要性…

2026/10/15 2:39:11 阅读更多 →
为什么这款免费开源图片查看器能彻底改变你的工作流:5个关键理由

为什么这款免费开源图片查看器能彻底改变你的工作流:5个关键理由

为什么这款免费开源图片查看器能彻底改变你的工作流:5个关键理由 【免费下载链接】ImageGlass 🏞 A fast, open-source, modern image viewer for 90 formats – including WEBP, GIF, SVG, AVIF, JXL, HEIC and more – built for smooth browsing acro…

2026/10/8 17:46:53 阅读更多 →

最新新闻

AI PPT实战:从指令到专业级演示文稿的完整流程与检查清单

AI PPT实战:从指令到专业级演示文稿的完整流程与检查清单

周一晚上十一点,我临时接到一个任务:第二天一早要给团队内部分享一份关于智能家居市场趋势的演示材料。说实在的,以前这种活我一般要预留一个晚上慢慢磨——先想框架,再抠措辞,然后花大量时间调版式、换配色、找图标&a…

2026/10/16 14:46:53 阅读更多 →
BrowserSkill:面向AI时代的浏览器CLI自动化工具

BrowserSkill:面向AI时代的浏览器CLI自动化工具

1. 项目概述:BrowserSkill 是什么,它解决的到底是什么问题?BrowserSkill 这个名字乍一听像某个浏览器插件或 Chrome 扩展,但结合热词中反复出现的bsk、CLI、Chrome、Edge,以及与codex cli、zcode cli、trae cli、devec…

2026/10/16 14:46:53 阅读更多 →
插件系统原理与排障:从Qt平台插件到failed to load plugins实战

插件系统原理与排障:从Qt平台插件到failed to load plugins实战

1. 插件系统:知识工作者的效率杠杆点knowledge-work-plugins 这个名字听起来有点大,但它解决的问题非常具体:一个做知识工作的人,手头少说也有七八种工具——代码编辑器、IDE、笔记软件、命令行终端、文档生成器、绘图工具&#x…

2026/10/16 14:46:53 阅读更多 →
BrowserSkill:用CLI给AI agent装上浏览器操作能力

BrowserSkill:用CLI给AI agent装上浏览器操作能力

1. 从"浏览器自动化"到"给AI装一双手":BrowserSkill到底在解决什么浏览器自动化这件事,做了十几年了。从最早的 Selenium 驱动 WebDriver,到后来的 Puppeteer、Playwright,工具一直在进化,但核心矛…

2026/10/16 14:46:53 阅读更多 →
虚幻引擎角色加速系统:从物理参数到感知体验的完整实现

虚幻引擎角色加速系统:从物理参数到感知体验的完整实现

1. 项目概述:这不是“按住Shift就跑得快”的简单开关在虚幻引擎里做角色移动,很多人卡在第一个坑:明明蓝图里连好了“Add Movement Input”,也设置了“Max Walk Speed”,可角色一加速就飘、一转向就滑、一上坡就原地踏…

2026/10/16 14:46:53 阅读更多 →
STC8G I2C从模式代码调试指南:中断不进、数据错位排查与实战

STC8G I2C从模式代码调试指南:中断不进、数据错位排查与实战

简介:这份资源面向使用STC8G系列单片机进行嵌入式开发的工程师与学习者,聚焦I2C总线从模式的中断编程实践,帮助解决从机响应主机请求、数据收发与错误处理等典型问题。压缩包内共1个文件,为一份C语言源码,整体约1KB&am…

2026/10/16 14:45:52 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →