RISC-V MCU 导盲手套

2023-05-16

RISC-V MCU 导盲手套

  • 关于本文
  • 队伍名称
  • 第一部分 设计概述
    • 1.1 设计目的
    • 1.2 应用领域
    • 1.3 主要技术特点
    • 1.4 关键性能指标
    • 1.5 主要创新点
  • 第二部分 系统组成及功能说明
    • 2.1 整体介绍
    • 2.2 各模块介绍
  • 第三部分 完成情况及性能参数
    • 3.1 可通过手机蓝牙实现经纬度设定:
  • 第四部分 总结
    • 4.1 可扩展之处
    • 4.2 心得体会
  • 第五部分 相关链接
  • 第六部分 详细方案设计
    • 收集导航模块数据
    • 处理接收数据
    • 实现充放气
    • 实现蓝牙通信
  • 第七部分 总体代码

关于本文

本项目采用沁恒RISC-V板卡/芯片,参加了2022年(第五届)全国大学生嵌入式芯片与系统设计竞赛,应用赛道为中部赛区。秉承RISC-V开源精神,本队伍选择对作品开源。

队伍名称

一零二八队

第一部分 设计概述

1.1 设计目的

为帮助视障人群更好出行,本作品设计为一款便携可穿戴式设备——导盲手套,该设备基于沁恒赤菟平台和RT-thread物联网技术,根据北斗定位模块定位,当位置处于电子围栏内部,手套下方气囊充气产生触感,处于电子围栏外部气囊放气,使用者据此提示调整路线。

1.2 应用领域

可应用于盲人导航,未来可扩展用于VR技术。

1.3 主要技术特点

基于沁恒赤菟平台和RT-thread物联网技术,并用北斗数据地图定位和超声波检测加以辅助。使用时,该项目APP先通过定位与避障,规划出电子护栏的位置和方向,使用者到达附近后会得到语音提示,气囊随之变化,使用者可根据触感调整路线从而达到导盲效果。

1.4 关键性能指标

可通过手机蓝牙连接手套进行经纬度设定,划定区域,在到达指定经纬度区域内,手套可实现充气,提醒用户到达区域,离开区域后,手套可实现放气。

1.5 主要创新点

  1. 改变了传统的拐杖避障,采用更人性化更轻松的模式,给予盲人虚拟现实的体验和与人交互的可能。

  2. 结合北斗定位模块,提供防丢保障和科学的路径规划。

第二部分 系统组成及功能说明

2.1 整体介绍

本作品主要由四部分组成:沁恒赤菟开发板、Air530北斗定位模块、手套充放气控制模块、手套主体。沁恒开发板为主要信息处理模块,负责各模块间的信息交流和数据处理。Air530模块主要负责实时定位,向赤菟开发板提供经纬度数据。手套充放气控制模块通过电磁阀和气泵,实现手套的充放气功能。
导盲手套

2.2 各模块介绍

  1. 开发板采用沁恒官方提供的赤菟开发板;
    开发板

  2. 北斗定位模块采用合宙的Air530模块,精度高,连接快;
    合宙Air530

  3. 手套充放气模块为自主设计电路,采用了12V供压的电磁阀和气泵;
    电磁阀和气泵

  4. 手套主体采用了可以实现充放气的医疗康复手套。
    手套

第三部分 完成情况及性能参数

3.1 可通过手机蓝牙实现经纬度设定:

蓝牙发送
反馈信息

  1. 当进入划定区域时,手套充气,LED1亮起。

充气
当前位置

  1. 当离开划定区域时,手套放气,LED2亮起。
    放气
    当前位置

第四部分 总结

4.1 可扩展之处

  1. 手套充放气模块需12V供压,本作品使用3节18650电池实现,过于臃肿,可通过DC-DC升压模块,用一节电池完成12V供压。
  2. 手套充放气模块现阶段使用洞洞板简单实现,未来可使用PCB,缩小模块体积。
  3. 可通过增加超声波模块达到更精确实时的避障功能。
  4. 增加姿态传感功能,使得手套上方屏幕可根据手部姿态显示信息来提示路人。

4.2 心得体会

深入理解了北斗定位模块使用原理,学会了NMEA0183 协议及其使用,深入学习串口通信和RT-Thread操作系统使用。

第五部分 相关链接

Air530定位模块使用手册
NMEA0183 协议手册(中文)
项目gitee页面

第六部分 详细方案设计

收集导航模块数据

找到两个扩展接口D8和D9作为TX与RX,接收来自导航模块的数据。将两个端口重定向到USART3,波特率经查阅导航模块手册为9600

// USART3
rt_pin_mode(55, PIN_MODE_OUTPUT_AF_PP);  // PIND8 USART3_TX
rt_pin_mode(56, PIN_MODE_INPUT);         // PIND9 USARt3_RX
// 重定位
GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);
// 初始化USART3
USART_InitStruct.USART_BaudRate = 9600;
USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruct.USART_Parity = USART_Parity_No;
USART_InitStruct.USART_StopBits = USART_StopBits_1;
USART_InitStruct.USART_WordLength = USART_WordLength_8b;
USART_Init(USART3, &USART_InitStruct);
// 使能串口3
USART_Cmd(USART3, ENABLE);

导航模块定时发送数据,采用接收中断方式接收数据

// 中断初始化
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);

处理接收数据

收到的数据遵循NMEA-0831协议,经查阅知所需数据(经纬度)在#GNRMC行。
由于接收中断为每个字符产生一次,故只需检测以”#”开头的行后面是否为”GNRMC”,然后将整行用字符串变量存储。

if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
 {
      USART_ClearITPendingBit(USART3,USART_IT_RXNE);
      tmp = USART_ReceiveData(USART3);
      if(tmp == '$' && flag == 0)
      {
          flag = 1;
      }
      if(flag && tmp != '$')
      {
          buf[index++] = tmp;
      }
      if(flag && (tmp == '$' || index == 100) && index > 3)
      {
          if(buf[0] == 'G' && buf[1] == 'N' && buf[2] == 'R')
          {
              strcpy(gnrmc, buf);
              printf("%s", gnrmc);
              rt_pin_write(AIR_IN_PIN, PIN_LOW);
              rt_pin_write(AIR_OUT_PIN, PIN_LOW);
              break;
          }
          index = 0;
          memset(buf, 0, sizeof(buf));
      }
  }

根据协议,利用数逗号方法,提取出N/S前的数字作为维度,提取出E/W前的数字作为经度

// 经纬度
longt = 0; lat = 0;
u_int8_t i, c, count = 0;
for(i = 0; i < 100; i++)
{
    c = gnrmc[i];
    if(c == ',') count++;
    if(count == 3)
    {
        c = gnrmc[i + 1];
        if(c >= '0' && c <= '9') lat = lat * 10 + (u_int32_t)(c - '0');
        else if(c == '.');
        else if(c == ',')
        {
            count++;
            i++;
        }
    }
    if(count == 5)
    {
        c = gnrmc[i + 1];
        if(c >= '0' && c <= '9') longt = longt * 10 + (u_int32_t)(c - '0');
        else if(c == '.');
        else if(c == ',') break;
    }
}

实现充放气

实际上利用两个扩展接口实现充放气功能,这里用两个LED灯指示。初始状态两个LED等均灭,进入范围后LED1亮,LED2灭;出范围后均亮
实现方法,直接判断读取到的当前经纬度是否在设置范围内
如果在范围内,开始充气,到界限后停止充气;出范围后,放气。

 if(longt <= longt_right && longt >= longt_left && lat <= lat_up && lat >= lat_down)
 {
     // 亮LED1
     rt_pin_write(LED1_PIN, PIN_LOW);
     rt_pin_write(LED2_PIN, PIN_HIGH);
     // 充气
     if(has_gas <= 4)
     {
         rt_pin_write(AIR_IN_PIN, PIN_HIGH);
         has_gas++;
     }
 }
 else
 {
     if(rt_pin_read(LED1_PIN) == 0)
     {
         // 亮LED2
         rt_pin_write(LED2_PIN, PIN_LOW);
         // 放气, 无论什么状态,放气 1个时间单位, 置充气位为0;
         if(has_gas)
         {
             rt_pin_write(AIR_OUT_PIN, PIN_HIGH);
             has_gas = 0;
         }

     }
 }

实现蓝牙通信

接收导航数据相同,另找两个扩展接口C2与C3作为TX与RX端,重定位为UART7,需要另打开蓝牙模式

    rt_pin_mode(32, PIN_MODE_INPUT_PULLUP);  //PINA7 BLUETOOTH MODE

在更改边界时,通过uart7向蓝牙发送信息,进行选择,信息的接收依旧使用rx中断接收

UART_SendString(UART7, "Change boundary? 1 - Yes  2- No");

// 发送当前经纬度
// 发送当前经纬度
char *s1 = "\r\nCurrent Latitude:    ",
     *s2 = "\r\nCurrent Longitude: ";
char t[20];
UART_SendString(UART7, s1);
itoa(lat, t, 10);
UART_SendString(UART7, t);
UART_SendString(UART7, s2);
itoa(longt, t, 10);
UART_SendString(UART7, t);

UART_SendString(UART7, "\r\nYour option: ");
u_int8_t op, count, print_flag;
u_int8_t num[20], index, c;
memset(num, 0, sizeof(num));

依次输入四个边界点,以’#’为中止

while(USART_GetITStatus(UART7, USART_IT_RXNE) == RESET);
 // 接收选择
 if(USART_GetITStatus(UART7, USART_IT_RXNE) != RESET)
 {
     USART_ClearITPendingBit(UART7, USART_IT_RXNE);
     op = USART_ReceiveData(UART7);
     if(op == '2')
     {
         UART_SendString(UART7, "2\r\nBoundary unchange!\r\n");
         return;
     }
     UART_SendString(UART7, "1\r\nInput the new boundary ended with '#':\r\n");
     // 1 - 维度上边界
     count = 1;
     print_flag = 1;
     index = 0;
     while(1)
     {
         if(print_flag)
         {
             switch(count)
             {
             case 1: UART_SendString(UART7, "Latitude_Up:        "); break;
             case 2: UART_SendString(UART7, "\r\nLatitude_Down:   "); break;
             case 3: UART_SendString(UART7, "\r\nLongitude_Left:   "); break;
             case 4: UART_SendString(UART7, "\r\nLongitude_Right: "); break;
             case 5: UART_SendString(UART7, "\r\nEnd!"); return;
             }
         }
         while(USART_GetITStatus(UART7, USART_IT_RXNE) == RESET);
         if(USART_GetITStatus(UART7, USART_IT_RXNE) != RESET)
         {
             USART_ClearITPendingBit(UART7, USART_IT_RXNE);
             c = USART_ReceiveData(UART7);
             print_flag = 0;
             num[index++] = c;
             if(c == '#')
             {
                 if(count == 1)      lat_up = to_int(num);
                 else if(count == 2) lat_down = to_int(num);
                 else if(count == 3) longt_left = to_int(num);
                 else if(count == 4) longt_right = to_int(num);
                 UART_SendString(UART7, num);
                 memset(num, 0, sizeof(num));
                 count++;
                 index = 0;
                 print_flag = 1;
             }
         }
     }
 }

第七部分 总体代码

/* 该文件基于RT-thread系统,仅显示main.c内容 */
#include "ch32v30x.h"
#include <rtthread.h>
#include <rthw.h>
#include "drivers/pin.h"
#include <debug.h>
#include <string.h>
#include <stdlib.h>

#define LED1_PIN    42   //PE11
#define LED2_PIN    43   //PE12

#define AIR_IN_PIN  57   //PD10
#define AIR_OUT_PIN 58   //PD11

#define CH_EDGE_IT_INIT 5

// 经纬度限界
u_int32_t longt_left, longt_right, lat_up, lat_down;

// 经纬度
u_int32_t longt, lat;

// 显示经纬度
u_int8_t started = 0;

// 更改限界中断间隔
u_int8_t change_edge_it = CH_EDGE_IT_INIT;

// 气体容量
u_int8_t has_gas = 0;

void Init_UART()
{
    //USART1
    rt_pin_mode(68, PIN_MODE_OUTPUT_AF_PP);  //PINA9  USART1_TX
    rt_pin_mode(69, PIN_MODE_INPUT);         //PINA10 USARt1_RX

    //USART3
    rt_pin_mode(55, PIN_MODE_OUTPUT_AF_PP);  //PIND8 USART3_TX
    rt_pin_mode(56, PIN_MODE_INPUT);         //PIND9 USARt3_RX

    // UART7
    rt_pin_mode(17, PIN_MODE_OUTPUT_AF_PP);  //PINC2 USART7_TX
    rt_pin_mode(18, PIN_MODE_INPUT);         //PINC3 USART7_RX
    rt_pin_mode(32, PIN_MODE_INPUT_PULLUP);  //PINA7 BLUETOOTH MODE

    USART_InitTypeDef USART_InitStruct;

    // 开时钟(USART1 TX-A9 RX-A10)
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1| RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3| RCC_APB1Periph_UART7, ENABLE);

    GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);

    // 初始化USART3
    USART_InitStruct.USART_BaudRate = 9600;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART3, &USART_InitStruct);

    // 使能串口3
    USART_Cmd(USART3, ENABLE);

    // 初始化USART1
    USART_InitStruct.USART_BaudRate = 115200;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_Init(USART1, &USART_InitStruct);

    // 使能串口1
    USART_Cmd(USART1, ENABLE);

    // 初始化USART7
    USART_InitStruct.USART_BaudRate = 9600;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStruct.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_Init(UART7, &USART_InitStruct);

    // 使能串口7
    USART_Cmd(UART7, ENABLE);

    // 中断初始化
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
    USART_ITConfig(UART7,  USART_IT_RXNE, ENABLE);

}

void UART_SendByte(USART_TypeDef * USARTx,uint8_t data)
{
    USART_SendData(USARTx, data);
    while(!USART_GetFlagStatus(USARTx, USART_FLAG_TXE));
}

void UART_SendString(USART_TypeDef * USARTx,char* string)
{
    char *str = string;
    while(*str)
    {
        UART_SendByte(USARTx,*str);
        str++;
    }
}

u_int32_t to_int(u_int8_t *num)
{
    u_int8_t i;
    u_int32_t result = 0;
    for(i = 0; i < 20; i++)
    {
        if(num[i] == '#')
            return result;
        else
        {
            result = result * 10 + (num[i] - '0');
        }
    }
    return 0;
}

void change_edge()
{
    UART_SendString(UART7, "Change boundary? 1 - Yes  2- No");

    // 发送当前经纬度
    // 发送当前经纬度
    char *s1 = "\r\nCurrent Latitude:    ",
         *s2 = "\r\nCurrent Longitude: ";
    char t[20];
    UART_SendString(UART7, s1);
    itoa(lat, t, 10);
    UART_SendString(UART7, t);
    UART_SendString(UART7, s2);
    itoa(longt, t, 10);
    UART_SendString(UART7, t);


    UART_SendString(UART7, "\r\nYour option: ");
    u_int8_t op, count, print_flag;
    u_int8_t num[20], index, c;
    memset(num, 0, sizeof(num));

    while(USART_GetITStatus(UART7, USART_IT_RXNE) == RESET);
    // 接收选择
    if(USART_GetITStatus(UART7, USART_IT_RXNE) != RESET)
    {
        USART_ClearITPendingBit(UART7, USART_IT_RXNE);
        op = USART_ReceiveData(UART7);
        if(op == '2')
        {
            UART_SendString(UART7, "2\r\nBoundary unchange!\r\n");
            return;
        }
        UART_SendString(UART7, "1\r\nInput the new boundary ended with '#':\r\n");
        // 1 - 维度上边界
        count = 1;
        print_flag = 1;
        index = 0;
        while(1)
        {
            if(print_flag)
            {
                switch(count)
                {
                case 1: UART_SendString(UART7, "Latitude_Up:        "); break;
                case 2: UART_SendString(UART7, "\r\nLatitude_Down:   "); break;
                case 3: UART_SendString(UART7, "\r\nLongitude_Left:   "); break;
                case 4: UART_SendString(UART7, "\r\nLongitude_Right: "); break;
                case 5: UART_SendString(UART7, "\r\nEnd!"); return;
                }
            }
            while(USART_GetITStatus(UART7, USART_IT_RXNE) == RESET);
            if(USART_GetITStatus(UART7, USART_IT_RXNE) != RESET)
            {
                USART_ClearITPendingBit(UART7, USART_IT_RXNE);
                c = USART_ReceiveData(UART7);
                print_flag = 0;
                num[index++] = c;
                if(c == '#')
                {
                    if(count == 1)      lat_up = to_int(num);
                    else if(count == 2) lat_down = to_int(num);
                    else if(count == 3) longt_left = to_int(num);
                    else if(count == 4) longt_right = to_int(num);
                    UART_SendString(UART7, num);
                    memset(num, 0, sizeof(num));
                    count++;
                    index = 0;
                    print_flag = 1;
                }
            }
        }
    }
    return;
}

void Daomang()
{
    Init_UART();
    rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(LED2_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(AIR_IN_PIN, PIN_MODE_OUTPUT);
    rt_pin_mode(AIR_OUT_PIN, PIN_MODE_OUTPUT);

    uint8_t capcity = 100;
    char buf[capcity], gnrmc[capcity];
    uint8_t index, tmp;
    int flag;

    rt_pin_write(LED1_PIN, PIN_HIGH);
    rt_pin_write(LED2_PIN, PIN_HIGH);

    lat_up      = 30462290;      // 上
    lat_down    = 30462250;      // 下

    longt_left  = 120182900;     // 左
    longt_right = 120183100;     // 右

//    change_edge();

    while(1)
    {
        index = 0; flag = 0;
        memset(buf, 0, sizeof(buf));
        memset(gnrmc, 0, sizeof(gnrmc));
        while(1)
        {
            if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
            {
                USART_ClearITPendingBit(USART3,USART_IT_RXNE);
                tmp = USART_ReceiveData(USART3);
                if(tmp == '$' && flag == 0)
                {
                    flag = 1;
                }
                if(flag && tmp != '$')
                {
                    buf[index++] = tmp;
                }
                if(flag && (tmp == '$' || index == 100) && index > 3)
                {
                    if(buf[0] == 'G' && buf[1] == 'N' && buf[2] == 'R')
                    {
                        strcpy(gnrmc, buf);
                        printf("%s", gnrmc);
                        rt_pin_write(AIR_IN_PIN, PIN_LOW);
                        rt_pin_write(AIR_OUT_PIN, PIN_LOW);
                        break;
                    }
                    index = 0;
                    memset(buf, 0, sizeof(buf));
                }
            }
        }
        // 经纬度
        longt = 0; lat = 0;
        u_int8_t i, c, count = 0;
        for(i = 0; i < 100; i++)
        {
            c = gnrmc[i];
            if(c == ',') count++;
            if(count == 3)
            {
                c = gnrmc[i + 1];
                if(c >= '0' && c <= '9') lat = lat * 10 + (u_int32_t)(c - '0');
                else if(c == '.');
                else if(c == ',')
                {
                    count++;
                    i++;
                }
            }
            if(count == 5)
            {
                c = gnrmc[i + 1];
                if(c >= '0' && c <= '9') longt = longt * 10 + (u_int32_t)(c - '0');
                else if(c == '.');
                else if(c == ',') break;
            }
        }


        // 更改经纬度限界
        if(started == 0){
            started ++;
        }
        else if(started == 1){
            change_edge();
            started ++;
        }
        else{
            printf("Latitude:  %d\r\nLongitude: %d\r\n", lat, longt);
            printf("lau: %d\r\nlad: %d\r\nlol: %d\r\nlor: %d\r\n",lat_up,lat_down,longt_left,longt_right);
        }
        if(longt <= longt_right && longt >= longt_left && lat <= lat_up && lat >= lat_down)
        {
            // 亮LED1
            rt_pin_write(LED1_PIN, PIN_LOW);
            rt_pin_write(LED2_PIN, PIN_HIGH);
            // 充气
            if(has_gas <= 4)
            {
                rt_pin_write(AIR_IN_PIN, PIN_HIGH);
                has_gas++;
            }

        }
        else
        {
            if(rt_pin_read(LED1_PIN) == 0)
            {
                // 亮LED2
                rt_pin_write(LED2_PIN, PIN_LOW);
                // 放气, 无论什么状态,放气 1个时间单位, 置充气位为0;
                if(has_gas)
                {
                    rt_pin_write(AIR_OUT_PIN, PIN_HIGH);
                    has_gas = 0;
                }

            }
        }
    }
}

int main()
{
    rt_kprintf("\r\n MCU: CH32V307\r\n");
    rt_kprintf(" SysClk: %dHz\r\n",SystemCoreClock);
    rt_kprintf(" www.wch.cn\r\n");

    while(1)
    {
        rt_thread_mdelay(500);
    }
}
MSH_CMD_EXPORT(Daomang,test);


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RISC-V MCU 导盲手套 的相关文章

  • 4.4线索二叉树遍历

    1 中序线索二叉树遍历 找到第一个中序遍历的结点 ThreadNode span class token operator span span class token function Firstnode span span class t
  • 自动根据本机字节序 将小端字节序的报文(字符数组)转为整数

    1 xff0c 判断本机的字节序 xff08 大端优先 小端优先 xff09 判断当前PC为大端还是小端字节序 64 返回值 xff1a 1 大端 xff1b 0 小端 int JudgeEndianOfPC int num 61 1 if
  • 智能指针的使用

    智能指针在C 43 43 11版本之后提供 xff0c 包含在头文件 lt memory gt 中 xff0c shared ptr unique ptr weak ptr 1 xff0c shared ptr的使用 shared ptr使
  • 图像检索系列——利用深度学习实现以图搜图

    转载自 xff1a 图像检索系列 利用深度学习实现以图搜图 知乎 前言 在上一篇文章 图像检索系列 利用 Python 检测图像相似度 中 xff0c 我们介绍了一个在图像检索领域非常常用的算法 感知哈希算法 这是一个很简单且快速的算法 x
  • Windows下select模型(以及EAGAIN、EWOULDBLOCK、EINTR)

    在这里记录一下 xff0c 以前都是新项目用到了就从旧项目中拷贝 自从将博客当作记事本 xff0c 发现自己多了一个好习惯 Windows下select模型 程序员攻略 CSDN博客 套接字IO超时设置和使用select实现超时管理 wj
  • RANSAC算法理解

    RANSAC是 RANdom SAmple Consensus xff08 随机抽样一致 xff09 的缩写 它可以从一组包含 局外点 的观测数据集中 xff0c 通过迭代方式估计数学模型的参数 它是一种不确定的算法 它有一定的概率得出一个
  • C++ 环形缓冲区(队列)简单实现

    1 说明 在实际工作中 xff0c 如果数据流量过大 xff0c 可以先把数据接收到数据缓冲区中 xff0c 处理之后再取出 我们定义的包协议可以采用定长包 xff0c 可以采用不定长度的包 xff0c 环形缓冲区都能处理 2 使用场景 2
  • Visual Studio Code (vscode) 配置 C / C++ 环境

    Visual Studio Code vscode 配置 C C 43 43 环境 步平凡 博客园 在电脑安装软件管控严格的情况下 xff0c 想装VS装不了 xff0c 就装轻量版的VSCode了 以上写得很好 xff0c 照做即可 本人
  • c++实现basename

    window API居然不包含Linux中很好用的basename函数 xff0c 实现了一下 xff0c 留个记录 xff0c 省得日后重复写 std string m basename std string fullPath size
  • tortoiseGit教程

    0 前言 TortoiseGit其实是一款开源的git的版本控制系统 xff0c 也叫海龟git TortoiseGit提供了人性化的图形化界面 xff0c 不用像Git一样输入许多语句 xff0c 像git init git add gi
  • 用STL库创建线程

    测试了3种方式 xff1a 1 xff1a 子线程不带返回值 2 xff1a 子线程带返回值 3 xff1a 子线程带引用类型参数 使用join方式 xff0c 让父线程等待子线程运行结束 TestTemp cpp 定义控制台应用程序的入口
  • 4.5树的存储

    双亲表示法 xff0c 孩子表示法 xff0c 孩子兄弟表示法 1 双亲表示法 查找双亲简单 空数据导致遍历更慢 xff0c 查指定节点的孩子只能遍历 span class token keyword typedef span ElemTy
  • Windows下MySQL数据库的安装、配置及C++使用案例

    1 安装及配置 Windows判断本地是否安装mysql以及mysql安装过程 企鹅要去银河思考人生 xff01 xff01 xff01 的博客 CSDN博客 windows查看是否安装mysql 注意按照文中提示 xff0c 配置好环境变
  • C++获取系统毫秒级时间(自1970年1月1日至今的毫秒数)

    跟系统时间相关的 ifdef WIN32 include lt time h gt include lt windows h gt else include lt sys time h gt endif unsigned long long
  • Window 10下SQL Server的安装配置以及C++使用案例

    1 SQL Server2008的安装与配置 参照下面这篇博客实现即可 里面提供了安装包下载方式 xff08 百度网盘有点慢 xff09 安装及配置步骤 SQLServer安装教程 xff08 史上最详细版本 xff09 杨林伟的博客 CS
  • 基于OpenCV实现的多角度、多目标模板匹配项目实战案例

    1 说明 本案例采用NCC的匹配 金字塔 为了加速 思想 基于OpenCV实现的多角度 多目标模板匹配 不支持尺度不变 若研究旋转 尺度不变性的匹配 请参考本人的OpenCV专栏内的 nbsp OpenCV实现多角度多尺度模板匹配 基于形状
  • 程序日志模块的两种模式

    程序员都知道程序的运行日志在不少时候都非常有用 xff0c 利于排查 理清逻辑 一般而言 xff0c 日志都按天生成 xff0c 并且具备自动清理多少天以前的旧日志 xff0c 避免无限增长占用磁盘 下图展示了2种日志模式 模式一 1 xf
  • C++开发面试常考

    C 43 43 后台开发面试常考 pudn com
  • 如何在微软官网上下载旧版本的visual studio

    想在微软官网下载旧版本的VS 太长不想看的可以直接戳网址进入最终的界面 xff1a Visual Studio 较旧的下载 2019 2017 2015 和以前的版本想从官网首页一步一步进入到最终下载界面的可以看下面详细步骤 xff1a 1
  • 基于OpenCV实现的RANSAC随机抽样一致性直线拟合

    概要 本文介绍基于ransac随机抽样一致性随机抽样一致性的直线拟合方法 涵盖一下的内容 ransac的算法思想 ransac的算法步骤 如何调整ransac算法迭代的次数 基于opencv编码实现 ransac算法流程 RANSACRAN

随机推荐

  • 基于OpenCV(C++)实现的RANSAC随机抽样一致性的曲线拟合(二次)

    nbsp 0 前言 nbsp nbsp 前不久整理了RANSAC直线拟合的文章 基于OpenCV实现的RANSAC随机抽样一致性直线拟合 thequitesunshine007的博客 CSDN博客 这篇文章与其类似 只是从拟合直线变为拟合曲
  • 最小二乘least-squares拟合曲线(三次或多次)

    1 说明 基于最小least squares去拟合出多次曲线 考虑到了所有的样本点 因此这种方法对噪声敏感 尤其是遇到较为突兀明显的噪声时 曲线的形状易受干扰 2 代码 代码细节仔细读基本都能读懂 或者查一下也不是什么大问题 include
  • 4.6树和森林的遍历

    一 树的遍历 1 先根遍历 对应二叉树先序遍历 span class token keyword void span span class token function PreOrder span span class token punc
  • 扩展欧几里得算法(简单易懂,详细分析)

    扩展欧几里得算法 扩展欧几里得算法证明 43 应用 61 61 欧几里得算法 61 61 61 61 扩展欧几里得算法 61 61 应用1 xff1a 求一元二次线性方程的整数解应用二 xff1a 求ax 61 c mod p 应用三 xf
  • 佩尔方程(超详细推导+例题讲解) 每日一遍,算法再见!

    这里写目录标题 佩尔方程第一类佩尔方程第一类佩尔方程例题讲解 第二类佩尔方程 佩尔方程 第一类佩尔方程 定义 xff1a 形如 x 2 d
  • FFT(傅里叶快速变换,详细讲解+推导) 每日一遍,算法再见!

    FFT详细推导 FFT 傅里叶快速变换 一 前置知识1 复数和单位根2 单位根的三个引理3 多项式 二 FFT 快速傅里叶变换推导 三 IFFT四 FFT求解多项式乘积模板代码1 递归版2 非递归版 这个更快 xff0c 省去了递归时间 五
  • 背包问题----分组背包(超详细讲解)

    树形dp 分组背包 43 依赖背包 分组背包1 定义2 讲解3 练习题 依赖背包1 定义2 讲解3 练习题 分组背包 1 定义 分组背包 xff0c 通俗的讲就是 xff0c 给你N组物品 xff0c 然后每一组你至多选择一个物品 也可以不
  • 树状数组(详细分析+应用),看不懂打死我!

    树状数组介绍 在学习一个算法之前一定要清楚它能干嘛 xff0c 能解决什么样的问题 xff0c 对你解题是否有帮助 xff0c 然后才去学习它 那么接下来看如下几个问题 什么是树状数组 顾名思义就是一个结构为树形结构的数组 xff0c 于二
  • 更新Win10版本后,wifi图标不见了,并且连接不到wifi和宽带,以及点击网络和Internet闪退的情况

    问题描述 你们是不是遇到过这样的问题 xff0c 更新系统前还好好的 xff0c 更新之后wifi图标不见了 于是你尝试点击最右边的图标打开wifi xff0c 如下图所示 但是你发现没有任何可连接wifi xff0c 就下面这样 xff0
  • Netty框架之Selector使用详解

    谈到Selector的具体使用 xff0c 那么就要结合BIO NIO的知识讲解 xff0c Selector使用在非阻塞模式NIO场景下 xff0c 学习NIO之前先要了解BIO原理 xff0c 下面我们一步步讲解 一 BIO Block
  • SpringBoot系列---application.yml配置文件

    1 yml配置文件格式 span class token comment 对象 span span class token key atrule person span span class token punctuation span s
  • Spring系列---SpringBoot配置-profiles

    1 profiles的作用 2 使用profiles span class token punctuation span span class token comment 开发环境 span span class token key atr
  • SpringBoot系列---SpringBoot配置文件加载顺序

    1 内部文件配置加载顺序 resource目录下打包之后就是classpath路径 xff0c 所以classpath路径下也就是resource目录下的配置文件 2 外部配置文件加载顺序我们再使用springboot开发程序的时候 xff
  • 4.7树的使用(并查集、哈夫曼树的构建)

    一 并查集 优化后 时间复杂度 xff1a 树高 O log2n 查找 xff1a O log2n 1 并查集初始化 span class token macro property span class token directive ha
  • 游标v_cur的%notfound

    当游标的值为空的时候 xff0c 处理无效员工的id时就会出现错误 比如 xff1a 创建一个程序检索某个员工的工龄 a 创建一个函数GET SERVICE YRS xff0c 检索某个员工总的工龄 xff1b 此函数应该接受员工ID作为输
  • 两个大数(包括负数)相加

    分析 xff1a 当这两个大数为正数时 xff0c 我们可以将字符转化为数字相加 xff0c 再加进位talg xff0c 有进位为1 xff0c 否则为0 xff1b 两个为负数则与正数相似 xff0c 为一正一负时 xff0c 我们可以
  • WRF模式运行的流程以及简单错误的避免

    前提安装好 WPS 43 WRF 43 WRFDomainWizard等组件 一 xff0c WPS 1 xff0c geogrid exe 准备静态数据 地理数据 2 xff0c ungrib exe 解压强迫场资料 气象数据 3 xff
  • 两台计算机之间的直连

    1 xff0c 直连线的要求 xff0c 需要交叉线 2 xff0c 在网络里打开适配器选项 xff0c 右击以太网 xff0c 打开属性 xff0c 双击IP4 xff0c 如图所示 IP地址设置如上图 3 xff0c 另一台计算机的设置
  • MP3转码PCM

    支持aac和mp3转码 xff0c 主要是dst nb sample的计算 xff0c aac大致为1024 xff0c MP3为1152 xff0c static int dst nb samples 61 0 define SWR in
  • RISC-V MCU 导盲手套

    RISC V MCU 导盲手套 关于本文队伍名称第一部分 设计概述1 1 设计目的1 2 应用领域1 3 主要技术特点1 4 关键性能指标1 5 主要创新点 第二部分 系统组成及功能说明2 1 整体介绍2 2 各模块介绍 第三部分 完成情况