1
0
Fork 0

Compare commits

...

No commits in common. "master" and "main" have entirely different histories.
master ... main

161 changed files with 64827 additions and 68 deletions

378
.gitignore vendored Normal file
View File

@ -0,0 +1,378 @@
##
## PROJECT: Mouri Internal Library Essentials
## FILE: .gitignore
## PURPOSE: The root .gitignore file for Mile.Project Project
##
## LICENSE: The MIT License
##
## DEVELOPER: Mouri_Naruto (Mouri_Naruto AT Outlook.com)
##
##
## Ignore Mile.Project specific temporary files, build results,
## and files generated by popular Visual Studio add-ons.
##
Output/
##
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

View File

@ -0,0 +1,25 @@
**Fusion360 使用教程**
## **一、场景基本的控制**
**1.1 场景的旋转:**Shift + 鼠标左键
## 二、工具的基本使用
**2.1 曲面工具:**
通过二维的轮廓然后360°旋转所生成的实体。需要指定1旋转轴 2轮廓 两个信息实现曲面的生成。
## **三、模型的导出**
fusion360采用的是项目管理的方式在下图中我们可以看到有Admin Project和BalanceCar两个项目这些项目默认是云端同步的。
<img src="./Image/Project_All.png" alt="image-20220917192141176" style="zoom:33%;" />
在项目中选择模型右键选择导出可以导出Fusion360的文件格式。
<img src="./Image/Project_BalanceCar.png" alt="image-20220917192224716" style="zoom:45%;" />
在导出对话框中可以将模型导出到本地文件夹
<img src="./Image/Model_Export.png" alt="image-20220917192246893" style="zoom:33%;" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

View File

@ -0,0 +1,176 @@
# Kotlin调用Jni的写法
## 一、安装CMake和NDK
在android studio的设置中安装Cmake安装Cmake的时候注意cmake的版本。如果忘记CMake的版本那么可以通过Android SDK Locatio目录中查看CMake的版本。如下图所示的CMake和NDK。
![image-20230221221558825](E:\技术武器库\技术开发笔记\Android开发笔记\Image\image-20230221221558825.png)
## 二、创建工程
选择一个带 Native C++ 支持的工程,如下图所示:
![image-20230221223742943](E:\技术武器库\技术开发笔记\Android开发笔记\Image\image-20230221223742943.png)
## 三、配置 ndk 目录
在文件 local.properties 中加入 ndk 的配置
## 四、目录结构
以下文件都是自动生成的
![image-20230221223834839](E:\技术武器库\技术开发笔记\Android开发笔记\Image\image-20230221223834839.png)
## 五、配置模块 build.gradle
```shell
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig {
applicationId "com.lujianfei.androidjnicall"
minSdkVersion 26
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
version "3.10.2"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.core:core-ktx:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}
```
## 六、配置CMakeLists.txt和native-lib.cpp
```
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
```
```C++
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL
Java_com_lujianfei_androidjnicall_MainActivity_stringFromJNI(
JNIEnv* env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
```
## 七、Activity调用
```kotlin
package com.lujianfei.androidjnicall
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Example of a call to a native method
sample_text.text = stringFromJNI()
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
external fun stringFromJNI(): String
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -0,0 +1,103 @@
# 安卓开发环境配置问题
## 一、gradle的问题
由于国内网络环境的问题导致gradle经常没有办法正常下载从而难以正常构建Android程序。
## 1.1 gradle下载失败的问题
Android Studio首次创建项目或其他操作时会更新Gradle由于一些原因会导致下载失败就会提示ERRORGradle project sync failed。解决办法如下
1.根据报错提示的链接直接下载gradle-xxxxx.zip可以通过浏览器在 https://services.gradle.org/distributions/ 下载对应的版本。
![image-20231124132205455](./Image/image-20231124132205455.png)
如上图所示可以看到Android Studio正在下载gradle-8.0-bin.zip, 如果反复失败,可以通过上面的网址直接通过浏览器下载(如果不能访问可能需要使用科学上网),在网页中,我们可以找到对应的下载链接。:
<img src="./Image/image-20231124132430205.png" alt="image-20231124132430205" style="zoom: 50%;" />
2.虽然AndroidStudio Gradle下载失败但是会在你的C盘创建一个文件夹如 C:\Users(你的用户名).gradle\wrapper\dists\gradle-6.5-bin\xxxxxxx(最后一级目录,每个人的文件名可能不一样)
<img src="/Image/image-20231124132703141.png" alt="image-20231124132703141" style="zoom:50%;" />
我们将步骤1中下载号的gradle-8.0-bin.zip复制到存在gradle-8.0-bin.zip.lck和gradle-8.0-bin.zip.part文件的文件夹中。
3.修改Android Studio的gradle-wrapper文件
<center>
<img src="./Image/image-20231124133122986.png" alt="image-20231124133122986" style="zoom:50%;" />
</center>
修改的方式如下不同环境下路径存在不同根据实际情况调整即可重要的是要正确映射gradle的位置。
```shell
# Fri Nov 24 11:56:39 CST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
# 这是修改后的distributionUrl,把原先的网络地址映射为本地地址,程序通过本地地址下载
distributionUrl=file:///C:/Users/admin/.gradle/wrapper/dists/gradle-8.0-bin/ca5e32bp14vu59qr306oxotwh/gradle-8.0-bin.zip
# 下面是原地址
#distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
```
4.最后重启AndroidStudio或者点击Sync Now就可以了。
## 二、Maven仓库配置问题
目前最新版本的Android Studio的依赖配置和旧版本不太一样。一般来说如果采用默认的仓库配置下载速度过慢同时容易失败。
```shell
# 旧版
pluginManagement {
repositories {
//新增这 4 个
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/google/' }
maven { url 'https://maven.aliyun.com/repository/jcenter/' }
maven { url 'https://maven.aliyun.com/repository/central/' }
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
//新增这 4 个
maven { url 'https://maven.aliyun.com/repository/public/' }
maven { url 'https://maven.aliyun.com/repository/google/' }
maven { url 'https://maven.aliyun.com/repository/jcenter/' }
maven { url 'https://maven.aliyun.com/repository/central/' }
google()
mavenCentral()
}
}
rootProject.name = "helloworld"
include ':app'
# 最新版 maven写法发生了改变 maven { url 'https://jitpack.io' } => maven { url = uri("https://jitpack.io") }
pluginManagement {
repositories {
maven { url = uri("https://maven.aliyun.com/repository/public/") }
maven { url = uri("https://maven.aliyun.com/repository/google/") }
maven { url = uri("https://maven.aliyun.com/repository/jcenter/") }
maven { url = uri("https://maven.aliyun.com/repository/central/") }
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
maven { url = uri("https://maven.aliyun.com/repository/public/") }
maven { url = uri("https://maven.aliyun.com/repository/google/") }
maven { url = uri("https://maven.aliyun.com/repository/jcenter/") }
maven { url = uri("https://maven.aliyun.com/repository/central/") }
google()
mavenCentral()
}
}
```

View File

@ -0,0 +1,19 @@
## Android引入其他工程
在安卓开发中,我们为了开发方便,所以需要引入其他的已经封装好的模块。如下所示:
<img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230211150717050.png" alt="image-20230211150717050" style="zoom: 50%;" />
在app工程中需要用到libsmb库提供的smb管理和访问的功能。需要在两个地方进行配置。首先是app工程目录下的settings.gradle中配置。
```shell
# settings.gradle的配置是编译器包含libsmb
rootProject.name = "My Application"
include ':app'
include ':libsmb'
# 在build.gradle中添加依赖选项
implementation fileTree(include: ['*.jar'], dir: 'libs')
...
implementation project(':libsmb')
```

View File

@ -0,0 +1,16 @@
## Android 播放器使用
### 一、调用第三方视频播放器
Android通过Intent调用第三方播放器通过Url播放视频。
```java
// 启动第三方播放器
Intent intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse(http), "video/*");
startActivity(intent);
```
### 二、Exo播放器的使用

View File

@ -0,0 +1,173 @@
# Android 线程池ThreadPoolExecutor 的使用和封装kotlin
```java
// 传统开启线程方式
Thread(Runnable {
//to do异步请求
}).start()
```
**1.使用new Thread()创建线程存在的问题**
1. 如果在一个list每一个item都创建一个Threadlist量大的话会大量创建Thread导致内存抖动GC频繁的回收。要知道GC的回收是在主线程的这样会导致卡顿。
2. 线程过多导致各个线程竞争抢夺CPU执行权线程的频繁切换导致效率的降低。
3. ListView的每一个item滑出窗口线程无法停止也无法控制。
**2.使用线程池的好处**
1. 重用已经创建的好的线程避免频繁创建进而导致的频繁GC
2. 控制线程并发数,合理使用系统资源,提高应用性能
3. 可以有效的控制线程的执行,比如定时执行,取消执行等
**3.创建线程池 ThreadPoolExecutor 7个参数**
- corePoolSize 线程池中核心线程的数量
- maximumPoolSize 线程池中最大线程数量,等待队列的任务塞满了之后,才会触发开启非核心线程,直到总线程数达到 maximumPoolSize
- keepAliveTime 非核心线程的超时时长当系统中非核心线程闲置时间超过keepAliveTime之后则会被回收。如果ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true则该参数也作用于核心线程的超时时长
- unit 第三个参数的单位,有纳秒、微秒、毫秒、秒、分、时、天等
- workQueue 线程池中的任务队列该队列主要用来存储已经被提交但是尚未执行的任务。存储在这里的任务是由ThreadPoolExecutor的execute方法提交来的。这个队列任务塞满了之后才会触发开启非核心线程
- threadFactory 为线程池提供创建新线程的功能,这个我们一般使用默认即可
- handler 拒绝策略当线程无法执行新任务时一般是由于线程池中的线程数量已经达到最大数或者线程池关闭导致的默认情况下当线程池无法处理新线程时会抛出一个RejectedExecutionException。
**4.线程池 ThreadPoolExecutor 的方法**
1. shutDown() 关闭线程池,不影响已经提交的任务
2. shutDownNow() 关闭线程池,并尝试去终止正在执行的线程
3. allowCoreThreadTimeOut(boolean value) 允许核心线程闲置超时时被回收
```java
import com.orhanobut.logger.Logger
import java.util.concurrent.*
/***
* Created by LiangJingJie on 2019/5/16.
* 线程池封装类
* */
class ThreadPoolManager private constructor() {
private var threadPoolMap = hashMapOf<String, ThreadPoolExecutor>()
/**
* cpu数量
* */
private val CPU_COUNT = Runtime.getRuntime().availableProcessors()
/**
* 核心线程数为手机CPU数量+1
* */
private val CORE_POOL_SIZE = CPU_COUNT + 1
/**
* 最大线程数为手机CPU数量×2+1
* */
private val MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1
/**
* 线程活跃时间 秒,超时线程会被回收
* */
private val KEEP_ALIVE_TIME: Long = 3
/**
* 等待队列大小
* */
private val QUEUE_SIZE = 128
companion object {
fun getInstance() = SingleHolder.SINGLE_HOLDER
}
object SingleHolder {
val SINGLE_HOLDER = ThreadPoolManager()
}
/**
* @param tag 针对每个TAG 获取对应的线程池
* @param corePoolSize 线程池中核心线程的数量
* @param maximumPoolSize 线程池中最大线程数量
* @param keepAliveTime 非核心线程的超时时长,
* 当系统中非核心线程闲置时间超过keepAliveTime之后则会被回收
* 如果ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true
则该参数也作用于核心线程的超时时长
* @param unit 第三个参数的单位,有纳秒、微秒、毫秒、秒、分、时、天等
* @param queueSize 等待队列的长度 一般128 (参考 AsyncTask)
* workQueue 线程池中的任务队列,
该队列主要用来存储已经被提交但是尚未执行的任务。
存储在这里的任务是由ThreadPoolExecutor的execute方法提交来的。
* threadFactory 为线程池提供创建新线程的功能,这个我们一般使用默认即可
*
* 1.ArrayBlockingQueue这个表示一个规定了大小的BlockingQueueArrayBlockingQueue的构造函数接受一个int类型的数据
* 该数据表示BlockingQueue的大小存储在ArrayBlockingQueue中的元素按照FIFO先进先出的方式来进行存取。
* 2.LinkedBlockingQueue这个表示一个大小不确定的BlockingQueue在LinkedBlockingQueue的构造方法中可以传
* 一个int类型的数据这样创建出来的LinkedBlockingQueue是有大小的也可以不传不传的话
* LinkedBlockingQueue的大小就为Integer.MAX_VALUE
* */
private fun getThreadPool(tag: String): ThreadPoolExecutor {
var threadPoolExecutor = threadPoolMap[tag]
if (threadPoolExecutor == null) {
threadPoolExecutor = ThreadPoolExecutor(
CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE,
KEEP_ALIVE_TIME,
TimeUnit.SECONDS,
ArrayBlockingQueue<Runnable>(QUEUE_SIZE),
Executors.defaultThreadFactory(),
RejectedExecutionHandler { _, _ ->
Logger.d("$ThreadPoolManager RejectedExecutionHandler----")
}
)
//允许核心线程闲置超时时被回收
threadPoolExecutor.allowCoreThreadTimeOut(true)
threadPoolMap[tag] = threadPoolExecutor
}
return threadPoolExecutor
}
/**
* @param tag 针对每个TAG 获取对应的线程池
* @param runnable 对应的 runnable 任务
* */
fun removeTask(tag: String, runnable: Runnable) {
getThreadPool(tag)?.queue?.remove(runnable)
}
/**
* @param tag 针对每个TAG 获取对应的线程池
* @param runnable 对应的 runnable 任务
* */
fun addTask(tag: String, runnable: Runnable) {
getThreadPool(tag).execute(runnable)
}
/**
* @param tag 针对每个TAG 获取对应的线程池
* 取消 移除线程池
* */
//shutDown():关闭线程池后不影响已经提交的任务
//shutDownNow():关闭线程池后会尝试去终止正在执行任务的线程
fun exitThreadPool(tag: String) {
var threadPoolExecutor = threadPoolMap[tag]
if (threadPoolExecutor != null) {
threadPoolExecutor.shutdownNow()
threadPoolMap.remove(tag)
}
}
}
```

View File

@ -0,0 +1,27 @@
```java
// 给定视频的URL
final String url = videoUrl;
// 调用Android的MediaMetadataRetriever获取视频封面
final MediaMetadataRetriever mmr = new MediaMetadataRetriever();
new Thread(() -> {
Map<String, String> headers = new HashMap<>() ;
// 指定header和url
mmr.setDataSource(url, headers);
// 设置截取视频第10秒钟内容
Long sec = 10L;
// sec转us单位
Long msec = sec * 1000L;
Long us = msec * 1000L;
final Bitmap image = mmr.getFrameAtTime(us, MediaMetadataRetriever.OPTION_CLOSEST_SYNC);
// 更新imageview显示图片
runOnUiThread(() -> {
ImageView tv = findViewById(R.id.imageView);
tv.setImageBitmap(image);
});
// 释放mmr断开连接
mmr.release();
}).start();
```
HTTP视频请求Range的计算方法

View File

@ -0,0 +1,16 @@
app : 程序的主页面(MainActivity),程序的启动页面(SplashActivity)
AppConfig模块 负责App的功能设置
**播放器显示控制器逻辑:**
DanDanVideoPlayer -> onKeyDown检测KeyEvent事件类型 -> {1、音量加 2、音量减 3、其他 触发控制View}
DanDanVideoPlayer -> 触摸检测 检测TouchEvent事件类型 -> {左上下滑动:亮度 右上下滑动:音量 横向滑动:视频进度}
自动更新功能BaseApplication(应用启动时的单例) => EMASHelper(阿里巴巴EMAS应用研发平台) => 发起弹窗和下载
**SMB文件浏览逻辑**
位置local_component/ui/fragment/media/MediaFragment

View File

@ -0,0 +1,13 @@
# DanDanPlay主页显示
## HomeFragmentViewModel
**位置:**anime_component/ui/fragment/home/HomeFragment
**核心:** 首页的显示Fragement
# MediaFragment
**位置:**local_component/ui/fragment/meda/MediaFragment
核心主页媒体的显示Fragement

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@ -0,0 +1,61 @@
# Kotlin 操作Layout控件
在Android Acitivity开发中传统的java开发中findviewbyid。在kotlin中有两种写法都可以操作layout控件。
## 一、传统写法(不推荐)
不推荐的原因主要是麻烦满屏幕都是findViewById非常的繁琐。
```kotlin
package com.geek.motion
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var textView = findViewById<TextView>(R.id.textView)
textView.setText("Hello Kotlin")
}
}
```
## 二、省略写法(推荐)
下面采用的是省略写法注意需要引入import kotlinx.android.synthetic.main.activity_main.*
```kotlin
package com.geek.motion
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textView.text = "Hello kotlin"
}
}
```
如果在引用import kotlinx.android.synthetic.main.activity_main.*时报错注意在build.gradle中添加**'kotlin-android-extensions'**
```shell
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
// 添加
id 'kotlin-android-extensions'
}
android {
compileSdk 32
...
```

View File

@ -0,0 +1,26 @@
```kotlin
Unit : 相当于JAVA的void
```
kotlin中when的用法
```kotlin
fun foo(value: Int): String {
return when (value) {
0 -> {
"Zero"
}
1 -> {
"One"
}
2 -> {
"Two"
}
else -> {
"Other"
}
}
}
```

View File

@ -0,0 +1,66 @@
# Kotlin测量经过的时间
## 一、使用 `System.nanoTime()` 功能
在 Kotlin 中测量程序运行时间的推荐方法是 `System.nanoTime()`,它以纳秒精度返回 JVM 时间源的当前值。
```kotlin
fun main() {
val begin = System.nanoTime()
/* 代码开始 */
// 休眠 2 秒
Thread.sleep(2000)
/* 代码结束 */
val end = System.nanoTime()
println("Elapsed time in nanoseconds: ${end-begin}")
}
```
## 二、使用 `System.currentTimeMillis()` 功能
您还可以使用 `System.currentTimeMillis()`,但结果可能不是那么准确。
```kotlin
fun main() {
val begin = System.currentTimeMillis()
/* 代码开始 */
// 休眠 2 秒
Thread.sleep(2000)
/* 代码结束 */
val end = System.currentTimeMillis()
println("Elapsed time in milliseconds: ${end-begin}")
}
```
这是使用的替代解决方案 `Instant.now()` 内部使用 `System.currentTimeMillis()`.
```kotlin
import java.time.Instant
fun main() {
val begin = Instant.now().toEpochMilli()
/* 代码开始 */
// 休眠 2 秒
Thread.sleep(2000)
/* 代码结束 */
val end = Instant.now().toEpochMilli()
println("Elapsed time in milliseconds: ${end-begin}")
}
```
## 三.使用 `Date.getTime()` 功能
```kotlin
import java.util.Date
fun main() {
val begin = Date().time
/* 代码开始 */
// 休眠 2 秒
Thread.sleep(2000)
/* 代码结束 */
val end = Date().time
println("Elapsed time in milliseconds: ${end-begin}")
```

View File

@ -0,0 +1,122 @@
## Android Smb开发笔记
### 一、SMB的基本操作
Android的SMB开发会用到jcifs这个库。这个库提供了SMB的底层操作功能。
根据URI打开一个SMB。
```java
// 指定SMB的路径
String uri = "smb://administrator:351002@192.168.31.52/H/琅琊榜 全54集 1080P/";
// 网络的相关操作必须通过新线程的方式启动否则会触发Android的错误
new Thread(new Runnable() {
@Override
public void run() {
try {
// 根据uri打开SmbFile
SmbFile smbFile = new SmbFile(uri);
String fileName = smbFile.getName();
Log.d("Test", fileName);
// 控制台打印SMB路径下的文件
try{
String[] FileList = smbFile.list();
for (String s : FileList) {
Log.d("Test", s);
}
}catch (SmbException e){
e.printStackTrace();
}
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
}).start();
```
### 二、SMB转HTTP
当我们把SMB的Uri提供给播放器后播放器会请求GET视频。对于一个完整的视频Http的请求如下所示。
如果我们在解析请求头的时候没有收到请求的范围信息,那么默认就是返回全部的内容。
```shell
GET /smb/192.168.31.52/I/XXX.mp4 HTTP/1.1
User-Agent: ExoPlayerTime/1.0 (Linux;Android 12) ExoPlayerLib/2.7.1
Accept-Encoding:identity
Host: 127.0.0.1:2222
Connection: Keep-Alive
```
当我们拖动进度条的时候此时视频不是从0开始播放所以视频播放器会请求包含Range的信息
```Shell
GET /smb/192.168.31.52/I/XXX.mp4 HTTP/1.1
User-Agent: ExoPlayerTime/1.0 (Linux;Android 12) ExoPlayerLib/2.7.1
Range: bytes=1207598076-
Accept-Encoding:identity
Host: 127.0.0.1:2222
Connection: Keep-Alive
```
上述情况下如果我们收到包含Range信息的请求时返回的时候就需要额外指定一些信息。HTTP的返回有如下的规则
```Java
// 如果用户拖动了进度条那么HttpRequest就会包含Range信息
// 1.此时contentLength = end - st, 需要返回Content-Length:头
"Content-Length: " + contentLength + "\r\n"
// 2.此时请求的是部分的信息所以返回的Responce的类型是206表示部分内容
HttpStatus.PARTIAL_CONTENT = 206
```
```Java
// 获取文件长度bytes
long contentLen = file.length();
// 从文件获得输入流
InputStream contentIn = file.getInputStream();
// 检查输入数据流是否正常
if (contentLen <= 0 || contentIn == null) {
httpReq.returnBadRequest();
return;
}
// 创建Http返回请求
HTTPResponse httpRes = new HTTPResponse();
// 指定视频数据格式
httpRes.setContentType("video/mpeg4");
if(startFrom == 0 && endAt == 0){
// 请求没有范围信息则返回全部内容状态OK(200)表示全部内容
httpRes.setStatusCode(HTTPStatus.OK);
}else if(startFrom > 0){
// 如果是包含RangeCotent,则需要返回PARTIAL_CONTENT(206)
httpRes.setStatusCode(HTTPStatus.PARTIAL_CONTENT);
httpRes.setContentRange(startFrom,endAt, contentLen);
}
// 设置内容总长度
httpRes.setContentLength(contentLen);
// 指定内容数据流
httpRes.setContentInputStream(contentIn);
// HttpReq提交数据
httpReq.post(httpRes);
contentIn.close();
```
HTTP 视频请求
```Java
// 已知信息
File_length = 2794939639
File_Range_st = bytes=2792308814
// 分析
st = 2792308814
// 由于文件长度是2794939639所以换算的索引是0~2794939639-1
ed = 2794939639 - 1
content_lenght = ( ed - st + 1 )= File_length - 1 - st + 1
= ed - st
```

View File

@ -0,0 +1,16 @@
#### 依赖 git repository
依赖 Github 上的一个插件:
```text
dependencies:
bloc:
git:
url: https://github.com/felangel/bloc.git
ref: bloc_fixes_issue_110
path: packages/bloc
```
- urlgithub 地址
- ref表示git引用可以是 **commit hash, tag** 或者 **branch**
- path如果 git 仓库中有多个软件包,则可以使用此属性指定软件包

View File

@ -0,0 +1,22 @@
# Flutter常见问题
基本上flutter安装官方教程进行环境安装即可但是有些细节会导致安装出现问题。常见问题如下
## 一、flutter doctor长时间等待问题
产生的原因1) Powershell没有采用管理员权限运行 2) 没有采用国内镜像源
1、先配置国内镜像仓库源
```shell
# 参考网址https://flutter.cn/community/china
# 下面命令不一定生效,可以采用手动的方式在环境变量中增加变量名和变量值
# 配置默认国内镜像源
$env:PUB_HOSTED_URL="https://pub.flutter-io.cn";
$env:FLUTTER_STORAGE_BASE_URL="https://storage.flutter-io.cn"
# 配置清华源
$env:PUB_HOSTED_URL="https://mirrors.tuna.tsinghua.edu.cn/dart-pub";
$env:FLUTTER_STORAGE_BASE_URL="https://mirrors.tuna.tsinghua.edu.cn/flutter"
```
2、采用管理员身份运行Powershell或者cmd

View File

@ -1,67 +0,0 @@
### 1.git安装教程
教程链接:<a href="https://zhuanlan.zhihu.com/p/443527549">https://zhuanlan.zhihu.com/p/443527549</a>
### <font color = "red">2.git基本操作命令</font>
#### 2.1 git常用命令
> - git init 初始化项目
> - git status 查看当前目录下文件的状态
> - git add (文件名 | .)添加到暂存盘,文件名代表某文件,"."代表所有文件
> - git commit -m "备注" 提交到git本地仓库产生新版本引号中的备注必须写
> - git log 查看所有提交的记录
> - git clone 链接 克隆远程仓库,进行连接
> - git checkout -b [branch] 新建一个分支,并切换到该分支
> - git checkout [branch] 切换到某分支
> - git branch -d [branch-name] 删除分支
> - git merge [branch] 合并指定分支到当前分支
> - git push 将本地仓库push到远程仓库
#### 2.2 流程详解
1.打开想要上传项目的文件根目录右击Git Bash Here输入命令 **git init**:
``` $ git init ```
![image-20240507131840732](D:\Linux+git笔记\Linux+git学习笔记\Images\git init.png)
发现在根目录中出现了一个 **.git** 文件表明此项目已被git管理。
2.通过` git clone "仓库链接"`与远程仓库进行连接:
![image-20240507131741797](D:\Linux+git笔记\Linux+git学习笔记\Images\git clone.png)
3. 连接成功后,添加项目到暂存区,并提交项目到本地仓库,中间可以使用 **git status** 命令查看文件状态:![image-20240507131929421](D:\Linux+git笔记\Linux+git学习笔记\Images\git status.png)![image-20240507131951291](C:\Users\dd\AppData\Roaming\Typora\typora-user-images\image-20240507131951291.png)![image-20240507132003856](C:\Users\dd\AppData\Roaming\Typora\typora-user-images\image-20240507132003856.png)
当使用用` git status` 查看状态显示“没有需要提交的,工作树干净”时,就说明项目已经全部提交至本地仓库。
4. 使用命令 `git checkout -b dev` 创建dev分支并切换到该分支下在分支上进行操作在这之前或之后都可以使用命令 `git branch` 查看仓库的分支都有哪些![image-20240507133520475](D:\Linux+git笔记\Linux+git学习笔记\Images\git checkout.png)
5. 操作这么多命令后,可能已经断开了与远程的连接,使用命令 `git remote -v`查看,如果为空,则使用 `git remote add origin 链接` 再次与远程仓库进行连接![image-20240507134004040](D:\Linux+git笔记\Linux+git学习笔记\Images\git remote.png)
出现如上图所示,则重新连接成功!
6. 把master分支合并到dev分支进行add和commit最后push到远程
7. 查看项目是否上传成功。
### <font color="red">beyond compare 解决冲突</font>
1. 安装beyond compare
2. 在git 仓库中配置
```
git config --local merge.tool bc4
git config --local mergetool.path 软件安装目录
git config --local mergetool.keepBackup false
```
3. 应用bc 解决冲突
```
git mergetool
```

View File

Before

Width:  |  Height:  |  Size: 118 KiB

After

Width:  |  Height:  |  Size: 118 KiB

View File

@ -1,6 +1,6 @@
### 1.Linux根文件系统 ### 1.Linux根文件系统
![image-20240429174454787](D:\Linux+git笔记\Linux+git学习笔记\Images\image-20240429174454787.png) ![image-20240429174454787](C:\Users\dd\AppData\Roaming\Typora\typora-user-images\image-20240429174454787.png)
- /bin - /bin
是binary的缩写这个目录存放着最经常使用的命令通过上方桌面可以看到bin文件夹有个箭头是链接到 /usr/bin下相当于快捷方式进入/bin和/usr/bin下是一模一样的。 是binary的缩写这个目录存放着最经常使用的命令通过上方桌面可以看到bin文件夹有个箭头是链接到 /usr/bin下相当于快捷方式进入/bin和/usr/bin下是一模一样的。

View File

@ -0,0 +1,6 @@
<font face="逐浪新宋">我是逐浪新宋</font><font face="逐浪圆体">我是逐浪圆体</font><font face="逐浪花体">我是逐浪花体</font><font face="逐浪像素字">我是逐浪像素字</font><font face="逐浪立楷">我是逐浪立楷</font><font color=red>我是红色</font><font color=#008000>我是绿色</font><font color=yellow>我是黄色</font><font color=Blue>我是蓝色</font><font color= #871F78>我是紫色</font><font color= #DCDCDC>我是浅灰色</font><font size=5>我是尺寸</font><font size=10>我是尺寸</font><font face="逐浪立楷" color=green size=10>我是逐浪立楷绿色尺寸为5</font> 作者:字库大师程序员发哥 https://www.bilibili.com/read/cv5975926/ 出处bilibili<font face="逐浪新宋">我是逐浪新宋</font><font face="逐浪圆体">我是逐浪圆体</font><font face="逐浪花体">我是逐浪花体</font><font face="逐浪像素字">我是逐浪像素字</font><font face="逐浪立楷">我是逐浪立楷</font><font color=red>我是红色</font><font color=#008000>我是绿色</font><font color=yellow>我是黄色</font><font color=Blue>我是蓝色</font><font color= #871F78>我是紫色</font><font color= #DCDCDC>我是浅灰色</font><font size=5>我是尺寸</font><font size=10>我是尺寸</font><font face="逐浪立楷" color=green size=10>我是逐浪立楷绿色尺寸为5</font> 作者:字库大师程序员发哥 https://www.bilibili.com/read/cv5975926/ 出处bilibili
<font size=10>字体大小size=10</font>

View File

@ -0,0 +1,422 @@
---
---
# Example for OneDark Theme
[toc]
## Headers
### h3
Markdown is a lightweight markup language with plain-text-formatting syntax. Its design allows it to be converted to many output formats, but the original tool by the same name only supports HTML. Markdown is often used to format readme files, for writing messages in online discussion forums, and to create rich text using a plain text editor.
#### h4
Since the initial description of Markdown contained ambiguities and unanswered questions, the implementations that appeared over the years have subtle differences and many come with syntax extensions.
##### h5
In MediaWiki, it is implemented in the currently unmaintained MarkdownExtraParser parser function extension
###### h6
Implementations of Markdown are available for over a dozen programming languages.
## Quote
> Most UI components including tooltip, dialog and buttons are painted by HTML. And you only need to change those part when you find the UI components are incompatible with your editor theme after finishing steps above. HTML files from the toolkit includes most common UI components for you to easily debug.
## Font Style
**Bold**, *italic*, ~~delete~~
<u>underline</u>, [Link](typora.io)
H~2~O, E=mc^2^
<span style="color:red">colored text</span>, ==highlight==
emoji: :smile:
- [ ] checkbox
## Codeblock
```python
# hello_world.py
class HelloWorld():
def __init__(self):
self.text='hello world!'
def show(self,word):
print(f'{word}, {self.text}')
test=HelloWorld()
test.show()
```
Run terminal then enter: `python hello_world.py`
## KBD
* bold<kbd>Ctrl/Command</kbd> + <kbd>B</kbd>
* italic<kbd>Ctrl/Command</kbd> + <kbd>I</kbd>
## MathJax
Given two populations, $x_1$ and $x_2$ , with logistic dynamics, the LotkaVolterra formulation adds an additional term to account for the species' interactions. Thus the competitive LotkaVolterra equations are:
$$
\begin{cases}
\cfrac{dx_1}{dt}=r_1x_1\bigg(1-\cfrac{x_1+\alpha_{12} x_2}{K_1}\bigg)\\
\cfrac{dx_2}{dt}=r_2x_2\bigg(1-\cfrac{x_2+\alpha_{21} x_1}{K_2}\bigg)
\end{cases}
$$
Here, $\alpha_{12}$ represents the effect species 2 has on the population of species 1 and $\alpha_{21}$represents the effect species 1 has on the population of species 2.
## Order
1. first item
2. second item
1. first item
2. second item
3. third item
---
* first item
* second item
* first item
* first item
* fourth item
## Table
| Cinderella | 11 | glass | transparent |
| :----------- | ---: | :---------- | :---------- |
| Name | Size | Material | Color |
| All Business | 9 | leather | brown |
| Roundabout | 10 | hemp canvas | natural |
## Footnote
You can create footnotes like this[^fn1] and this[^fn2].
[^fn1]: Here is the **text** of the first ***\*footnote\****.
[^fn2]: Here is the **text** of the second ***\*footnote\****.
## Image, Video
<img src="D:\Project\typora-onedark-theme\example\image.jpg" alt="Cosmos08" style="zoom:15%;" />
<video src="./video.mp4" />
<table>
<tr>
<td>Bash command
</td>
<td>Description
</td>
</tr>
<tr>
<td>ls
</td>
<td>List directory contents
</td>
</tr>
<tr>
<td>cd
</td>
<td>Change directory
</td>
</tr>
<tr>
<td>cp
</td>
<td>Copy files
</td>
</tr>
<tr>
<td>mv
</td>
<td>Move files
</td>
</tr>
</table>
## Graph
### sequence
```sequence
Alice->Bob: Hello Bob, how are you?
Note right of Bob: Bob thinks
Bob-->Alice: I am good thanks!
```
### flow
```flow
st=>start: Start
op=>operation: Your Operation
cond=>condition: Yes or No?
e=>end
st->op->cond
cond(yes)->e
cond(no)->op
```
### mermaid
#### Flowchart
```mermaid
graph TD
Start --> Stop
```
```mermaid
graph LR
A([A]) --- B(B) -- C --- C{C}
C -- D --> D[[D]]
C -.->|E| E[E]
C -. F .-> F[(F)]
C ==>|G| G((G))
B == edge ==> H>H]
B --> I{{I}}
subgraph sub [subgraph]
I -->|J| J[/J/]
I -->|K| K[\K\]
I -->|L| L[\L/]
I -->|M| M[/M\]
end
```
#### Sequence diagram
```mermaid
%% Example of sequence diagram
sequenceDiagram
participant A
participant B
participant C
Note right of B: note
Note over A,B: note
A->B: a
activate B
A-->B: b
activate B
A->>B: c
deactivate B
A-->>B: d
deactivate B
rect rgba(128,0,0,0.5)
A-xA: e
end
loop loop
A--xB: f
end
alt alt
B->>A: g
else else
B->>A: h
end
par par
A->C: i
and and
A->B: j
par nest
B->C: k
end
end
```
#### Class diagram
```mermaid
classDiagram
A <|-- B: label
A "1" *-- "1.." C
A "*" o-- "0..1" D
C <-- E
C -- F
D <.. G
D <|.. H
D .. I
A: +int i1
A: -String s1
A: #List~int~ l1
A: ~f1(arg) bool
A: +f2()*
A: +f3()$
class B {
<<enumeration>>
RED
GREEN
BLUE
}
class D {
<<interface>>
int i1
f1()
}
```
#### State diagram
```mermaid
stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
```
```mermaid
stateDiagram
state fork_state <<fork>>
state "This is A" as A
[*] --> fork_state
[*] --> D
D --> fork_state
note right of D
note for D
end note
note left of A: note for A
fork_state --> A
fork_state --> B
A --> C: trans
B --> C
C --> [*]
state C {
[*] --> C1: test
C1 --> C2
C2 --> C3
C3 --> [*]
state C2 {
[*] --> C21
C21 --> [*]
state C21 {
[*] --> C211
}
}
C1: This is C1
--
[*] --> T
}
```
```mermaid
stateDiagram-v2
state fork_state <<fork>>
state "This is A" as A
[*] --> fork_state
[*] --> D
D --> fork_state
note right of D
note for D
end note
note left of A: note for A
fork_state --> A
fork_state --> B
A --> C: trans
B --> C
C --> [*]
state C {
[*] --> C1: test
C1 --> C2
C2 --> C3
C3 --> [*]
state C2 {
[*] --> C21
C21 --> [*]
state C21 {
[*] --> C211
}
}
C1: This is C1
--
[*] --> T
}
```
#### Entity Relationship Diagram
```mermaid
erDiagram
A |o--o| B : b
B ||--|| C : c
A }o..o{ D : d
D }|..|{ E : e
```
#### User Journey Diagram
```mermaid
journey
title My working day
section A
A1: 5: Me
A2: 3: Me
A3: 1: Me, Cat
A4: 2
A5: 4
```
#### Gantt
```mermaid
%% Example with selection of syntaxes
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Create tests for parser :crit, active, 3d
Future task in critical line :crit, 5d
Create tests for renderer :2d
Add to mermaid :1d
section Documentation
Describe gantt syntax :active, a1, after des1, 3d
Add gantt diagram to demo page :after a1 , 20h
Add another diagram to demo page :doc1, after a1 , 48h
section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page : 20h
Add another diagram to demo page : 48h
```
#### Pie Chart
```mermaid
pie
title Pie Chart
"A" : 1
"B" : 2
"C" : 3
"D" : 4
"E" : 5
"F" : 6
"G" : 7
"H" : 8
```

View File

@ -0,0 +1,9 @@
1.1 `MySQL`的内容查看
在`MySQL`中,部分内容可能是`json`结构,此时我们可以选择要查看的内容,然后选择文本功能,即可完整查看复杂的文本内容。
![Snipaste_2023-12-27_22-09-28](C:\Users\admin\Desktop\Snipaste_2023-12-27_22-09-28.png)
1.2 MySQL允许所有主机连接
https://blog.csdn.net/CoCo629vanilla/article/details/129008644

3
README.md Normal file
View File

@ -0,0 +1,3 @@
# Notes
技术开发笔记

View File

@ -0,0 +1,50 @@
# ESP内存和存储模型
ESP32-WROOM 规格说明书写到:
• 448 KB 的 ROM用于程序启动和内核功能调用
• 用于数据和指令存储的 520 KB 片上 SRAM • RTC 快速存储器,为 8 KB 的 SRAM可以在 Deep-sleep 模式下 RTC 启动时用于数据存储以及被主 CPU 访问
• RTC 慢速存储器,为 8 KB 的 SRAM可以在 Deep-sleep 模式下被协处理器访问
• 1 Kbit 的 eFuse其中 256 bit 为系统专用MAC 地址和芯片设置); 其余 768 bit 保留给用户程序, 这些 程序包括 flash 加密和芯片 ID
**1.1、ESP32的内存结构**
- IRAMinternal ram 内部RAM指的是集成到SoC内部的RAM
- DRAMdynamic ram 动态RAM特点就是容量大、价格低缺点就是上电后不能直接使用需要软件初始化后才可以使用。
```C
I (434) heap_init: Initializing. RAM available for dynamic allocation:
I (441) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (447) heap_init: At 3FFBC0E0 len 00023F20 (143 KiB): DRAM
I (454) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (460) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (466) heap_init: At 4008E7C4 len 0001183C (70 KiB): IRAM
```
从以上的输出结果来看ESP32的DRAM149KBIRAM一共195KB合并一共344KB。
**1.2 字节Bytes和KB**
观察ESP32生成的程序信息DRAM可用128KBIRAM可用70KB。
```
Total sizes:
DRAM .data size: 11532 bytes
DRAM .bss size: 37864 bytes
Used static DRAM: 49396 bytes ( 131340 available, 27.3% used)
Used static IRAM: 59330 bytes ( 71742 available, 45.3% used)
Flash code: 349355 bytes
Flash rodata: 296268 bytes
Total image size:~ 716485 bytes (.bin may be padded larger)
```
**Flash Code即代码域它通常是指编译器生成的机器指令这些内容会被存储到ROM区。** 大约有340KB
**RO-dataRead Only data即只读数据域它指程序中用到的只读数据这些数据被存储在ROM区因而程序不能被修改的内容。** 大约290KB。

View File

@ -0,0 +1,22 @@
# LVGL常用函数笔记
## 一、屏幕操作相关
**1.1 获取屏幕的对象**
```C
lv_obj_t * lv_scr_act(void) // 获取当前活动屏幕的指针
```
**1.2 在屏幕上创建对象**
```C
// 获取当前屏幕对象并创建对象
lv_obj_t* root_obj = lv_obj_create(lv_scr_act());
// 设置对象背景颜色
lv_obj_set_style_bg_color(root, lv_color_black(), 0);
// 设置对象背景透明度 Opacity透明度
lv_obj_set_style_bg_opa(root, LV_OPA_COVER, 0);
```
1.3

View File

@ -0,0 +1,19 @@
## 一、X-Track执行页面的Unload过程
**1.1 在PageView中不需要删除对象**
准确的来说应该是通过root节点创建的对象的是不需要删除的对于非root节点创建的对象如动画、style是需要在delete函数中删除的否则会造成内存泄漏。
```c
lv_obj_del_async(base->root);
base->root = nullptr;
base->priv.IsCached = false;
base->onViewDidUnload();
```
从上面的代码可以看出X-Track先执行root节点的删除然后再调用onViewDidUnload()函数。由于在删除父节点的时候子节点也会被删除所以不建议在PageView里面调用lv_obj_del()函数。
$$
y=k*(x-0)+b \\= k*(x-xt)+b = k*x-k*xt+b + k*xt
$$

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -0,0 +1,11 @@
Unity3D 对象的旋转
```C#
Debug.Log("position " + transform.position); //世界坐标的位置
Debug.Log("localPosition " + transform.localPosition); //相对于父位置的坐标 即把父物体当作自己的中心
Debug.Log("eulerAngles " + transform.eulerAngles);//世界坐标欧拉⾓度
Debug.Log("localEulerAngles " + transform.localEulerAngles);//相对于⽗级的变换的旋转欧拉⾓度
Debug.Log("localScale " + transform.localScale);//相对于父位置的缩放
Debug.Log("localRotation " + transform.localRotation);//相对于父位置的旋转
Debug.Log("rotation " + transform.rotation);//世界坐标的旋转
```

View File

@ -0,0 +1,33 @@
## Unity的基本操作
**一、场景的基本操作**
- 缩放:鼠标滚轮
- 旋转:鼠标箭头左键点击后拖动
- 拖动场景位置移动:鼠标滚轮按下
### **二、人物模型的控制**
**2.1 人物的结构和手动控制**
如下图所示一般来说3D人物模型的身体部分都是躯体的骨骼模型按照多叉树的结构组织的。对于每一部分的躯体部分都可以控制其平移、缩放、旋转等操作。
<img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220916003925721.png" alt="image-20220916003925721" style="zoom:45%;" />
完整的人物呈现如下图所示(默认状态):
<img src="./Image/Model_Default.png" style="zoom:50%;" />
对象的旋转、平移、缩放操作,可以通过窗口进行控制:
<div align=center><img src="./Image/Unity3D-Model-Transform.png" alt="image-20220916005017611" style="zoom:50%;" /></div>
设置手臂的Y轴旋转角度为-90°可以看到
<div align=center><img src="./Image/Model_UpperArm-90.png" style="zoom:50%;" /></div>
**2.2 人物脚本控制**

View File

@ -0,0 +1,16 @@
Matplotlib使用笔记
1、Matplotlib结合numpy绘制图形
```python
import numpy as np
from matplotlib import pyplot as plt
x = np.arange(1,11)
y = 2 * x + 5
plt.title("Matplotlib demo")
plt.xlabel("x axis caption")
plt.ylabel("y axis caption")
plt.plot(x,y)
plt.show()
```

View File

@ -0,0 +1,56 @@
# Numpy使用笔记
NumPy 全称为 Numerical Python是 Python 的一个以矩阵为主的用于科学计算的基础软件包。NumPy 和 Pandas、Matpotlib 经常结合一起使用所以被人们合称为数据分析三剑客。Numpy 中有功能强大的 ndarray 对象,能创建 N 维的数组,另外还提供很多通用函数,支持对数组的元素进行操作、支持对数组进行算法运算以及提供常用的统计函数。
相比 List 对象NumPy 数组有以下优势:
1. 这是因为列表 list 的元素在系统内存中是分散存储的,而 NumPy 数组存储在一个均匀连续的内存块中。这样数组计算遍历所有元素,不像列表 list 还需要对内存地址进行查找,从而节省了计算资源。
2. Numpy数组能够运用向量化运算来处理整个数组速度较快而 Python 的列表则通常需要借助循环语句遍历列表,运行效率相对来说要差。
3. NumPy 中的矩阵计算可以采用多线程的方式,充分利用多核 CPU 计算资源,大大提升了计算效率。
4. Numpy 使用了优化过的 C API运算速度较快。
## 一、数组创建和使用
**1.1、创建zeros数组**
```python
import numpy as np
# 创建1维数组
x1 = np.zeros(20)
# 打印一维数组
print(x1)
# 数组的赋值, 从0开始
for i in range(0,20):
x1[i] = i
print(str(x1[i]))
# 2维数组的创建
# 创建一个 3x4 的数组且所有值全为 0
x3 = np.zeros((3, 4), dtype=int)
print(x3)
# 创建一个 3x4 的数组且所有元素值全为 1
x4 = np.ones((3, 4), dtype=int)
print(x4)
# 创建一个 3x4 的数组,然后将所有元素的值填充为 2
x5 = np.full((3, 4), 2, dtype=int)
print(x5)
```
**1.2、创建随机数组**
```python
import numpy as np
# 创建2*2随机数组
lux_br_arr = np.random.random((2,2))
# 打印结果
print(lux_br_arr)
```
1.3 通过array_list创建数组
```python
import numpy as np
x_list = [1,2,3,4]
x = np.array(x_list)
print(x)
```

View File

@ -0,0 +1,213 @@
# Pandas-Dataframe使用笔记
## 一、Dataframe的读取和保存
**1.1 Dataframe导出csv**
```python
# Dataframe转CSV
xlsx_file.to_csv('F:/XXX/XXX.csv', encoding="utf-8-sig",header=True)
```
**1.2 Pandas读取xlsx**
```python
# xlsx_file_name 如:'F:/XXX/XXX.xlsx'
# 一般xlsx默认的sheet_name是Sheet1
xlsx_file = pd.read_excel(xlsx_file_name, sheet_name='Sheet1')
```
**1.3 Dataframe的创建**
dataframe可以通过读取csv或者xlsx等方式创建同时也可以通过数组创建
```python
import pandas as pd
# 创建数组
data_list = [[6,10,3],[1,5,4],[1,2,4],[1,15,24],[1,0,2],[3,7,9],[2,8,5]]
# 通过数组创建dataframe, columns并不是必须的, 如果不提供的话默认用0,1,...,n表示
df = pd.DataFrame(data_list,columns=['A','B','C'])
# 指定dataframe的行索引, 这也不是必须的, 如果不提供的话默认用0,1,...,n表示
df.index = ['G','H','I','J','K','L','M']
# 打印结果
print(df)
```
## 二、Dataframe的操作
**2.1 获取Dataframe和行数和列数**
```python
import pandas as pd
import numpy as np
# 创建dataframe
df = pd.DataFrame(np.arange(24).reshape(6,4), columns=['A', 'B', 'C', 'D'])
row_nums = df.shape[0]
col_nums = df.columns.size
print(row_nums)
print(col_nums)
# 获取特定行data.iloc[x,y]
```
**2.2 Dataframe删除行、列**
```python
import pandas as pd
import numpy as np
# 创建dataframe
df = pd.DataFrame(np.arange(24).reshape(6,4), columns=['A', 'B', 'C', 'D'])
print(df)
# 删除单行
df1 = df.drop(axis=0, index = 1, inplace=False)
print(df1)
# 删除多行
df2 = df.drop(axis=0, index = [1,2,4], inplace=False)
print(df2)
# 删除列
df3 = df.drop(axis=1, columns = ['A','D'], inplace=False)
print(df3)
```
注意删除多行的时候要确保index存在一种非常隐蔽的错误是
```python
import pandas as pd
import numpy as np
df1 = pd.DataFrame(np.arange(12).reshape(3,4), columns=['A', 'B', 'C', 'D'])
df2 = pd.DataFrame(np.arange(12).reshape(3,4), columns=['A', 'B', 'C', 'D'])
# ignore_index=True 保留原索引
new_df = pd.concat([df1,df2], ignore_index=False)
# 打印可以看到拼接之后索引只有0,1,2
print(new_df)
# 当我们调用删除行函数的时候会报错,因为没有index=3,虽然这个dataframe是6x4大小的
# 这是一个非常隐蔽的错误
df3 = new_df.drop(axis=0, index = 3, inplace=False)
```
**2.3 Dataframe的排序**
dataframe的排序有通过行列的名称进行排序也有同行的数值或者列的数值进行排序。对于数值排序采用sort_values函数。
```python
import pandas as pd
# 创建dataframe
data_list = [[6,10,3],[1,5,4],[1,2,4],[1,15,24],[1,0,36],[3,7,9],[2,8,5]]
df = pd.DataFrame(data_list,columns=['A','B','C'])
df.index = ['G','H','I','J','K','L','M']
# 对列A进行降序排列
# ascending表示是否升序排列, inplace表示在自身进行排序
df.sort_values(by='A',axis=0,ascending=False,inplace=True)
print(df)
df = pd.DataFrame(data_list,columns=['A','B','C'])
df.index = ['G','H','I','J','K','L','M']
# 对A列和B列进行升序排列,按照A、B的优先级进行排序
df_data_order = df.sort_values(by=['A','B'],ascending=[True,True])
print(df_data_order)
```
很多时候对于一些默认行号的dataframe排序之后会把把行号打乱。这个时候可以通过reset_index函数重置索引。
```python
import pandas as pd
data = [['a','3'],['b','1'],['c','2']]
df = pd.DataFrame(data)
df = df.sort_values(by = 1,axis = 0,ascending = False)
# 排序后的行号是乱的
print(df)
# 重置索引后行号按照0,1,2,...顺序
df = df.reset_index(drop=True)
print(df)
```
**2.4 Dataframe的拼接**
Dataframe的拼接有几个函数merge、concat等函数
```python
import pandas as pd
import numpy as np
df1 = pd.DataFrame(np.arange(12).reshape(3,4), columns=['A', 'B', 'C', 'D'])
df2 = pd.DataFrame(np.arange(12).reshape(3,4), columns=['A', 'B', 'C', 'D'])
# 拼接df1和df2,默认的拼接方向axis=0垂直方向拼接
# ignore_index=True 忽略原索引
new_df = pd.concat([df1,df2], ignore_index=True)
print(new_df)
# ignore_index=True 保留原索引
new_df = pd.concat([df1,df2], ignore_index=False)
print(new_df)
```
**2.5 Dataframe数据筛选**
```python
import pandas as pd
# 创建数组
data_list = [['拖动',10,3],[1,5,4],['拖动',2,4],[1,15,24],['滑动',0,2],[3,7,9],[2,8,5]]
# 通过数组创建dataframe, columns并不是必须的, 如果不提供的话默认用0,1,...,n表示
df = pd.DataFrame(data_list,columns=['A','B','C'])
print(df)
# 去掉A列中包含拖动的数值
df1 = df[~(df['A']=='拖动')]
# 重建索引序号
df1 = df1.reset_index(drop=True)
print(df)
# 更加复杂的运算操作
# df=df[~((df['B']>7)|(df['D']==0))]
df1 = df[(df['A'].isin(['拖动','滑动']) == True)]
df1 = df1.reset_index(drop=True)
print(df1)
# 列筛选A列和B列
df = pd.DataFrame(data_list,columns=['A','B','C'])
df = df[['A','B']]
print(df)
```
对dataframe的字符串筛选也可以通过Dataframe的contain函数这种方式可以允许子串的搜索同时contain函数也支持正则表达式。
```python
import pandas as pd
# 创建数组
data_list = [['拖动',10,3],[1,5,4],['拖动',2,4],[1,15,24],['滑动',0,2],[3,7,9],[2,8,5]]
# 通过数组创建dataframe, columns并不是必须的, 如果不提供的话默认用0,1,...,n表示
df = pd.DataFrame(data_list,columns=['A','B','C'])
print(df)
# 去掉A列中包含动的数值
df=df[(df['A'].str.contains('动') == True)]
# 重建索引序号
df = df.reset_index(drop=True)
print(df)
# contains函数支持正则表达式
df = pd.DataFrame(data_list,columns=['A','B','C'])
parttern = r'.*?'
df=df[(df['A'].str.contains(parttern) == True)]
print(df)
```
**2.6 Dataframe NaN处理**
axis: default 0指行,1为列
how: {any, all}, default **any指带缺失值的所有行**;**'all指清除全是缺失值的**
thresh: int,保留含有int个非空值的行
subset: 对特定的列进行缺失值删除处理
```python
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [np.nan, 1, 2], 'B': [10, np.nan, 10], 'C': [10, 25, 15]})
print(df)
# any表示某一行或者某一列有NaN即被抛弃, all表示清除全部都是NaN
df = df.dropna(axis=0, how='any')
print(df)
# 删除pkg中存在NaN的列 subset=['pkg','xxx','xxxxx']
# df2 = df.dropna(axis='index', how='all', subset=['pkg'])
```

View File

@ -0,0 +1,109 @@
# Python 常用功能
## 一、python高频常用
**1.1 Python简单main框架**
```python
import os
def func():
print('func')
if __name__ =="__main__":
# 遍历文件夹所有文件
func()
```
**1.2 文件夹遍历**
```python
import os
def get_filelist(path):
Filelist = []
for home, dirs, files in os.walk(path):
for filename in files:
# 完整路径文件名列表
Filelist.append(os.path.join(home, filename))
# 文件名列表,只包含文件名
#Filelist.append(filename)
return Filelist
# 获取文件夹文件路径
Filelist = get_filelist('F:/data_all_apps/')
# 打印文件完整路径
for file in Filelist :
print(file)
```
**1.3 保留两位小数**
```python
# 方法一:格式化字符串
a = 12.345
b = 12.122276
print("%.2f %.2f" % (a,b))
# 方法二round函数
a = 12.44476
print(round(a,2))
```
**1.4 python格式化字符串**
```python
str = "hello"
print("this is a string: %s" % str)
print("this is a string: %s, %s" % (str, str))
idx = 2.66788
print("this %.2f is a string: %s, %s" % (idx, str, str))
```
其他丰富样例:
```python
first = "持续学习"
second = "持续开发"
slogan = first + second
print(slogan)
banner = "*" * 16
print(banner)
slice = slogan[2:4]
print(slice)
print(""""学习" in slogan %s""" % ("学习" in slogan))
print(""""不学习" not in slogan %s""" % ("不学习" not in slogan))
print(r"""打印\n换行被当做普通字符输出了""")
# 以上我们都可以看到%,很多次代码都有说到这个,但是并没有过多解释
print("%s" % slogan) # 最常用了%s 格式化字符串
# print("%c"%'ccc')#TypeError: %c requires int or char
print("%c" % 'c') # %c 通常用来强制检测待输出的字符串必须长度为1
print("%c" % '雷') # %c 通常用来强制检测待输出的字符串必须长度为1
number = 102.40101
print("%%i 符号整数 %i" % number)
print("%%i 符号整数:%i" % -number)
print("%%d 符号整数 %d" % number)
print("%%d 符号整数 %d" % -number)
print("%%u 无符号整数:%u" % number)
print("%%u 无符号整数:%u" % -number)
#print("八进制 %o" % number)
print("%%o 八进制 %o" % 102)
print("%%x16进制 %x" % 102)
#print("16进制 %X" % 102)
print("%%e 自然常数 e进制 %e" % number)
#print("%E" % number)
print("%%f 浮点数 %f" % number)
#保证显示6微有效数字的前提下灵活的选择小数方式或者科学计数法
print("%%g 灵活的有效显示:%g" % number)
#print("%G" % number)
#保证显示6微有效数字的前提下灵活的选择小数方式或者科学计数法
print("%%g 灵活的有效显示:%g" % (number*10001))
#下面两种写法需要注意执行顺序
#print("%g" % number*10001) #注意这种写法
#print("%g" % number**10) #注意这种写法
```
1.5 系统暂停
```python
os.system('pause')
```

View File

@ -0,0 +1,20 @@
```python
#!/usr/bin/python
# -*-coding:utf-8 -*-
import copy
a = [1, 2, 3, 4, ['a', 'b']] #原始对象
b = a #赋值,传对象的引用
c = copy.copy(a) #对象拷贝,浅拷贝
d = copy.deepcopy(a) #对象拷贝,深拷贝
a.append(5) #修改对象a
a[4].append('c') #修改对象a中的['a', 'b']数组对象
print( 'a = ', a )
print( 'b = ', b )
print( 'c = ', c )
print( 'd = ', d )
```

40
vslam/GPS算法工具.md Normal file
View File

@ -0,0 +1,40 @@
## GPS 算法Python工具
一、距离的计算
```python
#--------------------------------------------------------------------------
# Function : cal_distance
# Descripiton : 给定经纬度, 计算两点之间距离m
# Author : zhanli@vivo.com
# Date : 2022-07-06
#--------------------------------------------------------------------------
def cal_distance(lat1,lon1,lat2,lon2):
dis = 0
# WGS-84椭球体长半轴
WGS84_RE = 6378136.49
# 第一偏向率的平方e^2(WGS-84)
WGS84_ECCENTR2 = 6.69437999014e-3
# 角度转弧度系数
DEG2RAD = 0.017453292
lat = lat1 * DEG2RAD
sinLat = math.sin(lat)
p = 1 - WGS84_ECCENTR2 * (sinLat * sinLat)
temp = math.sqrt(p)
rmh = WGS84_RE * (1 - WGS84_ECCENTR2) / (p*temp)
rnh = WGS84_RE * math.cos(lat) / temp
rmh *= DEG2RAD
rnh *= DEG2RAD
latDiff = rmh*(lat1 - lat2)
lonDiff = rnh*(lon1 - lon2)
dis = math.sqrt(latDiff*latDiff + lonDiff*lonDiff)
return dis
```

19
vslam/PDR优化.md Normal file
View File

@ -0,0 +1,19 @@
## PDR的优化总结
一、PDR优化效果不明显分析
从逻辑上来讲PDR算法具有一定的独立位置推算能力实际上PDR并没有非常独立的推算能力。经过分析在卡尔曼滤波中利用IMU + PCA计算的方向的权重非常小所以从结果上看IMU并没有发挥其轨迹推算能力导致PDR的效果不明显。直接调大IMU的权重此时轨迹错乱。
二、检验PDR算法的系统效果
简单来说就让手机水平放置使得AHRS算法输出的YAW是正确的验证此时的PDR是否工作正常发现此时的PDR依旧效果存在问题。经过LOG调试分析发现AHRS输出的AHRS的航向角是偏差90度。最终定位到AHRS算法默认采用的是北东地的坐标系经过修改后能够输出正确的偏航角。此时增大IMU的融合权重此时可以观察到PDR算法能够独立推导轨迹效果一般。
三、优化GPS的噪声权重模型
四、卡尔曼模型优化
原版的卡尔曼滤波算法是直接融合IMU提供的方向角和GPS的方向角在这种方式下如果磁力计受到干扰会直接导致PDR的方向出现明显偏移轨迹出错。采用的优化思路是IMU提供角度的增量信息而不是直接提供角度。采用这种方式整体的轨迹比较稳定。
五、性能优化
原版的PDR算法采用的每次IMU更新的时候计算加速度均值的方式判断是否静止这种方式产生的计算量太大了没有必要。主要利用Visual Studio的性能探查器。

View File

@ -0,0 +1,31 @@
## 一、群、李群、李代数
群是一种代数结构,它是由集合加运算组成的。我们把运算记作$\cdot$,群要求这个运算满足封闭性 、结合律、幺元、逆四个性质。李群是具有光滑(连续)性质的群。那么马上可以想到全体单位四元数的集合加上四元数乘法也是群,其乘法满足群要求的四个性质,由于四元数是连续的所以全体单位四元数的集合加上四元数乘法也是李群。
SO(3) : 特殊正交群
SE(3) : 特殊欧式群
## 二、视觉里程计
**2.5 回环检测**
无论是视觉SLAM还是激光SLAM随着系统持续运行仅仅依靠视觉里程计会导致误差不断的积累长期运行后结果将是不可靠的。所谓回环检测回即是回到原点环表示系统走过的路径的轨迹是一个环形。最简单的描述就是检测SLAM系统绕了一圈回到原来走过的地方。
## 三、误差评估
**3.1 准确率、精确率和召回率**
- TPTrue Positive正确的正例一个实例是正类并且也被判定成正类
- FNFalse Negative错误的反例漏报本为正类但判定为假类
- FPFalse Positive错误的正例误报本为假类但判定为正类
- TNTrue Negative正确的反例一个实例是假类并且也被判定成假类
$$
Accuracy = \frac{TP+TN}{TP+TN+FP+FN} \\
Precision = \frac{TP}{TP +FP} \\
Reacall = \frac{TP}{TP +FN}
$$

32
vslam/数学推导.md Normal file
View File

@ -0,0 +1,32 @@
数学基础
1、从点到面的距离推导
求三维空间内点$p(x_p,y_p,z_p)$到平面$Ax+By+Cz+D$的距离。
很容易知道,平面方程$Ax+By+Cz+D=0$的法向量是$\vec n = (A,B,C)$。对于过空间点p且方向向量为$\vec n$的直线为:
$$
\frac{x-x_P}{A}=\frac{y-y_p}{B}=\frac{z-z_p}{C}
$$
联立方程组:
$$
\frac{x-x_P}{A}=\frac{y-y_p}{B}=\frac{z-z_p}{C} \\
Ax+By+Cz+D=0
$$
假设三维直线和三维平面的交点为$(x_0,y_0,z_0)$
$$
\frac{x_0-x_P}{A}=\frac{y_0-y_p}{B} \\
\frac{y_0-y_p}{B}=\frac{z_0-z_p}{C} \\
Ax_0+By_0+Cz_0+D_0=0
$$
那么根据距离公式:
$$
d=\sqrt{(x_0-x_p)^2+(y_0-y_p)^2+(z_0-z_p)^2}\\
d=\sqrt{(\frac{A}{B})^2\cdot(y_0-y_p)^2+(y_0-y_p)^2+(\frac{C}{B})^2\cdot(y_0-y_p)^2}\\
d^2=\frac{A^2\cdot(y_0-y_p)^2}{B^2}+(y_0-y_p)^2+\frac{C^2}{B^2}\cdot(y_0-y_p)^2
=\frac{(A^2+B^2+C^2)}{B^2}\cdot(y_0-y_p)^2
$$

41
vslam/组合导航.md Normal file
View File

@ -0,0 +1,41 @@
# 性组合导航算法原理
一、
## 二、汽车航位推算
**1、优化思路**
**2.1.1 增加mahony中的$[ex,ey,ez]$策略,提高精度 [2020-01-06]**
本质原因,通过调整$[ex,ey,ez]$的策略,某种意义上提高了姿态估计的准确度,从而最终提高了组合导航的精度。
**2.1.2 预积分[2020-01-06]**
简单来说,我们利用$t-1$时刻的姿态$q_{t-1}$用于重力消除。从代码结构上来讲,我们是通过先消除重力然后进行运动积分,最后进行姿态解算的过程。那么姿态的估计就会有延迟。所以理论上可以利用$q_t-1$和$gyro_t$进行预先的积分,得到“相对较准”的姿态,利用这个估计的姿态$q$进行重力消除会更加准确。
从结果试验来看,是没有太大的效果,但是也可能是其他部分做的不够好导致的。
**2.1.3 离心加速度**
从实际的试验中发现即使是低价的MEMS传感器在汽车的转向时会受到离心加速度的影响。因此当我们知道汽车的角速度和线速度信息的时候可以计算出离心加速度的大小通过修正离心加速度可以提高姿态估计的准确性最终达到提升导航定位精度的目的。
**2.1.4 轨迹融合优化**
一种比较讨巧的办法在汽车进行隧道期间进行历史位置匹配提高位置定位的精度。这种办法确实也应用到手机中从高通的部分泄露的信息发现高通也会缓存也部分历史信息用于提高定位精度不过这种办法主要是应用在汽车导航场景。主要原因在于汽车行驶的位置是有限制的不能在任意地方行驶。在PDR场景中我们也会用到历史信息缓存主要原因在用户经常带着手机沿着固定的场景跑圈这种情况下采用估计融合可以提高多圈轨迹叠加的一致性。
**2.1.5 EKF和Mahony对导航精度的影响**
在同时调参的情况下,两种算法的差异不大。主要原因在于核心原理是相同的。
## 三、行人航位推算
2.1 GPS协议解析
2.2 AHRS姿态解算
2.3 行人动作识别
2.4 PCA主方向分析
假设用户甩动手臂是规律的,

View File

@ -0,0 +1,84 @@
### 1.git安装教程
教程链接:<a href="https://zhuanlan.zhihu.com/p/443527549">https://zhuanlan.zhihu.com/p/443527549</a>
### <font color = "red">2.git基本操作命令</font>
#### 2.1 git常用命令
> - git init 初始化项目
> - git status 查看当前目录下文件的状态
> - git add (文件名 | .)添加到暂存盘,文件名代表某文件,"."代表所有文件
> - git commit -m "备注" 提交到git本地仓库产生新版本引号中的备注必须写
> - git log 查看所有提交的记录
> - git clone 链接 克隆远程仓库,进行连接
> - git checkout -b [branch] 新建一个分支,并切换到该分支
> - git checkout [branch] 切换到某分支
> - git branch -d [branch-name] 删除分支
> - git merge [branch] 合并指定分支到当前分支
> - git push 将本地仓库push到远程仓库
#### 2.2 流程详解
# **Git使用教程**
## 一、Git的公钥和私钥
github支持https和ssh方式访问代码库https是无状态传输。git传输使用rsa算法rsa生产一对数字一个数字用来加密另一个数字用来解密。git中这两个数字分别是公钥public key和私钥private key。通常公钥给服务器本地访问远端仓库下载代码时服务器通过公钥加密代码然后发出去本地电脑接收时用本地存储的私钥解密它。如果匹配就正常下载如果不匹配则下载失败。
## 二、生成密钥的步骤
1、在电脑桌面鼠标右键选择"Git Bash Here"打开Git命令窗口
2、在Git命令窗口中配置用户输入如下命令
```shell
# 这里的your_name需要替换为自己的id
git config --global user.name "your_name"
```
3、继续在Git窗口中配置邮箱输入如下命令
```shell
git config --global user.email "xxx@xx.com"
```
4、此时会在C:\Users\zhouxy目录下生成.gitconfig配置文件(此文件不能删除)
5、查看.gitconfig配置文件里的内容
6、继续在Git命令窗口中输入如下命令即可生成SSH公钥和私钥
```shell
ssh-keygen -t rsa -C "xxx@xx.com"
```
![image-20220827162221537](C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220827162221537.png)
7、进入C:\Users\Administrator.ssh目录下查看生成的SSH密钥
1.打开想要上传项目的文件根目录右击Git Bash Here输入命令 **git init**:
``` $ git init ```
![image-20240507131840732](D:\Linux+git笔记\代码同步协作(Git)\Image\git init.png)
发现在根目录中出现了一个 **.git** 文件表明此项目已被git管理。
2.通过` git clone "仓库链接"`与远程仓库进行连接:
![image-20240507131741797](D:\Linux+git笔记\代码同步协作(Git)\Image\git clone.png)
3. 连接成功后,添加项目到暂存区,并提交项目到本地仓库,中间可以使用 **git status** 命令查看文件状态:![image-20240507131929421](D:\Linux+git笔记\代码同步协作(Git)\Image\git add.png)![image-20240507131951291](D:\Linux+git笔记\代码同步协作(Git)\Image\git commit.png)![image-20240507132003856](D:\Linux+git笔记\代码同步协作(Git)\Image\git status.png)
当使用用` git status` 查看状态显示“没有需要提交的,工作树干净”时,就说明项目已经全部提交至本地仓库。
4. 使用命令 `git checkout -b dev` 创建dev分支并切换到该分支下在分支上进行操作在这之前或之后都可以使用命令 `git branch` 查看仓库的分支都有哪些![image-20240507133520475](D:\Linux+git笔记\代码同步协作(Git)\Image\git checkout.png)
5. 操作这么多命令后,可能已经断开了与远程的连接,使用命令 `git remote -v`查看,如果为空,则使用 `git remote add origin 链接` 再次与远程仓库进行连接![image-20240507134004040](D:\Linux+git笔记\代码同步协作(Git)\Image\git remote.png)
出现如上图所示,则重新连接成功!
6. 把master分支合并到dev分支进行add和commit最后push到远程
7. 查看项目是否上传成功。

View File

@ -0,0 +1,33 @@
1、查看远端仓库情况
```shell
git remote -v
# 样例输出如下:
origin http://logzhan.ticp.io:30000/logzhan/management.git (fetch)
origin http://logzhan.ticp.io:30000/logzhan/management.git (push)
```
2、将仓库添加到本地
执行完该命令,本地项目将同时关联到私有仓库与远程仓库地址。
```shell
# 命令参数upstream 表示远程仓库别名类似于origin
git remote add upstream 主库git地址
```
3、从主仓库更新代码
```shell
# 这句代码需要说明这句话表示我们要从upstream的main分支拉去代码到当前分支例如我们相把远端的A同步的本地的B
# 需要先git checkout B 然后 git fetch upsteram A
# 实际样例如下:
git fetch upstream main
```
4、推送到远程分支
```shell
# 此处的master是一个样例根据实际情况填写要合并的分支
git merge upstream/master
```

View File

@ -0,0 +1,53 @@
## 一、Commit回退
### 1.1 从一次commit回退到某一次commit
#### 1.1.1 查看历史提交记录
```shell
# git 查看历史commit
git log
```
#### 1.1.2 复制上一次提交的commit码
<img src="./Image/Git-Commit-History.png" style="zoom:50%;" />
#### 1.1.3、输入回退命令
```shell
git revert your_commit_code
```
### 1.2 强制回到某一次提交
在部分时候由于版本冲突的问题1.1 中提到的方法报冲突错误,这个时候实在没有办法可以使用`git reset --hard`命令。其步骤如下所示。值得注意的是,由于这个命令会重写历史,所以需要跟仓库的协作者进行沟通。
```shell
# 先找到要回去的commit的commit号
git log
# 回到某一次提交
git reset --hard your_commit_code
# 强制推送这是因为本地修改后提交上去会重新覆盖之前的历史如果不force会报冲突错误。
git push -f origin your_branch
```
## 二、放弃所有文件修改 未Commit
**2.1 解决方法**(两种解决方法)
```shell
# 方法1
git add .
git reset --hard "commit_code"
# 方法2实际测试
git stash
git stash drop #丢弃指定条目
```
**2.1 git stash 命令**
别急Git提供了一个**git stash命令**恰好可以完美解决该问题, 其将当前未提交的修改(即,工作区的修改和暂存区的修改)先暂时储藏起来这样工作区干净了后就可以切换切换到master分支下拉一个fix分支。在完成线上bug的修复工作后重新切换到dev分支下通过**git stash pop**命令将之前储藏的修改取出来,继续进行新功能的开发工作

View File

@ -0,0 +1 @@
https://blog.csdn.net/weixin_43729127/article/details/133185964

View File

@ -0,0 +1,11 @@
1、Git 某次Commit 有大文件导致Github无法提交上去
解决方案是把这个大文件从历史的所有提交剔除,如下面的命令所示:
```shell
# 使用双引号将文件路径括起来
# 当你的路径存在空格的时候容易导致命令行识别错,可以把你要删除的路径的文件加上""
git filter-branch --force --index-filter 'git rm --cached -r --ignore-unmatch "your path"' --prune-empty --tag-name-filter cat -- --all
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 934 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 862 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 917 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 724 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 485 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 386 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

120
定位技术/README.md Normal file
View File

@ -0,0 +1,120 @@
# Lighthouse定位原理
2016年Valve携手HTC一同发布了跨时代般的VR头显:HTC VIVE,随之而来的是一套全新的空间定位技术命名为Lighthouse的定位系统具备高精度、高响应、轻便易用等特点至今仍是VR全身追踪玩家首选的追踪设备。本文章详细解析Lighthouse初代系统1.0基站系统与不完全解析第二代系统2017年6月发布的2.0基站系统基站原理与追踪器定位原理为方便理解将以1.0基站指代初代系统2.0基站指代第二代系统。
## 一、Lighthouse定位原理
### 1.1 Lighthouse定位架构
每个1.0基站包含一个称为同步闪光灯的红外灯阵列和俩组马达集成激光发射器。系统内20ms为一个扫描周期。基站的定位原理如下图所示
<img src="./Image/positioning-principle.png" style="zoom:80%;" />
一个周期的定位过程1、首先基站的红外灯阵列闪烁一次发射一组红外光同步光覆盖整个扫描范围当追踪器*1 上一组光敏每个追踪器含有多组光敏传感器组件搭载的光电转换芯片接收到该端光敏传感器捕捉到的来自基站的红外同步光信息后启动全部传感器与惯性系统IMU并将数据清零。2、基站的X轴马达横向发射激光旋转10ms闪烁一次后停止3、基站的红外灯阵列再闪烁一次追踪器捕捉到第二次红外光同步信息后将准备捕捉Y轴光数据 4、Y轴马达纵向发射激光旋转10ms闪烁一次后停止至基站下次红外灯阵列闪烁后代表一个扫描周期结束。如下图所示
![](./Image/Lighthouse扫描过程.webp)
### 1.2 Lighthouse基站运行模式
1.0基站共有三种运行模式通过按钮切换单独A模式有线A、B模式无线B、C模式。一个空间内只运行一个基站时设置为A模式或B模式均可单独运行。一个空间内运行双基站当俩个基站设置为A模式与B模式有线模式由A模式的基站作为主基站。将线缆连接俩个基站后B模式的基站将与A模式基站通过线缆同步扫描周期同步红外光阵列点亮时间与马达转速、激光发射器点亮间当基站处于B、C模式无线模式由B模式的基站作为主基站C模式的基站上的一组光敏捕捉到B模式基站的红外同步光后通过分析一段时间内捕捉到的红外同步光的频率便可与B基站同步扫描周期同步红外光阵列点亮时间与马达转速、激光发射器点亮时间当一个空间内运行双基站时由追踪器判定使用哪一个基站的激光当多组光敏同时捕捉到某一个基站的光信息最多时优先使用该组基站的激光参与融合计算。
## 二、 Lighthouse基站拆解
### 2.1 基站的面板拆解
1.0基站有俩种型号分别为9灯与15灯基站(最早生产15灯基站2017年后生产的基站基本为9灯基站)9灯基站红外光同步阵列含9颗灯珠、15灯基站(红外光同步阵列含15颗灯珠)。9灯基站与15灯基站区别为红外同步阵列灯珠数量定位效果与原理相同9灯阵列灯珠亮度更高。
<img src="./Image/15灯基站.png" style="zoom:33%;" />
<center>15灯基站运行图片</center>
<img src="./Image/9灯基站.png" style="zoom:33%;" />
<center>9灯基站运行图片</center>
Tracker1.0等1.0追踪器搭载TS3633芯片设备将与基站完成红外光同步识别捕捉到的红外光信息为基站发出时才会进行定位。而后代更换TS4231或TSTS4631芯片的追踪器(如Tracker2018、Tracker3.0、Vive Pro头显与Vive2.0手柄等上取消了红外光同步模式当这类追踪器运行在1.0基站模式下,捕捉到红外光信息后将直接启动全部传感器,但无法判断是否为基站发射的同步光。当环境存在其他发射红外光的设备时,追踪器可能将其会误判为基站发射的同步光而错误定位,也就会产生所谓“干扰”丢追现象。
<img src="./Image/基站拆解图.png" alt="基站拆解图" style="zoom:67%;" />
### 2.2 Tracker 1.0跟踪器原理和拆解
每个追踪器表面都覆盖有多组光敏传感器与光电转换器。当一组光敏传感器俩次捕捉到红外同步光后分俩次捕捉到俩组激光。随后由该组光敏组件上搭载的光电转换器如TS3633等开始分别计算这俩组X轴与Y轴激光分别到达该组光敏的角度与时间这个时间正好是基站X轴与Y轴马达旋转到特定的面、点亮激光发射器的时间与角度基站位置为绝对静止马达转速与激光发射器点亮时间为已知一组马达一个周期旋转10ms并闪烁一次而分布在追踪器上的光敏传感器的位置也是已知的便可依此得到一组时间差数据发送给微控制器与FPGA。追踪器通过结合多组光电转换器得到的时间差数据并融合IMU惯性系统进行计算随后将数据发送给电脑便可得出追踪器的绝对位置与运动轨迹。下图为Tracker1.0跟踪器的拆解图:
<img src="./Image/Tracker拆解图.png" alt="Tracker拆解图" style="zoom:67%;" />
<center>Tracker1.0上覆盖的多组光敏与光电转换器</center>
<img src="./Image/Tracker1.0 Mainboard.png" style="zoom: 67%;" />
<center>Tracker1.0主板</center>
<img src="./Image/Tracker1.0主板2.png" style="zoom: 67%;" />
<center>Tracker1.0主板</center>
### 2.3 基站2.0结构和原理
第二代基站将原先俩组马达与一组红外光阵列的结构改为单马达集成俩组激光发射器,取消红外光同步模式。每组激光发射器的相对位置有差别(如下图所示),每组发射器点亮时间也略有间隔,发射的每组激光都包含信息(包括识别信息)。当搭载TS4231或TSTS4631芯片的追踪器如Tracker2018、Tracker3.0、Vive Pro头显与Vive2.0手柄等接收到来自2.0基站的光信息后,追踪器可快速归位并直接进入定位状态,并且可识别捕捉到的激光来自哪一个基站。
![](./Image/基站2.0原理1.png)
<center>单马达集成俩组激光发射器结构(来自网络)‍</center>
<img src="./Image/基站2.0原理拆解.png" alt="基站2.0原理拆解" style="zoom:67%;" />
<center>单马达集成俩组激光发射器结构(来自网络)‍</center>
2.0基站扫描过程马达将快速旋转至设定转速集成的俩组激光发射器旋转至特定位置时间隔几纳秒分别闪烁一次呈V字形发射X、Y轴激光。激光组件闪烁俩次后至下一次旋转到特定位置并再次闪烁前为一个扫描周期。如下图所示
<img src="./Image/基站2.0扫描过程.webp" style="zoom:67%;" />
<center>2.0基站运行过程(来自网络)</center>
2.0基站取消了红外光同步模式而改为激光通讯使得每个基站可独立运行多基站需要设置信道理论最多16个基站同时运行且启动、恢复对比1.0基站更加迅速但不再兼容旧款搭载TS3633芯片无法解码短波激光信息的追踪器如Tracker1.0Vive初代头显与Vive 1.0手柄等)。**单马达结构也存在弊端**。集成俩组激光发射器且转速非常高的马达更容易损耗。当系统中某个基站上的一组激光发射器出现老化或马达转速异常时,将直接影响到整个系统的定位稳定性。且独立运行且基站间无同步的工作模式更容易导致多个基站之间发射的激光频率产生差异。一个空间内同时运行多个基站时,如果每个基站的相对位置过于紧凑或都处于同一平面(扫描区域重合较多)可能会导致追踪器对多个方向的激光束接收混乱,产生所谓“干扰”丢追现象。
### 2.4 基站2.0模式下追踪器定位原理
每个追踪器表面都覆盖有多组光敏传感器与光电转换器。当一组光敏传感器俩次捕捉到来自基站的激光后由该组光敏组件上搭载的光电转换器TS4231或TS4631开始解码短波激光信息并分别计算这俩组X轴与Y轴激光到达该组光敏的角度与时间这个时间正好是基站俩组激光发射器旋转至特定位置的时间与发射激光的角度基站位置为绝对静止马达转速与激光发射器点亮时间为已知而分布在追踪器上的光敏传感器的位置也是已知的便可依此得到一组时间差数据发送给微控制器与FPGA。追踪器通过结合多组光电转换器得到的时间差数据并融合IMU惯性系统进行计算随后将数据发送给电脑便可得出追踪器的绝对位置与运动轨迹。
<img src="./Image/Tracker2.0主板.png" style="zoom:67%;" />
<center>Tracker2.0上覆盖的多组光敏传感器与光电转换器(来自网络)</center>
Tracker2018拆解图如下图所示:
<img src="./Image/Tracker2.0主板1.png" style="zoom:67%;" />
<center>Tracker2018搭载的TS4231芯片将刷新率从上一代TS3633的60Hz提升到了100Hz效率更高</center>
<img src="./Image/Tracker2.0主板2.png" style="zoom:67%;" />
<center>Tracker2018主板</center>
<img src="./Image/Tracker2.0主板3.png" style="zoom:67%;" />
<center>Tracker2018使用ATSAMG55微处理器</center>
### 2.5 Tracker3.0拆解图
Tracker3.0压缩了体积,但保持了覆盖光敏组件的数量。
<img src="./Image/Tracker3.0.png" style="zoom:67%;" />
<img src="./Image/Tracker3.0-光敏模组.png" style="zoom:67%;" />
<center>Tracker3.0上搭载的TS4631芯片</center>
<img src="./Image/Tracker3.0-主板.png" style="zoom:67%;" />
<center>Tracker3.0上的主板</center>
<img src="./Image/Tracker3.0-主板2.png" style="zoom:67%;" />
<center>Tracker3.0上的主板</center>
<img src="./Image/Tracker3.0-手柄TS4631.png" style="zoom:67%;" />
<center>Index手柄上搭载的TS4631芯片特写</center>
<img src="./Image/TundraTracker-TS4631.png" style="zoom:67%;" />
<center>N7R似乎采用的是和HTC同款方案效果却不及HTC</center>

57
工具脚本/Code2Utf8.py Normal file
View File

@ -0,0 +1,57 @@
import os
import chardet
import codecs
import tkinter as tk
from tkinter import filedialog
# 获取给定目录中的所有文件和子目录
def get_all_files(directory):
files = []
# 遍历目录中的所有文件和子目录
for root, subdirs, files_list in os.walk(directory):
for file in files_list:
file_path = os.path.join(root, file)
files.append(file_path)
return files
# 检测文件编码格式
def detect_encoding(file_path):
with open(file_path, 'rb') as file:
raw_data = file.read(8192)
return chardet.detect(raw_data)['encoding']
# 将文件转换为UTF-8编码格式
def convert_to_utf8(file_path, from_encoding):
with codecs.open(file_path, 'r', encoding=from_encoding, errors='ignore') as file:
lines = file.read()
with codecs.open(file_path, 'w', encoding='utf-8') as file:
file.write(lines)
# 将给定目录下的所有文件转换为UTF-8编码格式
def convert_files_in_directory(directory_path):
files = get_all_files(directory_path)
for file in files:
if file.endswith('.py') or file.endswith('.c') or file.endswith('.cpp') or file.endswith('.h'):
from_encoding = detect_encoding(file)
if from_encoding != 'utf-8':
print("file = " + file + "encoding = " + from_encoding)
convert_to_utf8(file, from_encoding)
print('所有文件均已转换为UTF-8编码格式')
# 按钮单击时执行的函数
def browse_folder():
folder_path = filedialog.askdirectory()
convert_files_in_directory(folder_path)
# 创建一个Tkinter窗口其中包含一个选择文件夹的按钮
window = tk.Tk()
window.geometry('200x100')
button = tk.Button(text='选择文件夹', command=browse_folder)
button.pack()
window.mainloop()

View File

@ -0,0 +1,7 @@
**一、删除面:**插入->面->删除面
<img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230506002227482.png" alt="image-20230506002227482" style="zoom:50%;" />
二、基本操作
平移Ctrl + 鼠标滚轮

View File

@ -0,0 +1,33 @@
## 一、Room Definition Violation
[Room Definition Violation] GeekIMU.PcbDoc Advanced PCB Room Definition: Between Room Sensor
主要解决方案是在DRC检查的时候删除掉不用的ROOM。
## 二、Minimum Solder Mask Sliver Constraint
这个问题主要描述的是两个焊盘之间阻焊层的最小间距。如果阻焊层的宽度过小PCB在生产的时候可能导致阻焊层制造失败。如下图所示
[Minimum Solder Mask Sliver Constraint Violation] GeekIMU.PcbDoc Advanced PCB Minimum Solder Mask Sliver Constraint: (4.842mil < 10mil)
<img src="E:\技术武器库\技术开发笔记\硬件开发笔记\Altium Designer\Image\Minimum Solder Mask Sliver.png" style="zoom:50%;" />
解决方案在Design -> Rule -> Manufacturing中找到Minimum Solder Mask Sliver。设置4mil即可。
## 三、Silk To Solder Mask Clearance
这个地方设置的是丝印到阻焊层的最小距离。
<img src="E:\技术武器库\技术开发笔记\硬件开发笔记\Altium Designer\Image\Silk To Solder Mask Clearance.png" style="zoom: 67%;" />
解决方案在Design -> Rule -> Manufacturing中找到Silk To Solder Mask Clearance设置为0mil即可。
## 四、Hole Size Constrain
这个描述是最大孔径默认是100mil在生产制造的时候如果挖的孔太大可能机器的钻头无法钻出这么大的孔如果生产能力满足直接把规则设大即可。
解决方案在Design -> Rule -> Manufacturing中找到Hole设置为合适值即可。
## 五、Silk To Silk Clearance Constraint
描述的是丝印之间的最小间距这个问题不大大不了就是丝印混在一起了。有时候真不好处理可以设置为0mil。

View File

@ -0,0 +1,133 @@
# 使用颜色突出显示网络——Altium Designer 笔记
* [在原理图编辑器中设置网络颜色](#_4)
* [在 PCB 编辑器中设置网络颜色](#_PCB__20)
* * [在 PCB 中网络的两种表示方式](#_PCB__23)
* [在 PCB 中网络的两个颜色设置](#_PCB__33)
* * [基本模式——图层和网络颜色的混合图案](#_53)
* [缩小行为——图层或网络颜色占主导](#_60)
* [设置和显示网络颜色](#_84)
* [在原理图和 PCB 之间传输颜色](#_PCB__102)
在[原理图](https://so.csdn.net/so/search?q=%E5%8E%9F%E7%90%86%E5%9B%BE&spm=1001.2101.3001.7020)编辑器中设置网络颜色
=====================================================================================================
  使用 view > Set Net Colors 命令,可以在原理图编辑器中将高亮颜色应用于网络或总线。**请注意,网络颜色设置无法撤消**,要删除颜色设置,请使用 “Clear Net Color” 命令或 “Clear All Net Colors” 命令。
![在这里插入图片描述](https://img-blog.csdnimg.cn/9d309b678fac4388a06cb803f34b4ecb.png?x-oss-process=image,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_13,color_FFFFFF,t_70,g_se,x_16#pic_center)
设置原理图网络颜色
![在这里插入图片描述](https://img-blog.csdnimg.cn/fce84713b7cf4e46aa67d61049d65bf8.png#pic_center)
网络颜色效果图
在 PCB 编辑器中设置网络颜色
================
在 PCB 中网络的两种表示方式
----------------
  在 PCB 编辑器中,一个网络有两种表示方式;作为未布线的**连接线**或由一系列轨道段定义的**布线网络**。
![在这里插入图片描述](https://img-blog.csdnimg.cn/57a7a6d8b7cb4df8ba912506da9c97c3.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
连接线和布线网络
在 PCB 中网络的两个颜色设置
----------------
  在 PCB 编辑器中,一个网络有两个颜色设置;**图层** (layer) 颜色和**网络**颜色。网络颜色始终应用于连接线。布线网络可以以图层颜色或网络颜色显示。
![在这里插入图片描述](https://img-blog.csdnimg.cn/b77a9f3e75624e81994361fd6d45e4d1.png#pic_center)
图层颜色
![在这里插入图片描述](https://img-blog.csdnimg.cn/68cba868c811419eba4aa39696fb125f.png#pic_center)
网络颜色
![在这里插入图片描述](https://img-blog.csdnimg.cn/34f4acb3865047f98315035bb2d4ef69.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
图层颜色和网络颜色效果图(**开和关闭可以通过F5完成开启和关闭**
### 基本模式——图层和网络颜色的混合图案
  打开首选项(界面右上角齿轮图案),在 PCB Editor > Board Insight Color Overrides 界面可以设置图层颜色和网络颜色混合的基本图案。
![在这里插入图片描述](https://img-blog.csdnimg.cn/de7bab4d458046538d982fa60c198638.png#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/c08f31ef94714459bc1781b70c1485d0.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
### 缩小行为——图层或网络颜色占主导
  打开首选项(界面右上角齿轮图案),在 PCB Editor > Board Insight Color Overrides 界面可以设置缩小行为。
缩小时,此显示行为可以是:
* 缩小时保持不变(基本图案比例),或
* 图案可以逐渐消失以恢复图层颜色(图层颜色占主导地位),或
* 覆盖颜色 (即网络颜色) 可以加强(覆盖颜色占主导地位)。
![在这里插入图片描述](https://img-blog.csdnimg.cn/ce449c4bd0e247b2b06a278705b731e7.png#pic_center)
缩小时保持不变(基本图案比例)
![在这里插入图片描述](https://img-blog.csdnimg.cn/8696b749d33040cf89d6f41a42dde414.png#pic_center)
图案可以逐渐消失以恢复图层颜色(图层颜色占主导地位)
![在这里插入图片描述](https://img-blog.csdnimg.cn/21d5bed5306a490abcf0e01abb9296b0.png#pic_center)
覆盖颜色 (即网络颜色) 可以加强(覆盖颜色占主导地位)
设置和显示网络颜色
---------
  在 PCB 编辑器的 PCB 面板中 (如果没有此面板,左下角 Panels 可以调出) ,选择 `Nets` 模式,点击 `All Net` 显示所有网络,右键单击选定的网络并选择 `Change Net Color` 命令可以设置网络颜色。
![在这里插入图片描述](https://img-blog.csdnimg.cn/7c87804e10634f1a90796e04aee284fa.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
设置 PCB 网络颜色
  布线网络默认是显示为其所在图层的**图层颜色**,要显示**网络颜色**则需要如上图所示,勾选网络以启用网络颜色。如果勾选后没有显示网络颜色,可以按下快捷键 F5 全局启用 / 禁用网络颜色显示,或在右下角 Panels 调出 View Configuration 面板,然后在 View Options 标签中使用 Net Color Override 按钮启用 / 禁用网络颜色显示。
![在这里插入图片描述](https://img-blog.csdnimg.cn/99f737d065d54a55a5d28e3b241d1e81.png?x-oss-process=image,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_9,color_FFFFFF,t_70,g_se,x_16#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/e7e8bef9bb6c4ea9b28c30655c134470.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_18,color_FFFFFF,t_70,g_se,x_16#pic_center)
在原理图和 PCB 之间传输颜色
================
  通过 Design > Update 命令,可以在原理图和 PCB 编辑器之间(双向)传输网络颜色。在工程变更单 (ECO) 中仅需勾选 Change Net Colors 项中的变更即可。
![在这里插入图片描述](https://img-blog.csdnimg.cn/ad8e44b2bcd444e192675ac54567ff55.png?x-oss-process=image,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
如果颜色没有转移,请检查 Project > Project Options 对话框中是否启用了以下选项
* Comparato 选项卡:与网络相关的差异 —— 更改网络颜色
* ECO Generation 选项卡:与网络相关的修改 —— 更改网络颜色
![在这里插入图片描述](https://img-blog.csdnimg.cn/3e426ad191c74b48ae077d306dc3839a.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
![在这里插入图片描述](https://img-blog.csdnimg.cn/ee674ac8152b41caa776a2f551300450.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBAQmVuQmVuRjE5,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)

View File

@ -0,0 +1,4 @@
**元件水平翻转和垂直翻转** 选中元件,鼠标左键按住同时 + 按下X按键\Y按键实现X轴和Y轴水平翻转
**元件旋转:**选中元件,**鼠标放松**,按下空格键

View File

@ -0,0 +1,19 @@
## 一、PCB板子形状重新定义
如下图所示我们按住Shirt的同时点击紫色的机械层边框。然后找到设计(Design)->板子形状->按照选择的形状定义。
<img src="E:\技术武器库\技术开发笔记\硬件开发笔记\Altium Designer\Image\PCB_Board_Def.jpg" style="zoom:50%;" />
Altium Designer选项如下图所示
<img src="E:\技术武器库\技术开发笔记\硬件开发笔记\Altium Designer\Image\PCB_Board_Def_Shape.jpg" style="zoom:50%;" />
## 二、元件的强制删除
部分情况下我们在Altium Designer选中元件后点击DEL无法起到删除的作用。此时Ctrl + DEL可以快速完成删除操作。
## 三、原理图自动分配位号
操作快捷键(TAA) 打开原理图图注配置,选择更新更改列表、接收更改。
<img src="E:\技术武器库\技术开发笔记\硬件开发笔记\Altium Designer\Image\Altium_SCH_Mark.png" alt="image-20230416152400400" style="zoom:50%;" />

View File

@ -0,0 +1,13 @@
Altium Designer 常见问题解决方案
## 一、元件无法对齐 & 元件拖动步距过大
这是以为栅格的最小步长太小了,元件存在拖动无法对齐的问题。解决方案:视图(View) -> 栅格(Gird) -> 设置捕捉栅格(Set Snap Gird)。点击后弹出对话框,我们可以把最小的栅格修改变小。那么画图的时候会更加精确。
二、原理图修改样式和尺寸
部分原理图偏小导致一个项目的原理图需要多个文件才能绘制完。可以把A4的原理图修改为A3.
<img src="C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230416151604248.png" alt="image-20230416151604248" style="zoom:50%;" />
鼠标点击原理图在右侧的Properties中就可以看到原理图的选项。一般我们选择标准的原理图大小。复杂一点的项目可以选择A3。方向一般选择Landsapce水平。Title一般用于记录公司、时间、作者等信息。

View File

@ -0,0 +1,16 @@
# Altium Designer必要设置
一、Altium Designer的层叠设置
如下图所示,在设计(Design)选项中可以找到Layer Stack Manager其描述如下图所示
<img src="E:\技术武器库\技术开发笔记\硬件开发笔记\Altium Designer\Image\PCB_LayerStackSetting.jpg" style="zoom: 33%;" />
| 层次描述 | 作用 | 注解 |
| ------------ | ------------------------------------------------------------ | ------------------------------------------------------- |
| Top Overlay | Top Overlay是指PCB板顶部的覆盖层通常包括PCB板的标识、标志、文字、线条和图形等信息。<br/>Top Overlay层通常是由PCB设计师在设计软件中添加的用于标识和说明PCB板上各个元件、电路和功能的位置和用途。 | 一般是需要在最顶层或者最底层。 |
| Dielectric | 这个层是绝缘层,用于不同层之间绝缘 | |
| Signal & Gnd | 信号层或者地层 | 上图稚晖君把GND放在第三层如果有射频可以考虑放在第二层 |

Some files were not shown because too many files have changed in this diff Show More