陪你骑车好吗 - 成都KTC的遗憾

返回目录

彼时Iris已经三岁半了,我们换Strider车也有好几个月了;终于迎来了一次大考,2019年09月08日KTC成都站。

当初决定报这场比赛,只是因为一个偶然的机会,看到Bike8的公众号推文。赛道摆成熊猫状,挺有意思的,而且我们也想带孩子出去见见世面,旅游 and 见识外省高手,一举两得。

陪你骑车好吗 - 目录

  1. 写在前面的话
  2. 买了辆PUKY
  3. 再也不想去宜昌了
  4. 驻马店浮沉
  5. 成都KTC的遗憾

Arduino之HC-SR505红外传感器模块

HC-SR505

PIR(Pyroelectric Infra Red)传感器可测量检测区域中的物体发出的红外光。 HC-SR505就是这样的传感器。它非常易于使用,如果检测区域中有物体在移动,该传感器会产生HIGH高电平信号。该高电平信号持续约8秒钟,有时被视为不利条件。不幸的是,这个缺点不能在软件上解决,即在源代码中添加替代方法不起作用。该模块的工作电压在4.5V至20V之间。根据数据手册,传感器可检测到长达3m的移动。

Arduino之GY-BMP280-3.3高精度大气压强传感器模块

GY-BMP280-3.3

GY-BMP280-3.3 高精度大气压强传感器模块是个低功耗数字复合传感器,它可以测量环境温度和大气压强。气压敏感元件是一个低噪高精度高分辨率绝对大气压力压电式感应元件;温度感测元件具有低噪高分辨率特性,温度值可以对气压进行温度补偿自校正。通过配置采样率寄存器,可以设置敏感元件的采样率。非常适合空间有限的移动设备,如智能是手机、平板电脑、智能手表和可穿戴设备、天气预报、垂直速度指示、飞控设备、室内室外导航、智能家居装置。

Arduino之US015高分辨超声波测距模块

超声波测距原理

超声波测距原理是在超声波发射装置发出超声波,它的根据是接收器接到超声波时的时间差,与雷达测距原理相似。 超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。(超声波在空气中的传播速度为340m/s,根据计时器记录的时间t(秒),就可以计算出发射点距障碍物的距离(s),即:s=340t/2)

Arduino之GY-30光照传感器

GY-30 光照传感器

数字光强度检测模块:GY-30

  • 采用ROHM原装BH1750FVI芯片
  • 供电电源 :3-5v
  • 光照度范围:0-65535 lx
  • 传感器内置16bitAD转换器
  • 直接数字输出,省略复杂的计算,省略标定
  • 不区分环境光源
  • 接近于视觉灵敏度的分光特性
  • 可对广泛的亮度进行1勒克斯的高精度测定

代码

采用IIC通讯方式,GY-30VCC接+5V,GND接地。GY-30 SDA 、SCL分别接A4、 A5

Arduino之DHT11温湿度传感器模块

DHT11 温湿度传感器

DHT11 是一款温湿度传感器,可以用来测试环境温湿度,该传感器的的温度测量范围为 0 ~ 50°C,误差为 2 °C;湿度测量范围为在 0°C时为30%-90%RH,环境温度为 25°C时,湿度测量范围为20%-90%RH,在50°C时,测量范围是20%-80%。

算数独

闲暇的时候写的小程序,从map输入数独的题目后自动计算。

#include "stdafx.h"

#include <vector>
#include <map>
#include <iostream>
#include <assert.h>

// 获取行index
std::vector<int> askRow(int index)
{
    std::vector<int> rownum;

    auto rowindex = index / 10;
    for (int i = 0; i < 9; i++)
    {
        rownum.push_back(rowindex * 10 + i);
    }
    return rownum;
}

// 获取列index
std::vector<int> askCol(int index)
{
    std::vector<int> colnum;

    auto colindex = index % 10;
    for (int i = 0; i < 9; i++)
    {
        colnum.push_back(i * 10 + colindex);
    }
    return colnum;
}

// 获取宫index
std::vector<int> askBlock(int index)
{
    std::vector<std::vector<int>> blocknum = {
        {0,1,2,10,11,12,20,21,22},
        {3,4,5,13,14,15,23,24,25},
        {6,7,8,16,17,18,26,27,28},
        {30,31,32,40,41,42,50,51,52},
        {33,34,35,43,44,45,53,54,55},
        {36,37,38,46,47,48,56,57,58},
        {60,61,62,70,71,72,80,81,82},
        {63,64,65,73,74,75,83,84,85},
        {66,67,68,76,77,78,86,87,88},
    };

    for (const std::vector<int>& item : blocknum)
    {
        if (item.end() != std::find(item.begin(), item.end(), index))
            return item;
    }
    assert(false);
    return std::vector<int>();
}

// 检查冲突(入参为格子的值,而非index)
bool check(const std::vector<char>& block)
{
    char checknum[9] = { 0 };
    for (auto item : block)
    {
        if (item == 0)
            continue;

        // 同一位置已经有值了
        if (checknum[item - 1] == 1)
            return false;

        // 占位
        checknum[item - 1] = 1;
    }
    return true;
}

// 获取一个检查数据
std::vector<char> getBlock(const std::vector<char>& table, const std::vector<int>& block)
{
    assert(block.size() == 9);

    std::vector<char> blockData;
    for (size_t i = 0; i < block.size(); ++i)
    {
        blockData.push_back(table.at(block.at(i)));
    }
    return blockData;
}

bool calcBackup(std::vector<char>& table, std::vector<std::pair<char, std::vector<char>>>& backupmap)
{
    // 侯选数
    backupmap.clear();
    for (int index = 0; index < 90; ++index)
    {
        if (index % 10 == 9)
            continue;

        if (table.at(index) > 0)
            continue;

        // 获取三种类型的数据集
        auto blockRow = askRow(index);
        auto blcokDataRow = getBlock(table, blockRow);
        auto blockCol = askCol(index);
        auto blcokDataCol = getBlock(table, blockCol);
        auto block = askBlock(index);
        auto blcokData = getBlock(table, block);

        // 获取每个格子的候选数
        std::vector<char> vec;
        for (int i = 1; i < 10; i++)
        {
            if (blcokDataRow.end() == std::find(blcokDataRow.begin(), blcokDataRow.end(), i) &&
                blcokDataCol.end() == std::find(blcokDataCol.begin(), blcokDataCol.end(), i) &&
                blcokData.end() == std::find(blcokData.begin(), blcokData.end(), i))
                vec.push_back(i);
        }

        // 如果只有一个候选数,则重算
        assert(vec.size() > 0);
        if (vec.size() == 1)
        {
            table.at(index) = vec[0];
            return true;
        }
        backupmap.push_back(std::make_pair(index, vec));
    }
    return false;
}

// 递归,一个个的试
bool calc(std::vector<char>& table, const std::vector<std::pair<char, std::vector<char>>>& backupmap, int num, int index)
{
    int currentIndex = backupmap.at(num).first;
    table.at(currentIndex) = backupmap.at(num).second.at(index);

    auto blockRow = askRow(currentIndex);
    auto blockCol = askCol(currentIndex);
    auto block = askBlock(currentIndex);
    if (check(getBlock(table, block)) && check(getBlock(table, blockRow)) && check(getBlock(table, blockCol)))
    {
        if (num >= backupmap.size() - 1)
        {
            // 计算到最后一格,出现全部备选数据相匹配的情况
            return true;
        }
        else
        {
            // 当前格子匹配正常,继续计算下一个
            for (int index = 0; index < backupmap.at(num + 1).second.size(); ++index)
            {
                if (calc(table, backupmap, num + 1, index))
                {
                    return true;
                }
            }
        }
    }
    table.at(currentIndex) = 0;
    return false;
}

void prinfTable(const std::vector<char>& table)
{
    for (int row = 0; row < 9; ++row)
    {
        if (row % 3 == 0)
        {
            printf("------------------------------------------ \n");
        }

        printf("%4d%4d%4d | %4d%4d%4d | %4d%4d%4d \n", table[row * 10], table[row * 10 + 1], table[row * 10 + 2],
            table[row * 10 + 3], table[row * 10 + 4], table[row * 10 + 5],
            table[row * 10 + 6], table[row * 10 + 7], table[row * 10 + 8]);
    }
}

bool fill(const std::map<char, char>& origin, std::vector<char>& table)
{
    for (auto item : origin)
    {
        table.at(item.first) = item.second;
    }

    int i = 0;
    std::vector<std::pair<char, std::vector<char>>> backupmap;
    while (calcBackup(table, backupmap))
    {
        if (i++ > 90)
            break;
    }

    if (backupmap.size() > 0)
    {
        for (int index = 0; index < backupmap.front().second.size(); ++index)
        {
            if (calc(table, backupmap, 0, index))
            {
                return true;
            }
        }
        return false;
    }
    return true;
}

int main()
{
    std::map<char, char> origin;
    origin.insert(std::make_pair(12, 1));
    origin.insert(std::make_pair(15, 9));
    origin.insert(std::make_pair(18, 7));
    origin.insert(std::make_pair(20, 7));
    origin.insert(std::make_pair(22, 9));
    origin.insert(std::make_pair(23, 4));
    origin.insert(std::make_pair(27, 2));
    origin.insert(std::make_pair(28, 3));
    origin.insert(std::make_pair(32, 4));
    origin.insert(std::make_pair(33, 7));
    origin.insert(std::make_pair(36, 6));
    origin.insert(std::make_pair(43, 1));
    origin.insert(std::make_pair(44, 5));
    origin.insert(std::make_pair(47, 8));
    origin.insert(std::make_pair(55, 4));
    origin.insert(std::make_pair(61, 2));
    origin.insert(std::make_pair(66, 7));
    origin.insert(std::make_pair(67, 3));
    origin.insert(std::make_pair(70, 5));
    origin.insert(std::make_pair(71, 8));
    origin.insert(std::make_pair(74, 1));
    origin.insert(std::make_pair(78, 2));
    origin.insert(std::make_pair(84, 4));
    origin.insert(std::make_pair(85, 3));

    std::vector<char> table(90, 0);
    if (fill(origin, table))
    {
        std::cout << "happy end" << std::endl;
        prinfTable(table);
    }
    else
    {
        std::cout << "sorry" << std::endl;
    }

    getchar();
    return 0;
}

前端矩阵 (matrix) 封装

使用 canvas 画布来操控图形或者图片的二维变化的方式一般是平移、缩放、和旋转。canvas 已相应提供了相关的 api。如:translate(), scale() 和 rotate(),但这些功能无法统一处理并且无法描述当前画布的处于某种状态。为了实现这种统一连贯性的状态描述,canvas 给我们提供了另外一种思路及方法,即使用:transform() / setTransform();因为画布上的每个对象都拥有一个当前的 3 x 3 变换矩阵,都可以使用一个 3 x 3 矩阵来描述当前状态,其实是 2 x 3 矩阵,但为了便于计算,人为添加第三行 0 0 1 变成 3 x 3 矩阵。费话不多话,下面直接看矩阵变换的已封装好的功能,为了便于读者理解,每一步都有详细解释及介绍。

boost b2 参数说明

命令参数

b2 命令的功能强大,用起来也比较复杂,因此在使用之前,最好先查看一下该命令的帮助:

b2.exe --help

stage/install

stage 表示只生成库(dll 和 lib),install 还会生成包含头文件的 include 目录。推荐使用 stage,因为 install 生成的 include 目录实际就是源码包下的 boost 目录,需要 include 的时候可以直接使用,不需要再次生成,这样可以节省大量的编译时间。