本帖最后由 hello怪 于 2017-7-25 22:24 编辑
! M0 s9 f9 J4 b
6 e6 J; s% F" }( b(视频里面最终轮子与黑线的距离,都不超过6mm,最小距离只有2mm。虽然也有运气成分在里面,不过就结果来讲已经很令人满意了^_^)
优酷视频网址: http://v.youku.com/v_show/id_XMjkxOTU1MjEyNA==.html 0 M! z; t; q0 ^0 y$ _3 y
首先说说车子的设计思路,希望也能对大家有用。我想到的影响车子走直线的因素有以下几个方面:
- L' x) q) S: c% U场地
2 V+ X, Q7 ^# O3 E 水平度和光滑度
在家里当然瓷砖的效果是最好的
! a/ _ u- ^# w t 线的直度 虽然规则里说起点终点之间不能有黑线,但是因为没用光感,完全是开环控制,所以也无所谓了。这里就直接用了瓷砖上的黑线来说明车子走的直不直
" e/ K- N, h E5 r/ F- P9 H' s$ s! v9 M( }7 D% F8 ]5 m0 K
车子结构
, f9 x; y0 ?; V6 q: t9 }0 T3 d 轮子间距" ^7 B8 N5 Z, P: C
轮子间距越大越好,稍微想一下便知
{3 i: ^# ` I# ~+ i6 U, O. f( o) T$ J 轮子大小
0 s* a8 u$ \" b; T0 h5 } 轮子直径越小越好,而且轮皮要尽量薄(我这里用的是nxt自带的轮子)
0 J, F* K* `) h3 @: W9 |3 W 随动轮的设计" m& r, e5 S. |9 v. J% J, s
随动轮转动时对车子的影响应该尽量小。这里我自己想出了一个设计方案(当然我觉得别人也用过),让车子几乎不受随动轮的影响. p, Y- G/ I0 [5 [0 b( R, [
重心位置/ w: B2 I! u; R/ g' I* ]
重心应该稍稍靠近主动轮以增大主动轮的抓地能力。但是太靠近的话就会降低车子的稳定性,并且升级空间较小9 n) G& R8 \! A) s$ k+ P
结构稳定性 不用说,肯定是越结实越好。但是不能造成重量过大
8 L+ b( I& J7 w1 M. v* {. [: ` 轮子个数 有三种方案:平衡车(独轮或双轮),三轮车,四轮或以上。虽然很想做平衡车,但是无奈暂时不会用陀螺仪。四轮的话转角不好把控,而且结构复杂,所以就用了最简单的三轮车。(另外,我个人认为不能拐弯的车子就不能叫车子~叫火车或者轨道炮比较合适。。。)1 g: L* M/ @; ~. H
驱动方式 这里我选择了直接由马达驱动轮子,不经过任何齿轮传动,一种简单准确的方式驱动. D1 @/ n( c8 Z* a4 r2 A6 B0 r, x6 a4 m
; Y- i0 q. `& c# p
控制程序
2 F% M" n0 z6 H# V( _) A' I3 m 运动过程控制
* J! s2 S2 |9 W 好的程序应该使轮子不打滑,车子运行平稳。由此采取平滑运动的控制方法,让车子开始时(近似)匀加速,直到速度足够(160度每秒)。在开始时,加速度甚至更小,可以参考我的程序(加速度增加->加速度不变->加速度为零)) i6 f* w1 A* g% d
$ }: W: M4 `: f7 G8 ~) p7 P
调试与运行
: A6 W3 F5 w0 v 轮子转速调整(车轮大小的设定)
- C& d8 j& w' k6 d+ ~ 这个就没什么办法,只能硬着头皮调了。调整轮子的大小设置,实际上就是调马达转速,没有什么更有效的解决办法
3 C% F) s7 r6 I 起始位置车子正方向和直线间的夹角
8 J- f; r7 X) \9 u7 u) |* h& } 一个非常重要的因素,可谓差之毫厘谬以千里。所以尽可能减小两者的方向差。顺带一提,开环控制的小车,如果最终结果差距在一厘米只内,就已经没有什么可比性了。一厘米之内运气成分占比很大,因为0.01rad(0.5度以内)的夹角足以造成差距一厘米的偏差。这就是开环控制的特点 6 h# s/ f9 B+ p; p0 _
1 x- t( y% g' o, b% @$ s
( \4 Y& c3 L# g
然后上源代码: - 4 R2 O# S- Z1 Z. s7 y' W
- importlejos.robotics.navigation.DifferentialPilot;$ y& a- S7 g- u+ D
- import lejos.util.Delay;1 K7 L' R3 v4 L/ s6 h
- ; ~# C4 i% Q! k! w5 e+ U& ]- t2 x
- /**
1 Y4 ]( ?/ X: J I! h - *Robot that stops if the buttons are presses before it completes its travel./ G |# x! t- J" s$ N$ H u
- */- }7 G2 c/ s: u. f) O- K: F: l+ |
" `: W5 J- e5 q3 ?5 a7 D- * @5 m x* f5 q+ p$ O
- public class Straight {6 i l, M6 M8 o5 ~$ S
- DifferentialPilotpilot;/ c R3 Z8 d5 r# R& t
- doubleleftD = 4.3, rightD = 4.3;
/ m6 ]- w; r7 N$ c1 Z5 n - 2 c% A. H/ g6 W. k' n6 V6 p) A6 `
- publicvoid adjust() {
0 v) }0 {" ` X/ n; x% @0 C - //wait for release& O' }" c1 w: i# I: E2 h
- while(Button.readButtons() > 0)
7 u4 m1 x$ L2 v; L0 O& v6 `, ? - ;7 X5 c' o/ M9 G5 _
- while(Button.readButtons() == 0) {
' e, t A* p* Y5 n5 E+ ?4 y5 C - //input size by adjusting the wheels! X" U8 |0 Y& A
- rightD= (double) (Motor.A.getTachoCount()) / 2160 + 4.3;
/ v0 _ L& @* n4 R* v, @ - leftD= (double) (Motor.B.getTachoCount()) / 2160 + 4.3148;// 调试所得值; i3 ?: E F' d* {
- 7 |5 U' U# R' A8 M7 k2 j
- //display the size input/ e h& G+ {$ i) b7 j7 Z) w+ d
- LCD.drawString("L:"+ String.valueOf(leftD), 0, 0);
. X: g; h% R! m1 l4 V5 g' k - LCD.drawString("R:"+ String.valueOf(rightD), 0, 1);
% X* o: I- y, {! D F9 M* u: G* ` - Delay.msDelay(100);
& a$ r' `7 w% G: o+ ~$ \- D' S - LCD.clear();
2 a( K( I1 z% ]; }. \" n - }
/ h0 O J2 R8 n' t - : m8 B$ o: C2 Z8 _
- }* B6 Q- f& ~, O. z% \( J: t8 W
/ r1 ~, _ n' @) O8 u- publicvoid go() {7 x7 J& b" i C; F- s# P
- //准备起步) e A0 K9 ^& M& W! o
- //wait for release' z( O% G" z% Q. o" _+ E( G
- while(Button.readButtons() > 0)4 w0 j/ z. A" u* [+ N% @0 c4 f
- ;- P, F5 N0 H& K, c3 W5 c- D% K; c& s
- System.out.println("pressto go");
, N' D# ^' `' J - 5 t" P! X1 Y4 ~0 \
- Button.waitForAnyPress();
3 O8 {7 u$ b9 u" \; o7 H - LCD.clear();
3 R1 S7 t; V G) M3 |
( k! J. r& i, A/ u- //初始化
. m( s* x% [) w; p7 t7 h5 z" t" D - pilot= new DifferentialPilot(rightD, leftD, 13.5, Motor.A, Motor.B, true);
% t% i8 C: }) L( @6 }" B - pilot.reset();' a2 |- H5 g+ J( { O# { b
% B$ O" i: `8 x* ]7 W7 \$ K3 G, f. W- Delay.msDelay(3000);
! P& V# [4 L$ m/ g+ i
# r5 q. q! b, C+ D+ Q7 F$ L8 H- doublespeed = 10;% _: _ B+ [$ y" S; o" v8 h/ Y
- doubledistance = 0;
- S# g3 l L5 A% ?9 A: C/ m
8 j/ b$ C% {3 L8 O# Y- //起步加速' j6 p* _% Z- c0 s
- pilot.travel(300,true);
/ _! L. V) r+ w% |" C. e. S
/ I6 N; m! m# A- D6 B- while(distance < 20) {, ?# ?. I, E& q- w; H
- distance= pilot.getMovement().getDistanceTraveled();
5 a' `7 ]: R0 X" d - speed= distance * 5 + 10;
. t1 h& W, ^8 m3 ^- f4 @ - pilot.setRotateSpeed(speed);$ \# q9 U* O( M: x7 e& F
- Delay.msDelay(100);4 X5 s" }+ U' P: `
- }
5 l* R% n' J6 k8 G/ l - for(int i = 0; i < 10; i++) {3 V# F7 |5 G3 ^! q
- speed+= 5;
5 ^0 A' ]0 \, {8 n/ }' r- O0 Q - pilot.setRotateSpeed(speed);
* J' z+ U, Z7 y) }, R. @ - Delay.msDelay(200);
0 ]$ J3 W1 A7 A9 `$ e) O - }$ ?, s, J; t3 @ |) f
+ L1 @" o6 C. G: d( v- //TODO 减速
# B* i4 L( y& i0 A2 i( O
. y/ u; D. \5 q- //停止机能* i9 W, e* T' p' z9 l/ D8 ?0 p0 b
- while(pilot.isMoving()) {6 T7 }8 R5 r. m
- if(Button.readButtons() > 0)
) i7 G0 E1 [3 h& N+ D, D" f& p - pilot.stop();
, \( G" F$ {9 r9 a& {4 r - }! t" h1 ^9 L9 f6 | G. Y
* E! w; G$ `# u0 P# j- System.out.println("" + pilot.getMovement().getDistanceTraveled());' g+ b( p4 V2 J# S$ W
- System.out.println(-Motor.A.getTachoCount());. T0 a7 K3 y+ @, M
- System.out.println(-Motor.B.getTachoCount());' _9 H( {# ]3 x4 w7 b
- Button.waitForAnyPress();
3 _% ^; n& M( J3 ?3 m3 R - }2 E$ Z9 P& r4 F/ V: L2 f: |- S3 T
- 2 Q/ X0 u+ O- |, u9 `
- publicstatic void main(String[] args) {
4 T2 C F' r0 e. w6 v& W+ F - Straighttraveler = new Straight();% D$ R; I* o0 O: V
9 h. p: A; J5 o& o0 ~1 e- traveler.adjust();
/ i' h' @& Z5 |) c4 S; y - traveler.go();$ y; }, _/ p; B
- }
2 L% }9 b* ?0 J: p' k" f - }
复制代码
# h \; B$ U0 V' O& h |