[zigbee][z-Stack]协议栈简介及工作流程

article/2025/10/22 5:40:58

文章目录

    • 什么是zigbee协议栈?
    • 如何使用zigbee协议栈?
    • z-Stack工作流程

什么是zigbee协议栈?

协议栈是协议的具体实现形式,通俗点来理解就是协议栈是协议和用户之间的一个缺口,开发人员通过使用协议栈来使用这个协议的,进而实现无线数据收发。

ZigBee的协议分为两部分,IEEE 802.15.4定义了PHY(物理层)和MAC(介质访问层)技术规范;ZigBee联盟定义了NWK(网络层) APS(应用程序支持子层) APL(应用层)技术规范。

ZigBee协议栈就是将各个层定义的协议都集合在一起,以函数的形式实现,并给用户提供API(应用层),用户可以直接调用。
无线网络协议层👇
在这里插入图片描述

如何使用zigbee协议栈?

协议栈是协议的实现,可以理解为代码,函数库,供上层应用调用,协议栈底下的层与应用是相互独立的。商业的协议栈就是给你写好了底层的代码,符合协议标准,提过给你一个功能模块给你调用。

我们需要关心的是我们的应用逻辑,数据从哪里到哪里,怎么存储,处理;还有系统里的设备之间的听信顺序什么的,当你的应用需要数据通信时,调用组网函数给你组建你想要的网络;当你想从一个设备发数据到另一个设备时,调用无线数据发送函数;当然,接收端就调用接收函数;当你的设备没事干的时候你就调用睡眠函数;要干活的时候就调用唤醒函数。

所以当你做具体应用时,不需要关心协议栈是怎么写的,里面的每条代码是什么意思。除非你要做协议研究。每个厂商的协议栈有区别,也就是函数名称和参数可能有区别,这个要看具体的例子、说明文档。

举个例子,用户实现一个简单的无线数据通信时的一般步骤:

    1、组网:调用协议栈的组网函数、加入网络函数,实现网络的建立与节点的加入。2、发送:发送节点调用协议栈的无线数据发送函数,实现无线数据发送。3、接收:接收节点调用协议栈的无线数据接收函数,实现无线数据接收。

是不是看上去很简单啊,其实协议栈很多都封装好了,下面我们大概看看无线发送函数:

afStatus_t AF_DataRequest(afAddrType_t *dstAddr,endPointDesc_t *srcEP,uint16 cID,uint16 len,  //发送数据的长度uint8 *buf,  //指向存放发送数据的缓冲区的指针uint8 *transID,uint8 options,uint8 radiuis)

用户调用该函数即可实现数据的无线数据的发送,此函数中有8个参数,用户需要将每个参数的含义理解以后,才能熟练使用该函数进行无线数据通信的目的。现在只讲其中最重要的两个参数,其它参数不需要死记硬背,以后用多了自然就记住了。

至于调用该函数后,如何初始化硬件进行数据发送等工作,用户不需要关心, ZigBee协议栈己经将所需要的工作做好了,我们只需要调用相应的API函数即可,而不必关心具体实现细节。

z-Stack工作流程

在这里插入图片描述
下载z-Stack 提取码:qta9

打开工程:

ZStack2.5.1a\Projects\zstack\Samples\SampleApp\CC2530DB\SampleApp.eww

建议大家复制工程到非中文目录,因为有些开发环境对中文路径的支持不友好;还有就是不要把文件放的太深层目录下,目录太长,打开工程是IAR会关闭;(如果使用 IAR 打开工程停止响应或关闭,说明你路径太长, IAR 不识别,把路径改短或移上几层目录即可解决)
在这里插入图片描述
App:应用层目录,这是用户创建各种不同工程的区域,在这个目录中包含了应用层的内容和这个项目的主要内容。

HAL:硬件层目录,包含有与硬件相关的配置和驱动及操作函数。MAC:MAC层目录,包含了MAC层的参数配置文件及其MAC的LIB库的函数接口文件。MT:实现通过串口可控制各层,并与各层进行直接交互NWK:网络层目录,包含网络层配置参数文件网络层库的函数接口文件及APS层库的函数接口。OSAL:协议栈的操作系统。Profile:Application framework应用框架层目录,包含AF层处理函数文件。应用框架层是应用程序APS层的无线数据接口。Security:安全层目录,包含安全层处理函数,比如加密函数等Services:地址处理函数目录,包括地址模式的定义及地址处理函数。Tools:工程配置目录,包括空间划分及Z-Stack相关配置信息。ZDO:ZDO目录ZMac:MAC层目录,包括MAC层参数配置及MAC层LIB库函数回调处理函数。ZMain:主函数目录,包括入口函数及硬件配置文件。Output:输出文件目录,由IAR IDE自动生成

看到工程中有这么多的文件夹和文件,先不要害怕,带着疑问做实验就行,做的多了就明白了。

用户自己添加的应用任务程序在 Zstack 中的调用过程:

main()---> osal_init_system()---> osalInitTasks()---> SampleApp_Init()

打开ZMain.c找到main函数


int main( void )
{osal_int_disable( INTS_ALL ); //关闭所有中断HAL_BOARD_INIT(); //初始化系统时钟zmain_vdd_check(); //检查芯片电压是否正常InitBoard( OB_COLD ); //初始化 I/O , LED 、 Timer 等HalDriverInit(); //初始化芯片各硬件模块osal_nv_init( NULL ); //初始化 Flash 存储器ZMacInit(); //初始化 MAC 层zmain_ext_addr(); //确定 IEEE 64 位地址zgInit(); //初始化非易失变量#ifndef NONWK// Since the AF isn't a task, call it's initialization routineafInit();#endifosal_init_system(); //初始化操作系统osal_int_enable( INTS_ALL ); //使能全部中断InitBoard( OB_READY ); //最终板载初始化zmain_dev_info(); //显示设备信息#ifdef LCD_SUPPORTEDzmain_lcd_init(); //初始化 LCD#endif#ifdef WDT_IN_PM1/* If WDT is used, this is a good place to enable it. */WatchDogEnable( WDTIMX );#endifosal_start_system();// No Return from here 执行操作系统,进去后不会返回return 0; // Shouldn't get here.
} // main()

看了上面的代码后,可能感觉很多函数不认识。没关系刚开始大概了解流程即可, main 函数先执行初始化工作,包括硬件、网络层、任务等的初始化。然后执行 osal_start_system(); 操作系统。进去后可不会回来了。

在这里,我们重点了解 2 个函数:

        初始化操作系统 osal_init_system();运行操作系统 osal_start_system();

先来看osal_init_system();系统初始化函数,进入函数。如果用IAR看代码可在函数名上单击右键——go to definition of…,便可以进入函数。发现里面有6个初始化函数,这里我们只关心 osalInitTasks();任务初始化函数,继续由该函数进入。
在这里插入图片描述


void osalInitTasks( void )
{uint8 taskID = 0;// 分配内存,返回指向缓冲区的指针tasksEvents = (uint16 *)osal_mem_alloc( sizeof( uint16 ) * tasksCnt);// 设置所分配的内存空间单元值为 0osal_memset( tasksEvents, 0, (sizeof( uint16 ) * tasksCnt));// 任务优先级由高向低依次排列,高优先级对应 taskID 的值反而小macTaskInit( taskID++ ); //macTaskInit(0) ,用户不需考虑nwk_init( taskID++ ); //nwk_init(1),用户不需考虑Hal_Init( taskID++ ); //Hal_Init(2) ,用户需考虑#if defined( MT_TASK ) //如果定义 MT_TASK 则调用 MT_TaskInit()MT_TaskInit( taskID++ );#endifAPS_Init( taskID++ ); //APS_Init(3) ,用户不需考虑#if defined ( ZIGBEE_FRAGMENTATION )APSF_Init( taskID++ );#endifZDApp_Init( taskID++ ); //ZDApp_Init(4) ,用户需考虑#if defined ( ZIGBEE_FREQ_AGILITY ) || defined ( ZIGBEE_PANID_CONFLICT )ZDNwkMgr_Init( taskID++ );#endif//用户创建的任务SampleApp_Init( taskID ); // SampleApp_Init _Init(5),用户需考虑。重要!
}

函数对 taskID 进行初始化,每初始化一个, taskID++。大家看到了注释后面有些写着用户需要考虑,有些则写着用户不需考虑。没错,需要考虑的用户可以根据自己的硬件平台或者其他设置,而写着不需考虑的也是不能修改的。TI 公司协议栈已完成。SampleApp_Init()是我们 应 用 协 议 栈 例 程 的 必 要 函 数 , 用 户 通 常 在 这 里 初 始 化 自 己 的 东 西 。至 此 ,osal_init_system();大概了解完毕。

接下来看第二个函数 osal_start_system();运行操作系统。同样用go to definition 的方法进入该函数。


void osal_start_system( void )
{#if !defined ( ZBIT ) && !defined ( UBIT )for(;;) // Forever Loop#endif{uint8 idx = 0;osalTimeUpdate(); //扫描哪个事件被触发了,然后置相应的标志位Hal_ProcessPoll(); //轮询 TIMER 与 UARTdo {if (tasksEvents[idx]) // Task is highest priority that is ready.{break; //得到待处理的最高优先级任务索引号 idx}} while (++idx < tasksCnt);if (idx < tasksCnt){uint16 events;halIntState_t intState;HAL_ENTER_CRITICAL_SECTION(intState);// 进入临界区,保护events = tasksEvents[idx]; //提取需要处理的任务中的事件tasksEvents[idx] = 0; //清除本次任务的事件HAL_EXIT_CRITICAL_SECTION(intState); // 退出临界区events = (tasksArr[idx])( idx, events );//通过指针调用任务处理函数,关键HAL_ENTER_CRITICAL_SECTION(intState); //进入临界区tasksEvents[idx] |= events; // 保存未处理的事件 Add back unprocessed eventsto the current task.HAL_EXIT_CRITICAL_SECTION(intState); // 退出临界区}#if defined( POWER_SAVING )else // Complete pass through all task events with no activity?{osal_pwrmgr_powerconserve(); // Put the processor/system into sleep}#endif}
}

看一下 events = tasksEvents[idx]; 进入 tasksEvents[idx]数组定义,发现恰好是osalInitTasks()函数里面分配空间初始化过的 tasksEvents。而且 taskID 一一对应。这就是初始化与调用的关系。taskID 把任务联系起来了。

SampleApp_Init()用户应用任务初始化函数


void SampleApp_Init( uint8 task_id )
{SampleApp_TaskID = task_id;//osal 分配的任务 ID 随着用户添加任务的增多而改变SampleApp_NwkState = DEV_INIT; //设备状态设定为 ZDO 层中定义的初始化状态/*初始化应用设备的网络类型,设备类型的改变都要产生一个事件—ZDO_STATE_CHANGE,从字面理解为 ZDO 状态发生了改变。所以在设备初始化的时候一定要把它初始化为什么状态都没有。那么它就要去检测整个环境,看是否能重新建立或者加入存在的网络。但是有一种情况例外,就是当 NV_RESTORE 被设置的候( NV_RESTORE 是把信息保存在非易失存储器中),那么当设备断电或者某种意外重启时,由于网络状态存储在非易失存储器中,那么此时就只需要恢复其网络状态,而不需要重新建立或者加入网络了.这里需要设置 NV_RESTORE 宏定义。*/SampleApp_TransID = 0; //消息发送 ID(多消息时有顺序之分)#if defined ( BUILD_ALL_DEVICES )if ( readCoordinatorJumper() )zgDeviceLogicalType = ZG_DEVICETYPE_COORDINATOR;elsezgDeviceLogicalType = ZG_DEVICETYPE_ROUTER;#endif // BUILD_ALL_DEVICES//该段的意思是,如果设置了 HOLD_AUTO_START 宏定义,将会在启动芯片的时候会暂停启动流程,只有外部触发以后才会启动芯片。其实就是需要一个按钮触发它的启动流程。#if defined ( HOLD_AUTO_START )ZDOInitDevice(0);#endif//设置发送数据的方式和目的地址寻址模式//发送模式:广播发送SampleApp_Periodic_DstAddr.addrMode = (afAddrMode_t)AddrBroadcast; //广播SampleApp_Periodic_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; //指定端点号SampleApp_Periodic_DstAddr.addr.shortAddr = 0xFFFF;//指定目的网络地址为广播地址//发送模式:组播发送 Setup for the flash command's destination address - Group 1SampleApp_Flash_DstAddr.addrMode = (afAddrMode_t)afAddrGroup; //组寻址SampleApp_Flash_DstAddr.endPoint = SAMPLEAPP_ENDPOINT; //指定端点号SampleApp_Flash_DstAddr.addr.shortAddr = SAMPLEAPP_FLASH_GROUP; //组号 0x0001//定义本设备用来通信的 APS 层端点描述符SampleApp_epDesc.endPoint = SAMPLEAPP_ENDPOINT;SampleApp_epDesc.task_id = &SampleApp_TaskID; //SampleApp 描述符的任务 IDSampleApp_epDesc.simpleDesc //SampleApp 简单描述符= (SimpleDescriptionFormat_t *)&SampleApp_SimpleDesc;SampleApp_epDesc.latencyReq = noLatencyReqs; //延时策略//向 AF 层登记描述符, 登记 endpoint description 到 AF,要对该应用进行初始化并在 AF/*进行登记,告诉应用层有这么一个 EP 已经开通可以使用,那么下层要是有关于该应用的信息或者应用要对下层做哪些操作,就自动得到下层的配合*/afRegister( &SampleApp_epDesc );// 登记所有的按键事件RegisterForKeys( SampleApp_TaskID );// By default, all devices start out in Group 1SampleApp_Group.ID = 0x0001; //组号osal_memcpy( SampleApp_Group.name, "Group 1", 7 ); //设定组名aps_AddGroup( SAMPLEAPP_ENDPOINT, &SampleApp_Group ); //把该组登记添加到 APS 中#if defined ( LCD_SUPPORTED )HalLcdWriteString( "SampleApp", HAL_LCD_LINE_1 ); //如果支持 LCD,显示提示信息#endif
}

SampleApp_ProcessEvent() 用户应用任务的事件处理函数

uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{afIncomingMSGPacket_t *MSGpkt;(void)task_id; // Intentionally unreferenced parameterif ( events & SYS_EVENT_MSG ) //接收系统消息再进行判断{//接收属于本应用任务SampleApp的消息,以SampleApp_TaskID标记MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );while ( MSGpkt ){switch ( MSGpkt->hdr.event ){// Received when a key is pressedcase KEY_CHANGE://按键事件SampleApp_HandleKeys( ((keyChange_t *)MSGpkt)->state, ((keyChange_t*)MSGpkt)->keys );break;// Received when a messages is received (OTA) for this endpointcase AF_INCOMING_MSG_CMD: //接收数据事件,调用函数 AF_DataRequest()接收数据SampleApp_MessageMSGCB( MSGpkt ); //调用回调函数对收到的数据进行处理break;// Received whenever the device changes state in the networkcase ZDO_STATE_CHANGE: //只要网络状态发生改变,就通过ZDO_STATE_CHANGE事件通知所有的任务。同时完成对协调器,路由器,终端的设置SampleApp_NwkState = (devStates_t)(MSGpkt->hdr.status);//if ( (SampleApp_NwkState == DEV_ZB_COORD) //实验中协调器只接收数据所以取消发送事件if ( (SampleApp_NwkState == DEV_ROUTER) || (SampleApp_NwkState ==DEV_END_DEVICE) ){//这个定时器只是为发送周期信息开启的,设备启动初始化后从这里开始触发第一个周期信息的发送,然后周而复始下去。osal_start_timerEx( SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT );}else{// Device is no longer in the network}break;default:break;}// Release the memory //事件处理完了,释放消息占用的内存osal_msg_deallocate( (uint8 *)MSGpkt );//指针指向下一个放在缓冲区的待处理的事件,返回 while ( MSGpkt )重新处理事件,直到缓冲区没有等待处理事件为止MSGpkt = (afIncomingMSGPacket_t *)osal_msg_receive( SampleApp_TaskID );}// return unprocessed events //返回未处理的事件return (events ^ SYS_EVENT_MSG);}// Send a message out - This event is generated by a timer// (setup in SampleApp_Init()).if ( events & SAMPLEAPP_SEND_PERIODIC_MSG_EVT ){/*处理周期性事件,利用 SampleApp_SendPeriodicMessage()处理完当前的周期性事件,然后启动定时器开启下一个周期性事情,这样一种循环下去,也即是上面说的周期性事件了,可以做为传感器定时采集、上传任务*/SampleApp_SendPeriodicMessage();// Setup to send message again in normal period (+ a little jitter)osal_start_timerEx(SampleApp_TaskID,SAMPLEAPP_SEND_PERIODIC_MSG_EVT,(SAMPLEAPP_SEND_PERIODIC_MSG_TIMEOUT + (osal_rand() & 0x00FF)) );// return unprocessed events 返回未处理的事件return (events ^ SAMPLEAPP_SEND_PERIODIC_MSG_EVT);}// Discard unknown eventsreturn 0;
}

分析接收数据函数 SampleApp_MessageMSGCB


//接收数据,参数为接收到的数据
void SampleApp_MessageMSGCB( afIncomingMSGPacket_t *pkt )
{uint16 flashTime;byte buf[3];switch ( pkt->clusterId ) //判断簇 ID{case SAMPLEAPP_PERIODIC_CLUSTERID: //收到广播数据osal_memset(buf, 0 , 3);osal_memcpy(buf, pkt->cmd.Data, 2); //复制数据到缓冲区中if(buf[0]=='D' && buf[1]=='1') //判断收到的数据是否为“ D1”{HalLedBlink(HAL_LED_1, 0, 50, 500); //如果是则 Led1 间隔 500ms 闪烁#if defined(ZDO_COORDINATOR) //协调器收到"D1"后,返回"D1"给终端,让终端 Led1 也闪烁SampleApp_SendPeriodicMessage();#endif}else{HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);}break;case SAMPLEAPP_FLASH_CLUSTERID: //收到组播数据flashTime = BUILD_UINT16(pkt->cmd.Data[1], pkt->cmd.Data[2] );HalLedBlink( HAL_LED_4, 4, 50, (flashTime / 4) );break;}
}

分析发送周期信息 SampleApp_SendPeriodicMessage()

void SampleApp_SendPeriodicMessage( void )
{byte SendData[3]="D1";// 调用 AF_DataRequest 将数据无线广播出去if( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,SAMPLEAPP_PERIODIC_CLUSTERID,2,SendData,&SampleApp_TransID,AF_DISCV_ROUTE,AF_DEFAULT_RADIUS ) == afStatus_SUCCESS ){}else{HalLedSet(HAL_LED_1, HAL_LED_MODE_ON);// Error occurred in request to send.}
}

AF_DataRequest 发送函数

AF_DataRequest( &SampleApp_Periodic_DstAddr, //发送目的地址+端点地址和传送模式
&SampleApp_epDesc, //源(答复或确认)终端的描述(比如操作系统中任务 ID 等)源 EP
SAMPLEAPP_PERIODIC_CLUSTERID, //被 Profile 指定的有效的集群号
2, // 发送数据长度
SendData,// 发送数据缓冲区
&SampleApp_TransID, // 任务 ID 号
AF_DISCV_ROUTE, // 有效位掩码的发送选项
AF_DEFAULT_RADIUS ) //传送跳数,通常设置为 AF_DEFAULT_RADIUS

内容很多但非常重要,最好尽力理解后再去做,会容易很多。

end.


http://chatgpt.dhexx.cn/article/W9g7dHav.shtml

相关文章

相机标定和双目相机标定标定原理推导及效果展示

文章目录 前言一、相机标定1.相机的四个坐标系2.相机的畸变 二、张正友标定法1.求解内参矩阵与外参矩阵的积2.求解内参矩阵3.求解外参矩阵4.标定相机的畸变参数5.双目标定6.极线矫正&#xff08;立体校正&#xff09; 三、视差图与深度图 前言 参考了一些大佬的文章&#xff0c…

视觉基础之相机标定

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 基于视觉的图像处理&#xff0c;通常要在实验前进行相机的标定&#xff0c;以获取相应的参数。为方便查阅&#xff0c;遂将常用到的三种相机标定总结如下。 相机内参标定…

照相机标定

一.相机标定的原理 1.1 相机如何成像&#xff1a; 相机成像系统中&#xff0c;共包含四个坐标系&#xff1a;世界坐标系、相机坐标系、图像坐标系、像素坐标系。 1.1.1 世界坐标系&#xff1a; 世界坐标系&#xff08;world coordinate&#xff09;&#xff0c;也称为测量坐…

Opencv——相机标定

相机标定的目的&#xff1a;获取摄像机的内参和外参矩阵&#xff08;同时也会得到每一幅标定图像的选择和平移矩阵&#xff09;&#xff0c;内参和外参系数可以对之后相机拍摄的图像就进行矫正&#xff0c;得到畸变相对很小的图像。 相机标定的输入&#xff1a;标定图像上所有…

为什么需要对相机标定?

以下内容来自系统教程如何搞定单目/鱼眼/双目/阵列 相机标定&#xff1f; 点击领取相机标定资料和代码 为什么需要对相机标定&#xff1f; 我们所处的世界是三维的&#xff0c;而相机拍摄的照片却是二维的&#xff0c;丢失了其中距离/深度的信息。从数学上可以简单理解为&…

1. 相机标定原理(学习笔记)

相机标定(Camera Calibration)-学习笔记 文章目录 相机标定(Camera Calibration)-学习笔记一、简介二、原理1. 坐标系 *coordinates*2. 相机参数 *camera matrix*2.1 外参数矩阵2.2 内参数矩阵2.3 畸变矩阵2.3.1 径向畸变2.3.2 切向畸变 2.4 小结 三、相机标定方法1. 张正友相机…

相机标定目的及原理

相机标定的目的&#xff1a; 相机标定的目的有两个&#xff0c;一个就是矫正由于镜头畸变造成的图片的变形&#xff0c;例如&#xff0c;现实中的直线&#xff0c;拍摄成图像后会外凸或内凹&#xff0c;进行相机标定后可以对这种情况进行校正&#xff1b;另一个是根据获得得图像…

Python之OpenCV相机标定方法

本文结合OpenCV官方样例&#xff0c;对官方样例中的代码进行修改&#xff0c;使其能够正常运行&#xff0c;并对自己采集的数据进行实验和讲解。 一、准备 OpenCV使用棋盘格板进行标定&#xff0c;如下图所示。为了标定相机&#xff0c;我们需要输入一系列三维点和它们对应的…

相机标定,内参数与外参数

相机标定 简介 所谓的相机标定就是将外界世界的坐标信息转化为计算机&#xff08;自带相机/摄像头&#xff09;可以理解的“距离”&#xff0c;将世界坐标系转换到相机坐标系。我们可以理解为从一个坐标系转换到另一个坐标系所需要的转换关系就是相机标定。 简单滴说&#x…

相机标定——张氏标定法

目录 前言动机为什么要进行相机标定什么是张氏标定法 张氏标定法的原理透镜成像原理世界坐标系到相机坐标系的转换相机坐标系到图像坐标系的转换图像坐标系到像素坐标系单应性矩阵内参求解外参求解Matlab实操 前言 动机 前段时间在整机械臂的手眼标定&#xff0c;也就是标定3D…

相机标定系列(三)利用matlab进行相机标定

相机标定系列&#xff08;三&#xff09;利用matlab进行相机标定 文章目录 相机标定系列&#xff08;三&#xff09;利用matlab进行相机标定前言一、棋盘格图像的采集二、单目相机标定三、双目相机标定 前言 matlab的应用程序中含有对双目相机和单目相机的标定工具箱&#xff…

机器视觉——相机标定

1 机器视觉为什么要做相机标定 机器视觉是采用相机成像来实现对三维场景的测量、定位、重建等过程。是一个利用二维图像进行三维反推的过程&#xff0c;我们所处的世界是三维的&#xff0c;而图像或者照片是二维的&#xff0c;可以把相机认为是一个函数&#xff0c;输入量是一…

相机标定篇——相机标定

认为相机标定是三维重建的核心&#xff0c;研究生期间主要方向为结构光三维重建 必要的数学知识 线性方程求解 Gauss消元法&#xff1b;LU分解&#xff1b;Cholesky分解 最小二乘问题-线性方法 特征值分解&#xff1b;奇异值分解&#xff1b;超定线性方程&#xff1b;最小二乘…

【相机标定】相机内参

相机标定 相机在计算机视觉方面的一些应用一般需要相机标定。我们总是听到标定这个词&#xff0c;那么具体标定的是什么呢&#xff1f;相机的拍摄是一个三维到二维&#xff08;透视投影&#xff09;的过程&#xff0c;这个过程可以用数学模型去表述&#xff0c;标定便是计算这…

什么是相机标定

1. 相机标定的定义及作用 相机标定是指借助标定板来计算单个或多个相机的内参、外参和镜头畸变参数。 作用&#xff1a; 将畸变的图像恢复为正常的图像&#xff0c;为后续进行拼接、SLAM等奠定基础。 多相机标定可以将所有相机输出变换到同一个坐标系。 相机标定是三维视觉…

相机标定究竟在标定什么?

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达 相机标定可以说是计算机视觉/机器视觉的基础&#xff0c;但是初学者不易上手&#xff0c;本文将给读者整理一遍相机标定的逻辑&#xff0c;并在文末回答评论区提出的问题…

相机标定(Camera calibration)

简介 摄像机标定(Camera calibration)简单来说是从世界坐标系换到图像坐标系的过程&#xff0c;也就是求最终的投影矩阵 P P P 的过程&#xff0c;下面相关的部分主要参考UIUC的计算机视觉的课件&#xff08;网址Spring 2016 CS543 / ECE549 Computer vision&#xff09;。 …

相机参数标定(camera calibration)及标定结果如何使用

重要更新&#xff1a;本文的第二次更新已发布。为了不破坏现有内容的结构&#xff0c;故重新开始新的一篇文章。同时本文的一些内容也会涵盖进去。 欢迎关注。 《第二更&#xff0c;相机参数标定基础&#xff1a;从小孔成像开始到单双目标定》 关于实践部分&#xff0c;可参…

相机标定详解

内参、外参、畸变参数三种参数与相机的标定方法与相机坐标系的理解 相机标定&#xff08;Camera calibration&#xff09;原理、步骤 相机标定详解 最近做项目要用到标定&#xff0c;因为是小白&#xff0c;很多东西都不懂&#xff0c;于是查了一堆的博客&#xff0c;但没有…

相机标定-机器视觉基础(理论推导、Halcon和OpenCV相机标定)

相机标定是获得目标工件精准坐标信息的基础。首先&#xff0c;必须进行相机内参标定&#xff0c;构建一个模型消除图像畸变&#xff1b;其次&#xff0c;需要对相机和机器人的映射关系进行手眼标定&#xff0c;构建一个模型将图像坐标系上的点映射到世界坐标系。主要分为背景知…