2023每日积累Q3

0712

  1. 关于如何配置log头文件
  • 头文件的撰写
#define LI_LOG_INFO_STREAM(args)                  \
    do {                                          \
        std::ostringstream ostr;                  \
        ostr << FILE_LINE << " " << args;         \
        FormatLiLog::LogInfo(ostr.str().c_str()); \
        ostr.str("");                             \
    } while (0);

这是一个宏定义,用于实现日志信息的打印和记录。

具体含义如下:

  • LI_LOG_INFO_STREAM(args) 是宏的名称,你可以通过调用该宏来输出日志信息。
  • 宏定义使用了 do { ... } while (0) 结构,这是为了确保宏在使用时表现得像单个语句,避免出现错误。这种技巧通常被称为“do-while 零次循环”或“封装技巧”。
  • 在宏的定义中,首先创建了一个 std::ostringstream 对象 ostr,它用于构建日志信息。
  • << 运算符用于将文件名、行号和传递给宏的参数(args)连接起来,并将结果写入到 ostr 中。
  • 接下来,使用 FormatLiLog::LogInfo() 函数将 ostr.str().c_str() 转换为 C 风格字符串并打印输出。
  • 最后,清空 ostr 的内容以便下一条日志的构建和记录。

通过调用 LI_LOG_INFO_STREAM(args) 宏,你可以将指定的信息与文件名和行号一起记录在日志中,方便进行调试和问题追踪。

  • 函数接收可变参数
    函数是可以接受 (FMT, ...) 作为形参的。这种形式的参数通常用于实现可变参数函数。

在 C++ 中,可变参数函数可以使用 std::va_liststd::va_startstd::va_argstd::va_end 等宏和函数来处理可变参数列表。这些是 C 标准库中的功能,在 C++ 中也可用。

以下是一个示例,展示了如何使用 (FMT, ...) 形参来定义一个可变参数函数:

#include <cstdarg>
#include <iostream>

void printFormatted(const char* format, ...) {
    std::va_list args;
    va_start(args, format);

    // 使用 va_arg 处理可变参数
    while (*format != '\0') {
        if (*format == '%') {
            if (*(format + 1) == 'd') {
                int value = va_arg(args, int);
                std::cout << value << " ";
                format += 2;
                continue;
            }
            // 处理其他类型的参数
        }
        std::cout << *format;
        ++format;
    }

    va_end(args);
}

int main() {
    printFormatted("The values are: %d, %d, %d", 10, 20, 30);
    return 0;
}

在上面的例子中,我们定义了一个名为 printFormatted 的函数,它接受一个格式化字符串和可变参数列表。通过使用 std::va_list 和相关的宏和函数,我们可以在函数内部对可变参数进行处理和打印。

Tips

  1. 请注意,可变参数函数需要处理不同类型的参数时,需要根据具体的需求进行相应的类型检查和类型转换。
  2. #define FMT_HEADER_ONLY 是一个宏定义,用于启用 fmt 库的头文件实现。通过定义此宏,可以将 fmt 库的函数和实现直接嵌入到编译单元中,而无需链接 fmt 库。spdlog的使用时需要注意

0717

  1. 李群视角下如何推导旋转矩阵的中值积分?
    y n + 1 = y n + Δ t ⋅ k n k n = y ′ ( t + 1 2 Δ t ) R ′ ( t ) = R ( t ) w ∧ R ( t + 1 2 Δ t ) = R ( t ) e x p ( w ∧ 1 2 Δ t ) R ′ ( t + 1 2 Δ t ) = R ( t + 1 2 Δ t ) w ∧ = R ( t ) e x p ( w ∧ 1 2 Δ t ) ⋅ w ∧ R ( t + Δ t ) = R ( t ) + R ′ ( t + 1 2 Δ t ) ⋅ Δ t = R ( t ) + R ( t + 1 2 Δ t ) w ∧ Δ t = R ( t ) + R ( t ) e x p ( w ∧ 1 2 Δ t ) ⋅ w ∧ Δ t \begin{align} y_{n+1} & = y_n + \Delta{t} \cdot k_n \\ k_n & = y^{'}(t+\frac{1}{2}\Delta{t}) \\ R^{'}(t) & = R(t)w^{\wedge} \\ R(t+\frac{1}{2}\Delta{t}) & = R(t)exp(w^{\wedge}\frac{1}{2}\Delta{t}) \\ R^{'}(t+\frac{1}{2}\Delta{t}) & = R(t+\frac{1}{2}\Delta{t})w^{\wedge} \\ &= R(t)exp(w^{\wedge}\frac{1}{2}\Delta{t}) \cdot w^{\wedge}\\ R(t+\Delta{t}) &= R(t) + R^{'}(t+\frac{1}{2}\Delta{t}) \cdot \Delta{t} \\ &=R(t) + R(t+\frac{1}{2}\Delta{t})w^{\wedge} \Delta{t} \\ &=R(t) + R(t)exp(w^{\wedge}\frac{1}{2}\Delta{t}) \cdot w^{\wedge}\Delta{t} \\ \end{align} yn+1knR(t)R(t+21Δt)R(t+21Δt)R(t+Δt)=yn+Δtkn=y(t+21Δt)=R(t)w=R(t)exp(w21Δt)=R(t+21Δt)w=R(t)exp(w21Δt)w=R(t)+R(t+21Δt)Δt=R(t)+R(t+21Δt)wΔt=R(t)+R(t)exp(w21Δt)wΔt

最终结果
R ( t + Δ t ) = R ( t ) ⋅ E x p ( w t + w t + Δ t 2 ⋅ Δ t ) \begin{align} R(t+\Delta{t}) &= R(t) \cdot Exp(\frac{w_{t}+w_{t+\Delta{t}}}{2}\cdot \Delta{t}) \end{align} R(t+Δt)=R(t)Exp(2wt+wt+ΔtΔt)

0719

  1. 在声明函数时有override可以不用再添加virual

0721

  1. 如果使用了 spdlog::basic_file_sink 作为日志记录器的输出目标,并且程序非正常结束(例如崩溃或被强制终止),则未刷新的日志可能不会被写入文件。这是因为默认情况下,spdlog::basic_file_sink 在析构函数中进行日志文件的刷新操作。
    如果希望在程序非正常结束时也能保证将未刷新的日志写入文件,可以使用 spdlog::flush_on() 函数来设置日志记录器的刷新策略。例如,可以使用以下代码:
spdlog::flush_on(spdlog::level::err); // 设置在错误级别日志之前刷新

这样,在程序遇到错误级别的日志消息之前,就会强制执行刷新操作,确保日志被写入文件。
另外,请确保你在程序的适当位置调用了 spdlog::shutdown() 函数,以确保所有日志都被正确地刷新和关闭。

spdlog::shutdown(); // 在程序结束前调用,确保所有日志刷新和关闭

通过这些措施,可以尽量保证在程序非正常结束时也能将未刷新的日志写入文件。

0724

  1. aligned_allocator的试用
    STL容器中试用eigen变量,不用内存分配器就会报段错误。

0725

  1. EIGEN_MAKE_ALIGNED_OPERATOR_NEW的使用:EIGEN_MAKE_ALIGNED_OPERATOR_NEW是Eigen库中的一个宏,用于在自定义的Eigen类中重载operator newoperator delete,以确保内存对齐。
    当使用该宏时,它会在类的声明中插入必要的代码,允许该类使用Eigen所需的内存对齐方式进行动态内存分配。这对于需要使用Eigen的动态大小矩阵或向量的自定义类非常有用。
    请注意,在使用EIGEN_MAKE_ALIGNED_OPERATOR_NEW之前,你需要包含Eigen库的Core.h,并确保已经正确设置了编译环境以支持对齐操作。

0802

  1. 点云bin转换
#!/usr/bin/python3

import struct
import os
import sys
import numpy as np
from plyfile import PlyData, PlyElement

if len(sys.argv) < 2:
    print('Usage:\n   ' + 'python3 ' + os.path.basename(sys.argv[0]) + ' ' + '<point_cloud.bin>')
    exit(1)

bytes = open(sys.argv[1], "rb").read()

txt_name = os.path.realpath(sys.argv[1]).replace('.bin', '.txt')
ply_name = os.path.realpath(sys.argv[1]).replace('.bin', '.ply')

point_size = 4 * 3 + 2

assert len(bytes) % point_size == 0

pt_count = len(bytes) / point_size
points = []
with open(txt_name, "w") as file:
  for pi in range(int(pt_count)):
    start = pi * point_size
    end = (pi + 1) * point_size
    pt_bytes = bytes[start:end]
    data = struct.unpack("fffBb", pt_bytes)
    # data = list(data)
    # data[0] = data[0]+0.2
    # data = tuple(data)
    # print(data)
    file.write(f"{data[0]},{data[1]},{data[2]},{data[3]}\n")
    points.append([data[0], data[1],data[2], data[3]])

pc = list(map(tuple, points))
pc = np.array(pc, dtype=[('x', 'f4'),
                         ('y', 'f4'),
                         ('z', 'f4'),
                         ('intensity', 'uint8')])
el = PlyElement.describe(pc, "vertex")
PlyData([el]).write(ply_name)

0809

  1. spdlog格式控制
    • spdlog::warn("Easy padding in numbers like {:08d}", 12);
      这条日志记录使用了格式化字符串,将数字12填充为8位,不足的部分用0补齐。使用 {} 来指定需要进行格式化的内容,其中 :08d 表示将第一个参数(12)格式化为8位带有前导0的十进制数。

    • spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
      这条日志记录使用了多种格式化选项,将同一个参数(42)分别格式化为十进制、十六进制、八进制和二进制表示。{0:d} 表示将第一个参数(42)格式化为十进制,{0:x} 表示格式化为十六进制,{0:o} 表示格式化为八进制,{0:b} 表示格式化为二进制。

    • spdlog::info("Support for floats {:03.2f}", 1.23456);
      这条日志记录将浮点数 1.23456 格式化为只保留两位小数,并将结果用总宽度为3的字段进行填充。

    • spdlog::info("Positional args are {1} {0}..", "too", "supported");
      这条日志记录使用了位置参数,将 “too” 和 “supported” 分别填充到 {1}{0} 的位置。

    • spdlog::info("{:<30}", "left aligned");
      这条日志记录使用了对齐选项,将字符串 “left aligned” 左对齐,并使用30个字符的宽度进行填充
      通过使用这些格式化选项,你可以更方便地在日志中输出各种不同类型和格式的数据,并控制输出的对齐、宽度、精度等。spdlog库提供了丰富的格式化选项让你在日志中输出信息更加灵活和可读。

0821

  1. 图像去畸变的计算过程中,float和double的精度对于最终的结果是有较大影响的,要确定一个类型来保证最终的效果;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值