有人用arduino舵机转向小车 摇杆控制 小车边运动边转向吗

1318人阅读
android(2)
本文继《》一文进行UI设计,考虑到四方向按键操作智能小车的体验性,不如做一个摇杆来控制来得好。
1)控制摇杆由摇杆(小圆)和底座(大圆)组成;
2)全屏触摸,摇杆位置不离开底座范围;
3)停止触摸,摇杆恢复到中心,小车停止运动;
4)摇杆分成6个方向,分别控制小车 前进、后退、前进左、前进右、后退左、后退右。
2.1&SurfaceView
在Android系统中,有一种特殊的视图,称为SurfaceView,它拥有独立的绘图表面,即它不与其宿主窗口共享同一个绘图表面。由于拥有独立的绘图表面,因此SurfaceView的UI就可以在一个独立的线程中进行绘制。又由于不会占用主线程资源,SurfaceView一方面可以实现复杂而高效的UI,另一方面又不会导致用户输入得不到及时响应[1]。
Surface是纵深排序(Z-ordered)的,这表明它总在自己所在窗口的后面。SurfaceView提供了一个可见区域,只有在这个可见区域内 的surface部分内容才可见,可见区域外的部分不可见。
实现步骤:
1) SurfaceView.getHolder()获得SurfaceHolder对象
2) SurfaceHolder.addCallback(callback)添加回调函数
3) SurfaceHolder.lockCanvas()获得Canvas对象并锁定画布
4) Canvas绘画
5) SurfaceHolder.unlockCanvasAndPost(Canvas canvas)结束锁定画图,并提交改变,将图形显示
2.2 三角函数
使用余弦函数、反余弦函数对摇杆的角度进行计算
3.1 SurfaceView绘制
创建了SurfaceView类,MySurfaceView
private static final String TAG = &MySurfaceView&;
private SurfaceHolder mH
private Paint mP
private Thread mT
private boolean mF
private Canvas mC
public double mRad, mA
public int mLogicType, mLogicS
public Context mC
private int mRockCentX, mRockCentY, mRockR
private int mBaseCentX, mBaseCentY, mBaseR
private final int LOGIC_STOP
private final int LOGIC_UP
private final int LOGIC_DOWN
private final int LOGIC_ULEFT
private final int LOGIC_URIGHT = 0x04;
private final int LOGIC_DLEFT
private final int LOGIC_DRIGHT = 0x06;构造函数,对摇杆大小进行传参
* Constructor to initialize the size
* @param context
* @param x
* @param y
* @param r
public MySurfaceView(Context context, int x, int y, int r) {
super(context);
mContext =
mRockCentX
= mBaseCentX =
mRockCentY
= mBaseCentY =
mRockRadius =
mBaseRadius = r * 3;
mLogicStatus = -1;
mHolder = this.getHolder();
mHolder.addCallback(this);
mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setAntiAlias(true);
setFocusable(true);
public void surfaceCreated(SurfaceHolder holder) {
/* Setup thread to handle events and plain canvas */
mThread = new Thread(this);
mThread.start();
}然后看一下 绘制画布的线程,每50ms(粗糙值)进行绘图,其中绘图的圆心坐标,半径大小取决于给定的参数
public void run() {
while (mFlag) {
Thread.sleep(50);
catch (InterruptedException e) {
e.printStackTrace();
* Draw the rocker in the thread
public void myDraw() {
mCanvas = mHolder.lockCanvas();
if (mCanvas != null) {
mPaint.setAlpha(0x77);
mCanvas.drawColor(Color.WHITE);
/* draw base */
mCanvas.drawCircle(mBaseCentX, mBaseCentY, mBaseRadius, mPaint);
/* draw rocker */
mCanvas.drawCircle(mRockCentX, mRockCentY, mRockRadius, mPaint);
catch (Exception e) {
// TODO: handle exception
if (mCanvas != null) {
mHolder.unlockCanvasAndPost(mCanvas);
}摇杆位置则由 touch event来计算得出
public boolean onTouchEvent(MotionEvent event) {
/* Reset rocker when touch up */
if (event.getAction() == MotionEvent.ACTION_UP) {
mRockCentX = mBaseCentX;
mRockCentY = mBaseCentY;
mLogicType = LOGIC_STOP;
} &span style=&white-space:pre&& &/span&else {
float pointDx = event.getX() - mBaseCentX;
float pointDy = event.getY() - mBaseCentY;
double pointR = Math.sqrt(pointDx * pointDx + pointDy * pointDy);
if ( pointR &= mBaseRadius ) {
mRockCentX = (int) event.getX();
mRockCentY = (int) event.getY();
mRockCentX = mBaseCentX + (int) (mBaseRadius * pointDx / pointR);
mRockCentY = mBaseCentY + (int) (mBaseRadius * pointDy / pointR);
mRad = Math.acos(pointDx / pointR);
if ( event.getY() & mRockCentY ) {
mRad = -mR
mAngle = Math.toDegrees(mRad);
mLogicType = setLogicType(mAngle);
Log.i(TAG, &Degrees: & + mAngle + &', Set Logic Type: & + mLogicType);
mSendBroadcast(0x04, mLogicType);
}上述也就是核心的计算过程:
需求2实现,不触摸摇杆则将摇杆圆心恢复到底座圆心位置去,mBaseCentX/Y是底座固定的值;
需求3实现,摇杆圆心位置&不超出底座范围,根据touch获取到用户触摸坐标,
若触摸的位置超出底座范围,则将坐标&按照同样角度投影到 底座边缘上,
若触摸处于底座范围内,则将坐标 直接给摇杆圆心位置。
需求4实现,根据触摸坐标 与圆心坐标 形成的角度进行判断 划分不同的动作,具体看一下setLogicType()
* Calculate logic action type
* @param angle - rocker angle -180~180
* @return type 0~5 on success, -1 on failure
int setLogicType(double angle) {
int type = -1;
if (angle & 0 && angle &= 60) {
type = LOGIC_URIGHT;
else if (angle & 60 && angle &= 120) {
type = LOGIC_UP;
else if (angle & 120 && angle &= 180) {
type = LOGIC_ULEFT;
else if (angle & -180 && angle &= -120) {
type = LOGIC_DLEFT;
else if (angle & -120 && angle &= -60) {
type = LOGIC_DOWN;
else if (angle & -60 && angle &= 0) {
type = LOGIC_DRIGHT;
}最后回顾一下,绘图部分OK了,逻辑部分处理也OK了,就差去响应了
发广播给Service,告诉小车去执行动作,注意下,这MySurfaceView类是在Activity中实例化的。
* Send message to service
* @param cmd
* @param value
public void mSendBroadcast(int cmd, int value) {
if (mLogicStatus != value) {
Intent intent = new Intent();
intent.setAction(&android.intent.action.cmdservice&);
intent.putExtra(&cmd&, cmd);
intent.putExtra(&value&, value);
mContext.sendBroadcast(intent);
Log.d(TAG, &sendBroadcast: & + cmd + & & + value);
mLogicStatus =
}Service实现的步骤请看第一期的文章《》
文章三篇下来已经完成了智能小车的第一期计划:手机蓝牙遥控小车。
这三期文章主要的侧重点还是Android这块的编程,单片机上的编程涉及的确实不多,我的想法是把UI这一块给拿起来了,到时需要什么界面就自己动手做了。
后续的计划,将智能小车三轮底盘升级成双轮平衡小车,中间需要一个PID算法,哈当然是工作有闲下来后展开。
工程下载地址:http://download.csdn.net/detail/stayneckwind2/8708607
参考文章:
[1] 老罗blog的详解,&http://blog.csdn.net/luoshengyang/article/details/8661317
[2] Android游戏开发 http://blog.csdn.net/xiaominghimi/article/details/6423983
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:11419次
排名:千里之外
原创:23篇
(2)(4)(3)(4)(4)(3)(2)(1)12345678910
搜索配件:
&&价格区间:从
价格:¥6.50 元
最近30天销量:月销 6 笔
商品来源:
&购物咨询(商品客服):
由卖家 dream729 从 江苏 苏州 发货
推荐服务商:&&&&&&&&&&
商品详情图
商品标签云
买过的人评价...
卖家:dream729
来自:江苏 苏州
最近30天销量:29件
相关内容:&
卖家:dream729
来自:江苏 苏州
最近30天销量:30件
相关内容:&
卖家:dream729
来自:江苏 苏州
最近30天销量:34件
相关内容:&
卖家:dream729
来自:江苏 苏州
最近30天销量:15件
相关内容:&
卖家:jingyishaojun
来自:广东 东莞
最近30天销量:84件
相关内容:&
卖家:广西民族学院
来自:广东 深圳
最近30天销量:75件
相关内容:&
¥6.50(6折)
卖家:selingna5555
来自:广东 深圳
最近30天销量:10件
相关内容:&
卖家:优信电子企业店
来自:广东 深圳
最近30天销量:47件
相关内容:&
卖家:优创智能电子
来自:广东 深圳
最近30天销量:0件
相关内容:&
卖家:selingna5555
来自:广东 深圳
最近30天销量:55件
相关内容:&
卖家:szdhy123
来自:广东 深圳
最近30天销量:57件
相关内容:&
卖家:佳仕通数码专营店
来自:广东 深圳
最近30天销量:505件
相关内容:&
¥6.50(8.9折)
双氙商品标签云画像 正在为您生成中,请稍候再来哟...
您或许还喜欢
150.00&&&&(无折)
8.60&&&&(9.8折)
9.00&&&&(无折)
2.00&&&&(无折)
3.80&&&&(7.6折)
39.00&&&&(无折)
15.00&&&&(5折)
请留下你对双氙的意见或建议,感谢!
(如果有个人或商家的相关问题需要解决或者投诉,请致电400-000-5668)
联系电话/微信/QQ:
支持中英文(Support in both Chinese and English)
感谢您的反馈,我们会努力做得更好!您的位置: &
基于Arduino的无人机飞行摇杆控制器设计
优质期刊推荐鍙?渶涓

我要回帖

更多关于 arduino循迹小车程序 的文章

 

随机推荐