圓光柵演算法
❶ 脈沖編碼器上A B Z到底各代表什麼意思,然後怎麼用,望詳解
A/B/Z是編碼器的3個脈沖輸出端,A和B一般是兩個相差0.25個周期的連續脈沖輸出,通過分析2個脈沖的相位可以知道旋轉方向,通過頻率可以知道旋轉的速度。
Z脈沖式編碼器旋轉一圈才出現一個脈沖,它是編碼器上面的一個固定的一個參照點,通過對它技術就知道轉了多少圈,所以根據A/B/Z三個脈沖狀態完全可以分析出編碼器的運動狀態,即速度,角度,方向,和旋轉多圈的位置。
(1)圓光柵演算法擴展閱讀:
一,脈沖編碼器的工作原理:
脈沖編碼器是一種光學式位置檢測元件,編碼盤直接裝在電機的旋轉軸上,以測出軸的旋轉角度位置和速度變化,其輸出信號為電脈沖。是一種常用的角位移感測器。同時也可作速度檢測裝置。
脈沖編碼器的優點是無摩擦和磨損,驅動力矩小,響應速度快。脈沖編碼器的缺點是抗污染能力差,容易損壞。
二,脈沖編碼器的分類與結構:
脈沖編碼器分為光電式、接觸式和電磁感應式三種。光電式的精度與可靠性都優於其他兩種,因此數控機床上只使用光電式脈沖編碼器。
脈沖編碼器的結構:在一個圓盤的圓周上刻有等間距線紋,分為透明和不透明的部分,稱為圓光柵。圓光柵與工作軸一起旋轉。與圓光柵相對,平行放置一個固定的扇形薄片,稱為指示光柵,上面制有相差1/4節距的兩個狹縫(辨向狹縫)。
此外,還有一個零位狹縫(每轉發出一個脈沖)。脈沖發生器通過十字連接頭或鍵與伺服電動機相連。
❷ 關於Bresenham演算法的求助
今天一下子遇到三個類似的問題,所以我這篇東西就連續復制粘貼了三遍:
(下面的坐標本來是有下標的,但復制過來就變沒了,你可能看的有點暈)
Bresenham演算法是Bresenham提出的一種光柵線生成演算法!
DDA演算法表面上看起來很有效,並且代碼也比較容易實現,但是顯示每個像素都需要進行一次浮點數加法運算,而Bresenham演算法的最大優點是不需要進行浮點數運算!這是一種精確而有效的光柵線生成演算法,該演算法僅使用增量整數計算,計算速度比DDA要快,另外,Bresenham演算法還可用於顯示圓和其他曲線,這里暫時只顯示直線!
與DDA一樣,我們假設線段的兩個端點坐標是整數值(x0,y0)(xEnd,yEnd),且斜率m滿足0<=m>=1!坐標軸的垂直軸表示掃描線位置,水平軸標識像素列,假設以單位x間隔取樣,需要確定下一個每次取樣時兩個可能的像素位置中的哪一個更接近於線路徑!
從給定線段的左端點(x0,y0)開始,逐步處理每個後繼列(x位置),並在其掃描線y值最接近線段的像素處描出一點,假如已經確定要顯示的像素在(xk,yk),那麼下一步就要確定在列xk+1=xk+1上繪制哪個像素,是在位置(xk+1,yk)還是在(xk+1,yk+1)
在取樣位置xk+1,我們使用dlower和pper來標識兩個像素與數學上線路徑的垂直偏移(就是通過這兩個值來比較哪個點離線上的點最近,以下推導過程你可能看得有點暈,但都是為了推出後續的點而已,你可以結合下面例子程序中的Bresenham函數來看),在像素列xk+1處的直線上的y坐標根據直線方程可計算得:
y=m(xk+1)+b
那麼可求得:
dlower=y-yk=m(xk+1)+b-yk
pper=(yk+1)-y=yk+1-m(xk+1)-b
令斜率m=dy/dx,引入決策參數Pk,定義為:
Pk=dx(dlower-pper)
=2dx*xk-2dy*yk+c
C是一個常數,值為2dx+dx(2b-1)
由此可以計算得到
pk+1=Pk+2dy-2dx(yk+1-yk)
其中yk+1-yk取0還是取1取決於參數Pk的符號,Pk為負時取0,Pk非負時取1!
而Pk為負時,下一個要繪制的點就是(xk+1,yk)且pk+1=Pk+2dy
Pk為非負時則下一個要繪制的點就是(xk+1,yk+1)且pk+1=Pk+2dy-2dx
至此,Bresenham演算法介紹完畢,以下為某個示例:
#include<gl/glut.h>
#include<math.h>
#include<stdio.h>
voiddraw_pixel(intix,intiy)
{
glBegin(GL_POINTS);
glVertex2i(ix,iy);
glEnd();
}
voidBresenham(intx1,inty1,intxEnd,intyEnd)
{
intdx=abs(xEnd-x1),dy=abs(yEnd-y1);
intp=2*dy-dx;
inttwoDy=2*dy,twoDyMinusDx=2*dy-2*dx;
intx,y;
if(x1>xEnd)
{
x=xEnd;y=yEnd;
xEnd=x1;
}
else
{
x=x1;
y=y1;
}
draw_pixel(x,y);
while(x<xEnd)
{
x++;
if(p<0)
p+=twoDy;
else
{
y++;
p+=twoDyMinusDx;
draw_pixel(x,y);
}
}
}
voiddisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
Bresenham(0,0,400,400);
glFlush();
}
voidmyinit()
{
glClearColor(0.8,1.0,1.0,1.0);
glColor3f(0.0,0.0,1.0);
glPointSize(1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,500.0,0.0,500.0);
}
voidmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(200.0,200.0);
glutCreateWindow("CG_test_Bresenham_Lineexample");
glutDisplayFunc(display);
myinit();
glutMainLoop();
}
運行效果:
❸ 請問中點bresenham演算法畫圓與bresenham演算法畫圓有區別嗎
Bresenham演算法畫圓:
Bresenham演算法用來畫直線非常方便,但上次也說了,Bresenham演算法也可以用來顯示圓和其他曲線,只需要把直線方程改成圓方程或者其他曲線的方程就行,具體的推理過程就不演示了,大體跟直線的差不多!但由推算的結果可以看出,用Bresenham演算法來畫圓的確是不大明智的做法,要計算的步驟太多,計算速度比專門的畫圓方法慢很多!並且在斜率越大的地方像素的間距就越大,當然我們可以在畫某個像素之前先判斷一下這一點跟前面一點的連線的斜率,然後在適當的時候交換x、y的坐標,但這樣計算量必將增加!
直接給出Bresenham畫圓的代碼:
#include<gl/glut.h>
#include<math.h>
#include<stdio.h>
voiddraw_pixel(intix,intiy)
{
glBegin(GL_POINTS);
glVertex2i(ix,iy);
glEnd();
}
//intinlineround(constfloata){returnint(a+0.5);}
voidBresenham(intx1,inty1,intr,doublea,doubleb,doublec)/*圓心在(x1,y1),半徑為r的圓*/
{
glColor3f(a,b,c);
intdx=r;//intdy=abs(yEnd-y1);
//intp=2*dy-dx;
//inttwoDy=2*dy,twoDyMinusDx=2*dy-2*dx;
intx,y,d1,d2;
/*if(x1>xEnd)
{
x=xEnd;y=yEnd;
xEnd=x1;
}
else
{
x=x1;
y=y1;
}
*/
x=x1;
y=y1+r;
draw_pixel(x1,y1);
draw_pixel(x,y);//起始點裝入幀緩存,起始點是圓的最上面一點,然後按順時針來畫
while(x<=x1+dx)
{
d1=y1+sqrt(pow(r,2)-pow(x-x1,2));/*lower*/
x++;
d2=2*(y1+sqrt(pow(r,2)-pow(x-x1,2)))-2*d1-1;/*lower-upper*/
if(1)
{
y=d1;
draw_pixel(x,y);
draw_pixel(x,2*y1-y);
draw_pixel(2*x1-x,y);
draw_pixel(2*x1-x,2*y1-y);
}
else
{
y++;
//p+=twoDyMinusDx;
draw_pixel(x,y);
}
}
}
voiddisplay()
{
glClear(GL_COLOR_BUFFER_BIT);
Bresenham(250,250,200,0.0,0.0,1.0);
Bresenham(300,250,150,1.0,0.0,0.0);
Bresenham(200,250,150,0.0,1.0,0.0);
//Bresenham(250,300,150,0.8,0.4,0.3);
//Bresenham(250,200,150);
glFlush();
}
voidmyinit()
{
glClearColor(0.8,1.0,1.0,1.0);
//glColor3f(0.0,0.0,1.0);
glPointSize(1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,500.0,0.0,500.0);
}
voidmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(200.0,200.0);
glutCreateWindow("CG_test_Bresenham_Circleexample");
glutDisplayFunc(display);
myinit();
glutMainLoop();
}
以下為程序運行效果:
中點畫圓:
用光柵畫圓的不足在上次已經用實例表示的很明白了,上次畫的那個圓怎麼都不能算滿意,雖然可以通過修改演算法來得到改善,但本來計算步驟就已經很多了,交換坐標重新計算將會大大增加計算機的就是負擔,為此我們採用另一種更加常用的畫圓演算法——中點畫圓演算法,之所以叫做「中點」畫圓演算法是由於它不是像Bresenham演算法那樣所繪像素不是(xk+1,yk)就是(xk+1,yk+1),而是根據這兩個點的中點來判斷是(xk+1,yk)還是(xk+1,yk-1)更接近於圓!
對於給定的半徑r和圓心(x0,y0),我們先計算圓心在原點(0,0)的點,然後將其平移到圓心(x0,y0)處即可,跟Bresenham演算法一樣,我們也可以藉助圓的高度對稱性來減少計算機的計算步驟,在這里我們可以先計算出八分之一圓的像素點,然後根據對稱性繪出其他點。這樣可以大大加快畫圓的速度!
跟光柵化方法一樣,我們還是採用步進的方法來逐點描繪,但這里的決策參數計算方式跟Bresenham不大一樣,設決策參數為p,則:
P=x2+y2-r2
對於任一個點(x,y),可以根據p的符號來判斷點是在圓內還是圓外還是在圓上,這里不多說,假設我們在(xk,yk)處繪制了一個像素,下一步需要確定的是(xk+1,yk)還是(xk+1,yk-1)更接近於圓,在此代入這兩個點的中點來求出決策參數:
Pk=(xk+1)2+(yk-1/2)2-r2
如果Pk<0,則yk上的像素更接近於圓,否則就是yk-1更接近於圓
同理可以推出Pk+1=Pk+2(xk+1)+(yk+12-yk2)-(yk+1-yk)+1
給出一個示例,這個圓比用Bresenham畫出來的好看多了:
#include<glglut.h>
classscreenPt
{
private:
intx,y;
public:
screenPt(){x=y=0;}
voidsetCoords(GLintxCoordValue,GLintyCoordValue)
{
x=xCoordValue;
y=yCoordValue;
}
GLintgetx()const
{
returnx;
}
GLintgety()const
{
returny;
}
voidincrementx(){x++;}
voiddecrementy(){y--;}
};
voiddraw_pixel(intxCoord,intyCoord)
{
glBegin(GL_POINTS);
glVertex2i(xCoord,yCoord);
glEnd();
}
voidcircleMidpoint(GLintxc,GLintyc,GLintradius)
{
screenPtcircPt;
GLintp=1-radius;
circPt.setCoords(0,radius);
voidcirclePlotPoints(GLint,GLint,screenPt);
circlePlotPoints(xc,yc,circPt);
while(circPt.getx()<circPt.gety())
{
circPt.incrementx();
if(p<0)
p+=2*circPt.getx()+1;
else
{
circPt.decrementy();
p+=2*(circPt.getx()-circPt.gety())+1;
}
circlePlotPoints(xc,yc,circPt);
}
}
voidcirclePlotPoints(GLintxc,GLintyc,screenPtcircPt)//描繪八分圓各點
{
draw_pixel(xc+circPt.getx(),yc+circPt.gety());
draw_pixel(xc-circPt.getx(),yc+circPt.gety());
draw_pixel(xc+circPt.getx(),yc-circPt.gety());
draw_pixel(xc-circPt.getx(),yc-circPt.gety());
draw_pixel(xc+circPt.gety(),yc+circPt.getx());
draw_pixel(xc-circPt.gety(),yc+circPt.getx());
draw_pixel(xc+circPt.gety(),yc-circPt.getx());
draw_pixel(xc-circPt.gety(),yc-circPt.getx());
}
voiddisplay()
{
//screenPtPt;
glClear(GL_COLOR_BUFFER_BIT);
circleMidpoint(250,250,200);
glFlush();
}
voidmyinit()
{
glClearColor(0.8,1.0,1.0,1.0);
glColor3f(0.0,0.0,1.0);
glPointSize(1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,500.0,0.0,500.0);
}
voidmain(intargc,char**argv)
{
glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500,500);
glutInitWindowPosition(200.0,200.0);
glutCreateWindow("CG_test_中點畫圓example");
glutDisplayFunc(display);
myinit();
glutMainLoop();
}
運行效果:
❹ 圓光柵最高精度是多少
* 脈沖周期:50到10000
* 精度:±1/10 脈沖周期
❺ 我看到了這么句話,關於圓光柵編碼器的,求高手 告訴我下0.065arc sec 的解析度怎麼算的
我理解:
說明編碼器的一周有10,000線;
但是通過插補可能實驗0.065arc sec 的解析度。
可能是2000細分;10,000 * 2000=20,000,000 即 0.0648 arc sec。
度 (degrees, deg)
角分(arc minutes, arc min, ′)
角秒(arc seconds, arc sec, ″)
密位(mils)
1 度=60角分=3600角秒
1deg=60 arc min=3600 arc sec
1°=60′=3600″
360度=6000密位
1密位=0.06度
360度 / 10000解析度 = 0.036度/1解析度
❻ 光柵測長技術有什麼概念簡介
光柵測長技術是利用光柵產生的莫爾條紋測量位移和輪廓形狀等的長度計量技術。利用光柵產生的莫爾條紋測量位移和輪廓形狀等的長度計量技術。測量位移時,將計量光柵副中的光柵尺和指示光柵分別固定在長度測量工具或機床等的移動件(例如滑架)和不動件(例如機床導軌)上。兩者相隔一個很小的間隙(一般為0.05~0.1毫米)。當滑架移動時,出現在光柵副上的莫爾條紋的周期性光強變化,通過光電轉換元件轉換為正弦波形電信號,經放大、整形、細分、計數和顯示等電子部分後即可得出光柵位移量。
由光源、計量光柵副和光電轉換元件等組成的部件稱為光柵式長度感測器。由光柵式長度感測器和放大、整形、細分、計數和顯示等電子部分組成的系統稱為光柵測量系統,常用具有相位依次差1/4線距的四組線條的光柵作為指示光柵。當以圓光柵副代替長光柵副時,類似的測量系統可用於測量角位移。長、圓光柵測量系統的精確度分別可達1微米/1000毫米和0.5″/360°以上。
隨著光柵製造技術和電子技術的發展,從20世紀50年代開始應用光柵測長技術來測量位移。這種方法已用於三坐標測量機、數字顯示工具顯微鏡、漸開線測量儀、齒輪單面嚙合檢查儀和電子千分尺等的測量系統中,也常用於數字控制機床的定位反饋系統和其他機床的定位系統中。70年代又開始利用莫爾輪廓圖測量表面輪廓形狀和變形等。
❼ 圓光柵測角精度怎麼確定
主要看編碼器的型號是多少線的?還有顯示精度,確定到度分秒,