坐标变换

坐标变换

  • 位姿变换(位姿在不同坐标系中变换, 更常用): PosesT or T,
    • 关键在于同一个位姿(实际位姿固定不变),但是在不同坐标系有不同的 表 示!
  • 坐标系变换(坐标系本身变换), 并且 CoordsT: CoordsT = T.inverse().

注意: ROS tf 发布的变换是坐标系变换 CoordsT, 包括通过
tf2_ros static_transform_publisher, TransformBroadcaster.sendTransform()
发布. 但是获取到的变换却是位姿变换 PosesT, 例如 Transformer.lookupTransform() !!

计算位姿变换 T

  • 某个位姿在 a 坐标系中为: Pa, e.g. (0, 0, 0) * RI,
    该位姿在 b 坐标系中表示为 Pb, e.g. (-1, 0, 0) * Rb,
    那么 a 到 b 的位姿变换 Ta2b = Pb * Pa.inverse(), e.g. (-1, 0, 0) * RT!!
  • 即 a 原点位姿在 b 中的位姿值, 就是 a 到 b 的位姿变换!!

计算 CoordsT

  • 注意: 以同一个公共坐标系计算的是 CoordsT, e.g. 都在 a 坐标系中,
    a 的原点为 P1, b 的原点为 P2, 那么 CoordsT = P2 * P1.inverse(), and
    Ta2b = CoordsT.inverse()
    !
  • 又或者都在 world 坐标系中, a 的原点为 Pw1 , b 的原点为 Pw2, 那么 CoordsT =
    Pw2 * Pw1.inverse(), and Ta2b = CoordsT.inverse()
    !

See also geometry: MakeTransform:

/**
 * Make a transform: from @a from pose to @a to pose.
 *
 * If T is PosesT, then @a from usually should be (0, 0, 0) * RI,
 * then @a to should be same real pose with @a from, but value is its value
 * in coordinate of @a to.
 *
 * If T is CoordsT, then @a from pose and @a to pose should be values in the
 * same coordinate, e.g. world or coordinate of @a from or coordinate of @a
 * to or some other.
 *
 * And NOTE: CoordsT = T.inverse()!!
 *
 * @param from from pose to build transform.
 * @param to to pose to build transform.
 * @return the @a from to @a to transform (from --transform--> to).
 */
static inline Eigen::Affine3d MakeTransform(
    Eigen::Affine3d const& from, Eigen::Affine3d const& to) noexcept
{
    return to * from.inverse();
}

通过位姿变换 T 计算位姿

已知某个位姿在坐标系 a 中为: Pa, a 中位姿到 b 中位姿变换为 Ta2b, 那么,
Pa 在坐标系 b 中位姿 Pb = Ta2b * Pa.

已知某个位姿在坐标系 a 中为: Pa, b 中位姿到 a 中位姿变换为 Tb2a, 那么,
Pa 在坐标系 b 中位姿 Pb = Tb2a.inverse() * Pa
(Ta2b = Tb2a.inverse()).

坐标变换矩阵

r00 r01 r02 tx
r10 r11 r12 ty
r20 r21 r22 tz
0   0   0   1

仿射

表示位姿或者变换:

  • Affine3d = Translation3d(x, y, z) * Quaterniond(w, x, y, z)
  • Affine2d = Translation2d(x, y) * Rotation2D<double>(angle))

https://yuiwong.org/gitlab/math/geometry

Phone number regular expression

Phone number regular expression

  • ChinaMain11Mobile3Y2018Mobile
"(^((13[0-9])|(14[5,7,9])|(15[0-3,5-9])"
"|166|(17[0,1,3,5-8])|(18[0-9])|(19[8-9])))-?\\d{4}-?\\d{4}$"
  • ChinaMain11Mobile3Y2018Mobile86
"^((\\+86)|(86))?-?"
"((13[0-9])|(14[5,7,9])|(15[0-3,5-9])"
"|166|(17[0,1,3,5-8])|(18[0-9])|(19[8-9]))-?\\d{4}-?\\d{4}$"
  • ChinaMainPhone
"(^0\\d{2,3})?-?\\d{7,8}$"
  • LesserNums11Mobile
// "^\\d{11}$"

"^\\d{3}-?\\d{4}-?\\d{4}$"
  • LesserPhone
"^\\d+$"

Part of phone number validator implementation in C++

Full code and test cases see

struct PhoneNumber final {
    /**
     * Phone number specification
     * MDN号码的结构如下: CC + MAC + H0 H1 H2 H3 + ABCD 其中:
     * - 【CC】: 国家码,中国使用86。
     * - 【MAC】: 移动接入码,本网采用网号方案,为133。
     * - 【H0H1H2H3】: HLR识别码,由运营商统一分配。
     * - 【ABCD】: 移动用户号,由各HLR自行分配。
     */
    enum class Spec {
        /**
         * @sa https://baike.baidu.com/item/%E6%89%8B%E6%9C%BA%E5%8F%B7%E7%A0%81
         * 电信 联通 移动 + 2018
         * - 中国电信号段
         *   133 149 153 173 177 180 181 189 199
         * - 中国联通号段
         *   130 131 132 145 155 156 166 171 175 176 185 186
         * - 中国移动号段
         *   134(0-8) 135 136 137 138 139 147 150 151 152 157 158 159 178
         *   182 183 184 187 188 198
         *
         * - 其他号段
         *   14 号段以前为上网卡专属号段 如中国联通的是 145 中国移动的是 147 等等
         *   虚拟运营商
         *   - 电信
         *     1700 1701 1702
         *   - 联通
         *     1704 1707 1708 1709 171
         *   - 移动
         *     1703 1705 1706
         *   - 卫星通信
         *     1349
         *
         * Pattern:
         * - nnnnnnnnnnn
         * - nnn-nnnn-nnnn
         * - nnn-nnnnnnnn
         * - nnnnnnn-nnnn
         */
        ChinaMain11Mobile3Y2018Mobile   = 0,
        /**
         * Pattern:
         * - nnnnnnnnnnn
         * - nnn-nnnn-nnnn
         * - nnn-nnnnnnnn
         * - nnnnnnn-nnnn
         * - 86nnnnnnnnnnn
         * - 86-nnnnnnnnnnn
         * - 86-nnn-nnnn-nnnn
         * - 86-nnn-nnnnnnnn
         * - 86-nnn-nnnn-nnnn
         * - +86nnnnnnnnnnn
         * - +86-nnnnnnnnnnn
         * - +86-nnn-nnnn-nnnn
         * - +86-nnn-nnnnnnnn
         * - +86-nnn-nnnn-nnnn
         */
        ChinaMain11Mobile3Y2018Mobile86 = 1,
        /**
         * 区号+号码,区号以 0 开头 3 位或 4 位
         * 号码由 7 位或 8 位数字组成
         * 区号与号码之间可以无连接符 也可以 - 连接
         * Pattern:
         * - 0nnnnnnnnn
         * - 0nn-nnnnnnn
         * - 0nnnnnnnnnn
         * - 0nnn-nnnnnnn
         */
        ChinaMainPhone                  = 10,
        /**
         * Pattern:
         * - nnnnnnnnnnn
         * - nnn-nnnn-nnnn
         */
        LesserNums11Mobile               = 98,
        /**
         * Pattern: n...
         * @note remove all +/- first
         */
        LesserPhone                      = 99,
    };
    ...
};

See also

Make RPM package 创建 RPM 包

Make RPM package 创建 RPM 包

…NOT recommended, maybe better :point_right: DEB/APT … see


  • Example on centos7 18.04.
  • 直接在 源码目录 / GIT 仓库创建
  • 没有 tarball — 没必要
  • 没有 configure — 使用 CMAKE
  • 创建的包不安装到 /usr/...
  • 创建包的根目录不是 ~/... — 就在当前工程下面
  • 此外对于 APP 包还有 strippost install 等需要处理
  • 不要使用 root 用户, 普通用户创建权限足够了

Install building tools

sudo yum install rpm-build
sudo yum install rpmdevtools

创建使用的配置文件 .spec 示例

详见:

## MY_PROJ_NAME.desc
# topdir is here, NOT ~/...
%define _topdir %(pwd)/rpmbuild
# %(pwd)/MY_SRC_DIR
%define srcdir %(pwd)/yuiwongcppbase
# MY_PREFIX
%define prefix opt/lib/yuiwongcppbase
%define builddir %{srcdir}/build
Name:         libyuiwongcppbase-devel
Version:      1.1.1
Release:      1%{?dist}
# MY_SHORT_DESCRIPTION
Summary:      C++ common library.

Group:        yuiwong.org
License:      LGPL-3.0
URL:          https://yuiwong.org/gitlab/cpp/cppbase
Source0:      gitsrc

#BuildRequires:
#Requires:

%description
# MY_DESCRIPTION
C++ common library.

%prep
# NOT xf tarball
#%setup -q

%build
cd %{srcdir}
rm -rf build
mkdir -p build
cd build
echo %{buildroot}
cmake .. \
  -DCMAKE_INSTALL_PREFIX=%{buildroot}/%{prefix} \
  -DENABLETEST=0 \
  -DEIGEN3=/opt/lib/eigen3 \
  -Dboost=/usr
echo "exit 0" > configure
chmod 700 configure
%configure
#make %{?_smp_mflags}
#make

%install
#make install DESTDIR=%{buildroot}
cd %{builddir}
make install
cd -

%files
/%{prefix}
%doc

%clean
rm -rf %{buildroot}/%{prefix}
rm -rf %{builddir}

%changelog

Make

rpmbuild -bb rpmbuild/yuiwongcppbase.spec