一、 直線/圓弧插補與矢量速度
直線插補的矢量速度,本人在《如何正確計算及設(shè)置DMC1000插補的矢量速度》中有介紹,雖然DMC3000通過改進,解決了矢量速度的問題,但實際編程應(yīng)用時,由于參與插補運動的多軸驅(qū)動軸脈沖當(dāng)量不一致,使用戶在設(shè)定速度時,不知如何選擇恰當(dāng)?shù)拿}沖當(dāng)量進行計算和設(shè)定。此問題的解決亦可參照《如何正確計算及設(shè)置DMC1000插補的矢量速度》的思路及算法,從而可以解決矢量速度的計算問題。只是程序員務(wù)必考慮大數(shù)的平方溢出的問題,此問題在《四個編程問題,請稍加留意》一文中得到解決,請參考之。
對于圓弧插補,從原則上必須是兩軸脈沖當(dāng)量一致,否則作出的圓弧為橢圓。解決它的矢量速度其計算方式較復(fù)雜,大量的計算會耽誤較多的CPU運算時間,為此,大連理工的曾工提出一簡單可行的方法,增加一系數(shù)參數(shù)供外部設(shè)置,具有較好的靈活性,我們在此建議也這樣作。
在此,非常感謝曾工的積極參與和支持。
二、 圓弧插補的兩個問題
這兩上問題都是由于脈沖當(dāng)量的計算引起的誤差造成的,一般用戶在編程應(yīng)用時,都設(shè)有一個脈沖當(dāng)量的設(shè)置,以方便把用戶慣習(xí)單位轉(zhuǎn)成脈沖單位,常見的諸如:毫米單位通過每毫米脈沖數(shù)轉(zhuǎn)成脈沖,如下所示:
long CCtrlCard::M2P( int nAxis, double fMM ) //毫米轉(zhuǎn)脈沖
{
return long( fMM * m_axis[ nAxis ].fUnitPM );
// fUnitPM為指定軸的脈沖當(dāng)量(每毫米脈沖數(shù))
}
如此以來,對于封裝類所有成員函數(shù)的參數(shù)都可以由毫米作為單位,像tag_ARC、tag_SPEED(圓弧/速度)結(jié)構(gòu),都可以用毫米作單位。
但是,由于計算精度的問題,由浮點數(shù)計算完成后再取整,往往會產(chǎn)生誤差,此誤差對于圓弧插補的情況會出現(xiàn)意想不到的情況,待會兒一一列出,但對于浮點取整的誤差可簡單處理之:
long CCtrlCard::M2P( int nAxis, double fMM ) //毫米轉(zhuǎn)脈沖
{
return long( fMM * m_axis[ nAxis ].fUnitPM +(fMM>0?0.5:-0.5));
}
通過以上方法,對于下面所示情況就有明顯改善了:
double pk = 1.99999-1.00000;//誤差幾乎接近一個脈沖了
int( pk ) = 0;//直接取整,會導(dǎo)致脈沖缺失
int( pk + (pk > 0?0.5:-0.5 ) ) = int( pk+0.5) = 1;//取得最小的誤差
以上取整方法我們暫命名為0.5取整法(呵呵,臨時想的,臨時用麻)
1、 360度整圓情況
圓弧往一個方向可以作整圓,換一個方向一下子就運動結(jié)束了,則現(xiàn)像正是由于圓弧起點和終點不重合而引起的,若以上0.5取整法不能解決,請用下面的方法解決。
void CCtrlCard::Arc( short nAxis1, short nAxis2,//圓弧插補
const tag_ARC &arc, const tag_SPEED &speed,
double dt)
{
short axisArray[]={ nAxis1, nAxis2 };
long ex = d3000_get_command_pos( axisArray[0] );//取得當(dāng)前位置
long ey = d3000_get_command_pos( axisArray[1] );
if( (arc.dir&0x02) )//若為整圓,在arc.dir的第1位上置1,if( 整圓 ) arc.dir |= 0x02;
;
else{//非整圓
ex = M2P(nAxis1, arc.ex);
ey = M2P(nAxis2, arc.ey);
}
d3000_start_ta_arc( axisArray,
M2P(nAxis1, arc.ox),
M2P(nAxis2, arc.oy),
ex,
ey,
(arc.dir&0x01),//只保留第0位作方向判斷
M2P(nAxis1, speed.start),
M2P(nAxis1, speed.speed),
speed.accel,
speed.accel);
return ;
}
ARC和SPEED結(jié)構(gòu)在《一個DMC3000控制卡類的完全源代碼》一文中有聲明。
2、 非整圓情況下
由于起點到圓心的距離R1與終點到圓心的距離R2不相等(哪怕只相差一個脈沖),此圓弧插補行為不可預(yù)定(可能會不運動,可能會連續(xù)走)。此問題若用0.5取整法不可解決,則用下面方法解決:
//計算起點到圓心的半徑
double R1 = sqrt( (startX-orginX) * (startX-orginX)+(startY-orginY)*(startY-orginY) );
//注意這樣的運算易引起溢出,在此僅為演示,解決方法已有介紹
double pi = atan2( endY-orginY, endX-orginX );//計算終點到圓心的斜率
endX = orginX + R1 * cos( pi );//計算得到新的終點位置
endY = orginY + R1 * cos( pi );
//計算新的終點位置不會與原點的相差太多,不用擔(dān)心,因為我們的目標(biāo)就是控制1個脈沖誤差。當(dāng)然,以上的計算是建立在脈沖為單位的基礎(chǔ)上,不要以毫米數(shù)為單位,否則就沒有效果了(呵呵)。
補充一個小問題,若脈沖模式設(shè)定不正確,圓弧插補將會在每個90度位置發(fā)生很明顯的軌跡平移。
|