RoBoard魔人的機器人日誌

2013/12/6

[機械六足] 智慧手機控制器

上次發了一篇近況文

也告訴了大家我下一步想要做的東西

那魔人就來一步一步的製作&分享給大家吧

今天要分享的是智慧手機控制器的搖桿控制

還記得上次我的介紹吧

我要用遙感的方式控制六足的前進方向

而遙桿在網路上的範例已經有很多了

實做的方法是這樣的

用canvas畫圖 & 用Thread讀取螢幕觸碰的事件

讀取後去計算 & 重新畫圖   就可以做到搖桿的效果了

以下影片範例



這個範例是控制小android在螢幕上移動




接著是程式碼囉

MainActivity.java

package com.example.joystick;

import android.os.Bundle;
import android.app.Activity;
import android.view.WindowManager;

public class MainActivity extends Activity {

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
    WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(new GameSurface(this));
 }
}

GameControl.java
package com.example.joystick;

import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;

public class GameControls implements OnTouchListener{

 public float initx = 0;
 public float inity = 0;
 public Point _touchingPoint = new Point(0,0);
 public Point _pointerPosition = new Point(220,150);
 private Boolean _dragging = false;
 private double degree = 0;
 @Override
 public boolean onTouch(View v, MotionEvent event) {

  update(event);
  return true;
 }

 private MotionEvent lastEvent;
 public void update(MotionEvent event){

  if (event == null && lastEvent == null)
  {
   return;
  }else if(event == null && lastEvent != null){
   event = lastEvent;
  }else{
   lastEvent = event;
  }
  if ( event.getAction() == MotionEvent.ACTION_DOWN ){
   _dragging = true;
  }else if ( event.getAction() == MotionEvent.ACTION_UP){
   _dragging = false;
  }
  

  if ( _dragging ){
   _touchingPoint.x = (int)event.getX();
   _touchingPoint.y = (int)event.getY();
   
   _touchingPoint.x -= 250;
   _touchingPoint.y -= 250;
   if(_touchingPoint.x == 0 && _touchingPoint.y > 0)
    degree = Math.PI / 2;
   else if(_touchingPoint.x == 0 && _touchingPoint.y < 0)
    degree = Math.PI / 2 * 3;
   else if(_touchingPoint.x > 0)
    degree = Math.atan((double)_touchingPoint.y/_touchingPoint.x);
   else if(_touchingPoint.x < 0)
    degree = Math.PI + Math.atan((double)_touchingPoint.y/_touchingPoint.x);
   
   if(Math.sqrt(Math.pow(_touchingPoint.x,2) + Math.pow(_touchingPoint.y,2)) > 150){

    _touchingPoint.x = (int) (150.0 * Math.cos(degree));
    _touchingPoint.y = (int) (150.0 * Math.sin(degree));
    
   }
   
   _pointerPosition.x += ((double)_touchingPoint.x/30);
   _pointerPosition.y += ((double)_touchingPoint.y/30);
   if ( _pointerPosition.x > 480)
   {
    _pointerPosition.x= 0;
   }

   if ( _pointerPosition.x < 0){
    _pointerPosition.x = 480;
   }

   if (_pointerPosition.y > 840 ){
    _pointerPosition.y = 0;
   }
   if (_pointerPosition.y < 0){
    _pointerPosition.y = 840;
   }

  }else if (!_dragging)
  {
   if(Math.sqrt(Math.pow(_touchingPoint.x,2) + Math.pow(_touchingPoint.y,2)) <= 10){
    _touchingPoint.x = (int) initx;
    _touchingPoint.y = (int) inity;
   }else{
    _touchingPoint.x = (int) ((Math.sqrt(Math.pow(_touchingPoint.x,2) + Math.pow(_touchingPoint.y,2)) - 10)* Math.cos(degree));
    _touchingPoint.y = (int) ((Math.sqrt(Math.pow(_touchingPoint.x,2) + Math.pow(_touchingPoint.y,2)) - 10)* Math.sin(degree));
   }
   _pointerPosition.x += ((double)_touchingPoint.x/30);
   _pointerPosition.y += ((double)_touchingPoint.y/30);
   if (_pointerPosition.x > 480)
    _pointerPosition.x= 0;
   if (_pointerPosition.x < 0)
    _pointerPosition.x = 480;
   if (_pointerPosition.y > 840)
    _pointerPosition.y = 0;
   if (_pointerPosition.y < 0)
    _pointerPosition.y = 840;
  }
 }
}


GameJoystick.java
package com.example.joystick;

import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class GameJoystick {
 
 private Bitmap _joystick;
 private Bitmap _joystickBg;
 private Bitmap _trigger;
 private Bitmap _triggerDown;
 
 public Bitmap get_triggerDown() {
  return _triggerDown;
 }

 public void set_triggerDown(Bitmap triggerDown) {
  _triggerDown = triggerDown;
 }

 public GameJoystick(Resources res){
  
  _joystick = (Bitmap)BitmapFactory.decodeResource(res, com.example.joystick.R.drawable.joystick2);
  _joystickBg = (Bitmap)BitmapFactory.decodeResource(res, com.example.joystick.R.drawable.joystick_bg2);

 }

 public Bitmap get_joystick() {
  return _joystick;
 }

 public void set_joystick(Bitmap joystick) {
  _joystick = joystick;
 }

 public Bitmap get_joystickBg() {
  return _joystickBg;
 }

 public void set_joystickBg(Bitmap joystickBg) {
  _joystickBg = joystickBg;
 }
 
 public Bitmap get_trigger() {
  return _trigger;
 }

 public void set_trigger(Bitmap trigger) {
  _trigger = trigger;
 }
}


GameSurface.java
package com.example.joystick;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Handler;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameSurface extends SurfaceView implements SurfaceHolder.Callback {

 private Context _context;
 private GameThread _thread;
 private GameControls _controls;

 private GameJoystick _joystick;
 private Bitmap _pointer;

 public GameSurface(Context context) {
  super(context);
  _context = context;
  init();
 }

 private void init(){
  SurfaceHolder holder = getHolder();
  holder.addCallback( this);

  _thread = new GameThread(holder, _context, new Handler(),this);
  setFocusable(true);


  _joystick = new GameJoystick(getContext().getResources());
  _pointer = (Bitmap)BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
  _controls = new GameControls();
  setOnTouchListener(_controls);
 }


 public void doDraw(Canvas canvas){

  _controls.update(null);
  
  canvas.drawBitmap(_joystick.get_joystickBg(), 100,100, null);

  canvas.drawBitmap(_joystick.get_joystick(),_controls._touchingPoint.x + 200, _controls._touchingPoint.y + 200, null);

  canvas.drawBitmap(_pointer, _controls._pointerPosition.x, _controls._pointerPosition.y, null);

 }

 @Override
 public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}
 private boolean retry;
 @Override
 public void surfaceDestroyed(SurfaceHolder arg0) {
  retry = true;
  _thread.state = GameThread.STOPED;
  while (retry) {
   try {
    _thread.join();
    retry = false;
   } catch (InterruptedException e) {
   }
  }

 }

 @Override
 public void surfaceCreated(SurfaceHolder arg0) {
  if(_thread.state==GameThread.PAUSED){
   _thread = new GameThread(getHolder(), _context, new Handler(),this);
   _thread.start();
  }else{
   _thread.start();
  }
 }

 public void Update() {

 }

}



GameThread.java
package com.example.joystick;

import java.util.logging.Level;
import java.util.logging.Logger;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Handler;
import android.view.SurfaceHolder;

public class GameThread extends Thread {

 private SurfaceHolder mSurfaceHolder;
 private Handler mHandler;
 private Context mContext;
 private Paint mLinePaint;
 private Paint blackPaint;

 private long sleepTime;
 private long delay=70;
 int state = 1;
 public final static int RUNNING = 1;
 public final static int PAUSED = 2;
 public final static int STOPED = 3;

 GameSurface gEngine;

 public GameThread(SurfaceHolder surfaceHolder, Context context, Handler handler,GameSurface gEngineS){
  mSurfaceHolder = surfaceHolder;
  mHandler = handler;
  mContext = context;
  gEngine=gEngineS;
 }

 private long beforeTime;
 @Override
 public void run() {

  //UPDATE
  while (state==RUNNING) {
   try {
    this.sleep(50);
   } catch (InterruptedException e1) {
    e1.printStackTrace();
   }
   beforeTime = System.nanoTime();
   gEngine.Update();

   Canvas c = null;
   try {
    c = mSurfaceHolder.lockCanvas(null);
    synchronized (mSurfaceHolder) {
     c.drawColor(0x66000000);
     gEngine.doDraw(c);
    }
   } finally {
    if (c != null) {
     mSurfaceHolder.unlockCanvasAndPost(c);
    }
   }


   this.sleepTime = delay-((System.nanoTime()-beforeTime)/1000000L);

   try {
    if(sleepTime>0){
     this.sleep(sleepTime);
    }
   } catch (InterruptedException ex) {
    Logger.getLogger(GameThread.class.getName()).log(Level.SEVERE, null, ex);
   }
   
   while (state==PAUSED){
    try {
     this.sleep(1000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
   }
  }
 }}

Share:

2013/11/29

[RB魔人] 用小型區網建立良好的開發環境(五)

最近魔人拿到了一塊好東西


沒錯   它就是無線wifi啦

大家可能會好奇   現在這個時代   wifi有什麼好稀奇的

各位還記得魔人之前有發了四篇的系列文章也是介紹網路的嘛?

這次要介紹的就是   如何用wifi建立良好的開發環境

剩(線)勝有(線)嘛

而且之前本魔是使用藍芽做控制的

現在也不用這麼麻煩了

用網路就好啦~

檔案傳輸也沒問題

如此方便   就快點來教學吧

首先要有一顆USB的無線AP

裝上RoBoard



之後安裝驅動程式




安裝完之後便可找到裝置

之後設定wifi的名稱等




之後選橋接器連結   將無線網路與區網連結在一起


之後進入剛剛設定的網路就可以囉




再來是PC端

選擇連線後輸入密碼

之後就是一個小型的區域網路囉 

你也可以直接遠端到另一台電腦





















這讓本魔想到了

在某些地方連wifi時不是會有登入的頁面跑出來嘛?

如果我把機器人的手機控制程式丟在登入的網頁

那麼不就能夠用任何一台的手機裝置去控制了?


所以我最近會順便研究看看wifi登入頁面那如何實做

如果有神人知道方法    也敬請指教喔^^
Share:

2013/11/3

[機械六足] 近期新計畫

兩個月沒有更新文章了

大家有沒有想魔人阿XD

其實這一兩個月真的是由於學校的事務所以有些忙碌

然而這一兩個月魔人也不是閒著的喔!

這次要進行機械六足的新計畫了

之前各位都有看到我與實習生們合力製作的[RoBoard x League of Legends] 史加納Skarnar

而當時推出的影片也受到了大家的肯定及迴響   ((在此說聲謝謝

而現在魔人要一個人繼續製作這台機械六足

將步態變得更加的完整

之前的步態   如果各位有看過source code   或是認真看過影片的話

就會發現其實我的移動方式只有6種

包括前後左右平移,加上左右轉彎

而魔人我是不會就此滿足的!

所以現在魔人我有一個新的想法

用智慧手機控制機械六足!

以下為設計草圖


























看不懂沒關係!

魔人來為您解釋

首先就是手機上會有搖桿的圖示

在上面推移就會決定機械六足的前進方向以及步距or速度

而智慧手機上的陀螺儀感測器可以決定六足身體的平衡


那各位說不定會想問這樣到底有幾種步態

答案是1~2種   一種是轉彎的步態  一種是平移的步態

大家別急!

雖然是只有兩種步態   但是移動的方向是由搖桿決定的

而那排列組合   就可以請各位去計算看看了

而或許也會想加入一些對話的功能

這方面還在思考要怎麼做當中











別認為魔人我是光說不練的

魔人我其實有開始在動工了喔!

近期會有個小成果上來給各位看看的!
Share:

2013/9/5

[RoBoard x League of Legends] 史加納Skarnar

相信各位都知道現在相當火紅的遊戲英雄聯盟

本魔此次與第六屆的實習生們一起合作做了一隻英雄聯盟裡的角色

而此次的作品也是完全open source的

但我們必須要在2個月內趕出成果,所以我們很快的開始了這個開源計畫



最一開始

我們有想過製作烏爾加特或布里茲

烏爾加特

布里茲
但是我們最後決定選擇了史加納

史加納


六隻腳走起來比較霸氣!對吧?

所以大家開始著手製作,基本上本魔負責最後的程式控制

而機構設計以及電路與造型則是交由實習生們來做

於是找到了一款較適合機器人的模組讓我們參考


在大家的努力下,首先做出了Solidworks的機構圖


相當帥氣對吧?

基本上頭部與外殼要用3D printer印出來,這樣也可以做出我們要的樣子

既然畫好圖了,那麼大家就開始動手實做出來

而本魔也沒閒著

六足機器人如果還用編動作的不是就low掉了嗎!?

沒錯!

這次本魔要用反運動學來算!

所以要了機構的長度,以方便計算



第一次拿到實體機器時,本魔相當興奮


立刻用RoBoME簡單的編了一個走路

立刻來看看由於是貼在facebook上面,所以要請各位移駕一下

==========>影片連結video link<==========

可以很明顯的感受到機械式的走法

但本魔是不會安於現狀的!

約過了一周,首先史加納的頭印好了,而本魔的反運動學步行也有了個雛形



以下影片


看起來順暢許多吧?

沒錯,而且加上了手的動作,實在霸氣許多

最後,完整版出來了

眼睛加上了紅色的LED

外殼也加了上去

甚至加了噴漆做顏色裝飾

還有最霸氣的超大聲喇叭

先來看看圖片吧!


帥吧!?

別急

後面還有影片!






最後來個maker的合影



既然是open source的計畫

那當然要opne code與design了

以下連結

Github Robot-Skarnar

RoBoard粉絲專頁



Maker list:
朱酉致 / Chu Ue Chih
李智皓 / Li Chih Hao
鄒秉翰 / Tsou Ping Han
RB魔人 / RoBoardGod


如果你喜歡,請幫我們到facebook按【讚】,謝謝。
If you like this, please click the【Like!】on our facebook comment, thank you.


Share:

2013/8/9

[教學] 如何使用C#存取MySQL資料庫

今天本魔要講講如何使用C#存取MySQL資料庫

MySQL是一個open source的關聯性資料庫管理系統

可能會有人有疑問說:「資料庫和機器人怎麼有會關聯呢?」

本魔在此告訴你!一定有關聯的!

因為關聯這種東西就是讓我們扯出來的!

在網路上的資料庫可以隨時供電腦做存取

這樣一來,我們就可以很方便的管理一些資料了

也有可能可以把動作資料建立在資料庫上供機器人使用(好像很久以前有人就有給過我這個建議了)

這樣除了較不用擔心資料會隨著機器人損壞

更增加了許多的擴充性




那麼本魔在此就不教學如何安裝MySQL了

各位自己上網Google應該很好找到

那麼就開始我們的教學!

首先各位需要安裝MySQL官方所提供的Connector

安裝好了之後就可以開啟我們的Visual Studio建一個C#的專案囉!

首先要加入參考    [Project] ->[Add Reference]->[瀏覽]

選擇安裝路徑下的MySql.Data.dll



路徑通常在C:\Program Files\MySQL\MySQL Connector Net 6.6.5\Assemblies\v2.0

加入參考了之後會看到方案總管內的Reference有加入了MySql.Data囉


接了我們就可以開始撰寫程式囉

以下給各位新增、刪除、修改、查詢的範例

其實相當簡單

基本上就是與MySQL一樣   丟一串指令給他   他會回傳一些資料給你

首先假設我們的資料表的內容是這樣子的而資料表名稱為member


那我們先來新增10筆會員資料


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
namespace MySQLtest
{
    class Program
    {
        static void Main(string[] args)
        {
            string dbHost = "";//資料庫位址
            string dbUser = "";//資料庫使用者帳號
            string dbPass = "";//資料庫使用者密碼
            string dbName = "";//資料庫名稱

            string connStr = "server=" + dbHost + ";uid=" + dbUser + ";pwd=" + dbPass + ";database=" + dbName;
            MySqlConnection conn = new MySqlConnection(connStr);
            MySqlCommand command = conn.CreateCommand();
            conn.Open();

            String account;
            String password;
            int level;
            for(int i = 0; i < 10; i++){
                account = "account" + i.ToString();
                password = "password" + i.ToString();
                level = i * 10;
                command.CommandText = "Insert into member(account,password,level) values('"+ account +"','"+ password +"',"+ level +")";
                command.ExecuteNonQuery();
            }
            Console.ReadLine();
            conn.Close();
        }
    }
}


這樣執行後我們就可以看到資料表內增加了十筆資料囉
接著是刪除

假如我想刪除id為15的用戶

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
namespace MySQLtest
{
    class Program
    {
        static void Main(string[] args)
        {            string dbHost = "";//資料庫位址
            string dbUser = "";//資料庫使用者帳號
            string dbPass = "";//資料庫使用者密碼
            string dbName = "";//資料庫名稱

            string connStr = "server=" + dbHost + ";uid=" + dbUser + ";pwd=" + dbPass + ";database=" + dbName;
            MySqlConnection conn = new MySqlConnection(connStr);
            MySqlCommand command = conn.CreateCommand();
            conn.Open();


            command.CommandText = "Delete FROM member WHERE id=15";
            int n  = command.ExecuteNonQuery();

            Console.WriteLine("共刪除 {0} 筆資料", n);
            Console.ReadLine();
            conn.Close();
        }
    }
}



那麼執行後就可以發現id為15的資料不見囉

接著是修改

這裡把account6的password改為1234

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
namespace MySQLtest
{
    class Program
    {
        static void Main(string[] args)
        {            string dbHost = "";//資料庫位址
            string dbUser = "";//資料庫使用者帳號
            string dbPass = "";//資料庫使用者密碼
            string dbName = "";//資料庫名稱
            string connStr = "server=" + dbHost + ";uid=" + dbUser + ";pwd=" + dbPass + ";database=" + dbName;
            MySqlConnection conn = new MySqlConnection(connStr);
            MySqlCommand command = conn.CreateCommand();
            conn.Open();


            command.CommandText = "Update member SET password='1234' WHERE account='account6'";
            command.ExecuteNonQuery();


            Console.ReadLine();
            conn.Close();
        }
    }
}



再來看看資料表   沒錯   正確的改過去了


最後就是查詢啦

那我們來查詢看看level小於50的所有用戶

然後顯示在電腦上吧

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
namespace MySQLtest
{
    class Program
    {
        static void Main(string[] args)
        {   string dbHost = "";//資料庫位址
            string dbUser = "";//資料庫使用者帳號
            string dbPass = "";//資料庫使用者密碼
            string dbName = "";//資料庫名稱
            string connStr = "server=" + dbHost + ";uid=" + dbUser + ";pwd=" + dbPass + ";database=" + dbName;
            MySqlConnection conn = new MySqlConnection(connStr);
            MySqlCommand command = conn.CreateCommand();
            conn.Open();

            String cmdText = "SELECT * FROM member WHERE level < 50";
            MySqlCommand cmd = new MySqlCommand(cmdText, conn);
            MySqlDataReader reader = cmd.ExecuteReader(); //execure the reader
            while (reader.Read())
            {
                for (int i = 0; i < 4; i++)
                {
                    String s = reader.GetString(i);
                    Console.Write(s + "\t");
                }
                Console.Write("\n");
            }


            Console.ReadLine();
            conn.Close();
        }
    }
}





最後結果是

正確!
Share:

2013/7/5

[RoBoME] Smartphone Controller

最近進擊巨人很夯

所以機器人也要進擊一下這樣
以下影片演示給大家看:







這次本魔開發的是RoBoME的控制器喔~

只要將你用RoBoME編寫的動作丟到智慧手機裡就可以做控制了!!

聽起來相當的容易吧~

以下教學

首先智慧手機上的程式我有打包apk供各位下載安裝囉~   LINK

然後RoBoard上必須要有接收端程式     LINK

附注:   接收端程式我預設是接到COM8 所以藍芽設定請設定到COM8

接著   只要在智慧手機根目錄下建置一個資料夾為RoBoME (如下圖)

然後將檔案放入即可喔!

無feedback的機器人記得要放入homeframe文件

或有聲音也要放入喔

開啟應用程式後   會看到兩個欄位

第一個欄位用來選rbm檔案

第二個欄位為選擇藍芽通道
 完成後按下Start
出現此介面後

先按下Start   再開啟Power   它就會給馬達電了

下面中文字的部分是我們已經編輯好的動作   它會自動生成按鈕來做整套的動作

相信眼睛很利的大家都有看到voice的按鈕

沒錯   這按鈕就是用來做聲控的

你只要念出下面按鈕的名稱   它就會做對應的動作囉!!



P.S.介面相當的陽春   不過別太介意啦=D   有時間的話再來認真的設計界面吧
Share:

2013/6/7

[練習] AX-12輪胎 簡易控制程式

在很久之前本魔有介紹過AX-12轉動的方法

而今天我要介紹的是AX-12的全轉模式

基本上在官方的文件中有提到喔!

Address 0x20,0x21 
Moving Speed. Sets the angular velocity of the output moving to the Goal Position. Setting this value to its maximum value of 0x3ff moves the output with an angular velocity of 114 RPM, provided that there is enough power supplied (The lowest velocity is when this value is set to 1. When set to 0, the velocity is the largest possible for the supplied voltage, e.g. no velocity control is applied.)

沒錯的   所以我們只要將Operating Angle Limit設定為0    它就會進入全轉模式

而官方文件中也有寫到Operating Angle Limit 的Address為0x06,0x07,0x08,0x09

在這之後我們只要控制轉動速度    就可以讓馬達旋轉囉!!

那就讓我們來看看程式碼吧!!

首先看看介面的設計 在此本魔是使用C#來做的


應該是不會很難理解的

下面的上下左右button是可以讓輪胎轉動   直到按下stop button

上面的 speed則是可以調整轉速

keyboard mode則是可以讓我們使用WSAD來控制輪胎

那我們來看看本魔實做的辦法吧   

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using RoBoIO_DotNet;
namespace controller_AX12
{
    public partial class Form1 : Form
    {
        public byte[] ax01 = new byte[11]{ 0xff, 0xff, 0x0f, 0x07, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00 };
        public byte[] ax02 = new byte[11]{ 0xff, 0xff, 0x12, 0x07, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00 };
        public byte[] read = new byte[6];
        public int run;
        public Form1()
        {
            InitializeComponent();
            groupBox1.Enabled = false;
            checkBox1.Enabled = false;
            run = 0;
            
        }
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            //RoBoIO.com3_DisableTurboMode();
            RoBoIO.com3_Close();
        }
        private void Start_Click(object sender, EventArgs e)
        {
            if (!groupBox1.Enabled){
                if (!RoBoIO.roboio_SetRBVer(RoBoIO.RB_100RD))
                    MessageBox.Show("roboio_SetRBVer fail");
                if (!RoBoIO.com3_Init(RoBoIO.COM_HDUPLEX))
                    MessageBox.Show("com3_Init fail");
                if (!RoBoIO.com3_SetFormat(RoBoIO.COM_BYTESIZE8, RoBoIO.COM_STOPBIT1, RoBoIO.COM_NOPARITY))
                    MessageBox.Show("com3_SetFormat fail");
                if (!RoBoIO.com3_SetBaud(RoBoIO.COMBAUD_115200BPS))
                    MessageBox.Show("com3_SetBaud fail");
                //RoBoIO.com3_EnableTurboMode();
                groupBox1.Enabled = true;
                checkBox1.Enabled = true;
                Start.Enabled = false;
                ax02[10] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7] + ax02[8] + ax02[9]))[0];
                ax01[10] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7] + ax01[8] + ax01[9]))[0];
                if (!RoBoIO.com3_ServoTRX(ax01, 11, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                if (!RoBoIO.com3_ServoTRX(ax02, 11, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                ax01[3] = 0x05;
                ax01[5] = 0x20;
                ax02[3] = 0x05;
                ax02[5] = 0x20;
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            xUp();
        }
        private void xUp() {
            int speed = 10;
            if (run != 0)
            {
                Stop(5);
                speed = 5;
            }
            int v = speedbar.Value;
            run = 1;
            for (int i = 0; i < v % 0x3ff; i = i + v / speed)
            {
                ax01[6] = BitConverter.GetBytes(0x00ff & (i + 0x400))[0];
                ax01[7] = BitConverter.GetBytes((0xff00 & (i + 0x400)) / 0xff)[0];
                ax02[6] = BitConverter.GetBytes(0x00ff & i)[0];
                ax02[7] = BitConverter.GetBytes((0xff00 & i) / 0xff)[0];
                ax02[8] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7]))[0];
                ax01[8] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7]))[0];
                if (!RoBoIO.com3_ServoTRX(ax01, 9, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                if (!RoBoIO.com3_ServoTRX(ax02, 9, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                RoBoIO.delay_ms(25);
            }
        }
        private void button3_Click(object sender, EventArgs e)
        {
            xdown();
        }
        private void xdown() {
            int speed = 10;
            if (run != 0)
            {
                Stop(5);
                speed = 5;
            }
            int v = speedbar.Value;
            run = 2;
            for (int i = 0; i < v % 0x3ff; i = i + v / speed)
            {
                ax01[6] = BitConverter.GetBytes(0x00ff & i)[0];
                ax01[7] = BitConverter.GetBytes((0xff00 & i) / 0xff)[0];
                ax02[6] = BitConverter.GetBytes(0x00ff & (i + 0x400))[0];
                ax02[7] = BitConverter.GetBytes((0xff00 & (i + 0x400)) / 0xff)[0];
                ax02[8] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7]))[0];
                ax01[8] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7]))[0];
                if (!RoBoIO.com3_ServoTRX(ax01, 9, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                if (!RoBoIO.com3_ServoTRX(ax02, 9, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                RoBoIO.delay_ms(25);
            }
        }
        private void button2_Click(object sender, EventArgs e)
        {
            xleft();
        }
        private void xleft() {
            int speed = 10;
            if (run != 0)
            {
                Stop(5);
                speed = 5;
            }
            int v = speedbar.Value;
            run = 3;
            for (int i = 0; i < v % 0x3ff; i = i + v / speed)
            {
                ax01[6] = BitConverter.GetBytes(0x00ff & (i + 0x400))[0];
                ax01[7] = BitConverter.GetBytes((0xff00 & (i + 0x400)) / 0xff)[0];
                ax02[6] = BitConverter.GetBytes(0x00ff & (i + 0x400))[0];
                ax02[7] = BitConverter.GetBytes((0xff00 & (i + 0x400)) / 0xff)[0];
                ax02[8] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7]))[0];
                ax01[8] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7]))[0];
                if (!RoBoIO.com3_ServoTRX(ax01, 9, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                if (!RoBoIO.com3_ServoTRX(ax02, 9, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                RoBoIO.delay_ms(25);
            }
        }
        private void button4_Click(object sender, EventArgs e)
        {
            xright();
        }
        private void xright() {
            int speed = 10;
            if (run != 0)
            {
                Stop(5);
                speed = 5;
            }
            int v = speedbar.Value;
            run = 4;
            for (int i = 0; i < v % 0x3ff; i = i + v / speed)
            {
                ax01[6] = BitConverter.GetBytes(0x00ff & i)[0];
                ax01[7] = BitConverter.GetBytes((0xff00 & i) / 0xff)[0];
                ax02[6] = BitConverter.GetBytes(0x00ff & i)[0];
                ax02[7] = BitConverter.GetBytes((0xff00 & i) / 0xff)[0];
                ax02[8] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7]))[0];
                ax01[8] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7]))[0];
                if (!RoBoIO.com3_ServoTRX(ax01, 9, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                if (!RoBoIO.com3_ServoTRX(ax02, 9, read, 6))
                    MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                RoBoIO.delay_ms(25);
            }
        }
        private void button5_Click(object sender, EventArgs e)
        {
            Stop(10);
        }
        private void Stop(int speed)
        {
            if (run != 0)
            {
                int v = speedbar.Value;
                switch (run)
                {
                    case 1:
                        for (int i = v % 0x3ff; i > 0; i = i - v / speed)
                        {
                            ax01[6] = BitConverter.GetBytes(0x00ff & (i + 0x3ff))[0];
                            ax01[7] = BitConverter.GetBytes((0xff00 & (i + 0x3ff)) / 0xff)[0];
                            ax02[6] = BitConverter.GetBytes(0x00ff & i)[0];
                            ax02[7] = BitConverter.GetBytes((0xff00 & i) / 0xff)[0];
                            ax02[8] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7]))[0];
                            ax01[8] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7]))[0];
                            if (!RoBoIO.com3_ServoTRX(ax01, 9, read, 6))
                                MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                            if (!RoBoIO.com3_ServoTRX(ax02, 9, read, 6))
                                MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                            RoBoIO.delay_ms(25);
                        }
                        break;
                    case 2:
                        for (int i = v % 0x3ff; i > 0; i = i - v / speed)
                        {
                            ax01[6] = BitConverter.GetBytes(0x00ff & i)[0];
                            ax01[7] = BitConverter.GetBytes((0xff00 & i) / 0xff)[0];
                            ax02[6] = BitConverter.GetBytes(0x00ff & (i + 0x3ff))[0];
                            ax02[7] = BitConverter.GetBytes((0xff00 & (i + 0x3ff)) / 0xff)[0];
                            ax02[8] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7]))[0];
                            ax01[8] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7]))[0];
                            if (!RoBoIO.com3_ServoTRX(ax01, 9, read, 6))
                                MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                            if (!RoBoIO.com3_ServoTRX(ax02, 9, read, 6))
                                MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                            RoBoIO.delay_ms(25);
                        }
                        break;
                    case 3:
                        for (int i = v % 0x3ff; i > 0; i = i - v / speed)
                        {
                            ax01[6] = BitConverter.GetBytes(0x00ff & (i + 0x3ff))[0];
                            ax01[7] = BitConverter.GetBytes((0xff00 & (i + 0x3ff)) / 0xff)[0];
                            ax02[6] = BitConverter.GetBytes(0x00ff & (i + 0x3ff))[0];
                            ax02[7] = BitConverter.GetBytes((0xff00 & (i + 0x3ff)) / 0xff)[0];
                            ax02[8] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7]))[0];
                            ax01[8] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7]))[0];
                            if (!RoBoIO.com3_ServoTRX(ax01, 9, read, 6))
                                MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                            if (!RoBoIO.com3_ServoTRX(ax02, 9, read, 6))
                                MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                            RoBoIO.delay_ms(25);
                        }
                        break;
                    case 4:
                        for (int i = v % 0x3ff; i > 0; i = i - v / speed)
                        {
                            ax01[6] = BitConverter.GetBytes(0x00ff & i)[0];
                            ax01[7] = BitConverter.GetBytes((0xff00 & i) / 0xff)[0];
                            ax02[6] = BitConverter.GetBytes(0x00ff & i)[0];
                            ax02[7] = BitConverter.GetBytes((0xff00 & i) / 0xff)[0];
                            ax02[8] = BitConverter.GetBytes(~(ax02[2] + ax02[3] + ax02[4] + ax02[5] + ax02[6] + ax02[7]))[0];
                            ax01[8] = BitConverter.GetBytes(~(ax01[2] + ax01[3] + ax01[4] + ax01[5] + ax01[6] + ax01[7]))[0];
                            if (!RoBoIO.com3_ServoTRX(ax01, 9, read, 6))
                                MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                            if (!RoBoIO.com3_ServoTRX(ax02, 9, read, 6))
                                MessageBox.Show("com3_ServoTRX fail read back = " + read[0] + " " + read[1] + " " + read[2] + " " + read[3] + " " + read[4] + " " + read[5]);
                            RoBoIO.delay_ms(25);
                        }
                        break;
                }
                run = 0;
            }
        }
        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                groupBox1.Enabled = false;
            }
            else {
                groupBox1.Enabled = true;
            }
        }
        private void checkBox1_KeyDown(object sender, KeyEventArgs e)
        {
            if (checkBox1.Checked)
            {
                if (e.KeyCode == Keys.W && run != 1)
                    xUp();
                else if (e.KeyCode == Keys.S && run != 2)
                    xdown();
                else if (e.KeyCode == Keys.A && run != 3)
                    xleft();
                else if (e.KeyCode == Keys.D && run != 4)
                    xright();
            }
        }
        private void checkBox1_KeyUp(object sender, KeyEventArgs e)
        {
            if(checkBox1.Checked){
                if (run != 0)
                Stop(10);
            }
        }
    }
}

Share:

2013/6/6

[RoBoard魔人] DMP秘密機器人-Zero上半身 輪胎測試

各位大家好

如果大家有在關注這台機器人的話就會知道

他現在有分上下半身

下半身之前已經給各位看過他的走路了

雖然目前還是有點弱弱的走路

但我相信 近期內我會將他改得較順暢
 DMP秘密機器人-Zero下半身
 DMP秘密機器人-Zero下半身
加上了殼  變得更安全


而今天的主角呢   就是上半身啦!
 DMP秘密機器人-Zero上半身

沒錯

加上了輪子依然霸氣十足

這輪子是使用AX-12來驅動的

而AX-12也是可以使用360度旋轉的喔!!

這樣就可以用輪子來移動了

來看看影片吧!!




至於這小程式的code    我會再做介紹的!
Share:

2013/5/13

[RoBoME] DMP秘密機器人-Zero 走路測試

大家看了那麼多RoBoME的使用教學

不知道有沒有心動呢?

本魔自己認為是蠻好用的啦

本魔之前在介紹DMP秘密機器人-Zero時

就有說過要用RoBoME來編輯這機器人的動作囉!!

所以本魔在此也拍了個影片來給大家看看

由於DMP秘密機器人-Zero的馬達沒有Feedback

所以在編輯上會有些吃力

不過有Feedback的馬達會有個缺點就是

我們抓回來的動作不一定對稱 或精準

廢話不多說 來看看影片吧!


教學系列文章:
V1.0   V1.1   V1.2   V1.3-4   V1.5-6


Source Code:
Github link
Share:

2013/4/12

[RoBoME] 使用教學V1.5~V1.6

這一次的V1.5更新絕對讓大家有全新體驗

為什麼呢?

這是因為本魔有加入了新功能囉~

在某年某月某日有一位大大  

也就是DMP秘密機器人的製作者

他說:[這個拉霸一定要排成這樣嗎?這樣找馬達的效率不是會很差?]



真不愧是DMP秘密機器人的製作者

一語點醒夢中魔阿!

所以這一次更新的內容就是~~~

可以隨意的擺放拉霸到你想要的位置~~!!

什麼?   你說這樣擺放不知道有什麼意義?

別急~  本魔還新增了圖形背景的功能

你可以選擇匯入圖檔
在設定的地方   左下方新增了一個選擇圖片的按鈕  (附註: 位置必須為跟目錄下)



然後再將拉霸移到相對應的位置
移動的方法是拖曳拉霸前面的CHx字串

那這樣就可以很快速的對照馬達囉~

當然圖檔你可以選擇拍照片   也可以選擇自己畫一張草稿

這樣就不怕會找不到馬達或轉錯馬達囉~

且下次再開啟檔案時    它會讀取上一次設定的位置及圖片喔~

不用擔心需要重新設定

也不用管你是機器人 機器貓 機器手臂   只要有圖   就可以放到你想要的位置囉~



但是   如果是在RoBoard上使用   建議圖檔盡量壓小

本魔實際測試過在刷新的時候  

約105k的圖檔(約720*1080)會讓程式有點LAG

而如果有人怕圖檔放進去後   會被框架給拉長圖片  

這裡告訴各位 框架的大小為700*550    各位可以用這個比例去裁切圖片






疑~你說什麼?    v1.6是做什麼的?

其實v1.6是修正前面一些bug

如拉霸拉了之後   馬達反應得很奇怪

以及背景功能的一些小bug



Source code

RoBoME
Share:

2013/3/29

[RoBoard魔人] 遊記 - 臺北機器人館




在今年年初的時候在電視新聞上看到報導,說花博公園以多元化、互動性機器人為主題做了一個機器人館,一直就很期待安排假期來到此朝聖一番!

終於!在今年三月底來參觀囉!


本魔來到了臺北機器人館,臺北機器人館在哪呢?就是花博公園內的未來館喔!
相信大家都記得,在2010國際花卉博覽會的時候,人山人海啊!想進入一個館去參觀都要等很久!

本魔在此附上官方的資訊(機器人館),讓大家更了解臺北機器人館!

那臺北機器人館要怎麼去呢?別怕別怕,搭乘捷運或是公車,很快就到囉!


搭乘捷運
民眾可於捷運蘆洲線中山國小站4號出口出站後沿民權東路往東,於民權吉林路口左轉吉林路往北直行,合計步行約10分鐘即可抵達花博新生公園區。
搭乘公車
*民眾可搭乘72、222、285吉林、665、527、市民小巴9、棕16、紅34及敦化幹線公車到達,原服務花博新生三館至捷運圓山站之花博1號線接駁車已於100年5月2日變更為一般路線收費營運,並更名紅50路公車(內湖─捷運圓山站)服務民眾,現行發車班距為30~60分一班,為配合花博新生三館重新開館,自8月1日起於尖峰時段加密班次為15~30分鐘一班。
*公運處籲請民眾多加利用大眾運輸,以避免交通壅塞,民眾若想知道公車詳細路線資訊可上5284網站查詢(http://5284.taipei.gov.tw/)或可利用手機上網(網址:http://mobile.5284.com.tw)、電話語音查詢專線 02-23461168查詢公車預估到站時間。
*查詢大臺北地區公車到站資訊、即時道路績效及停車格位請多利用 臺北市即時交通資訊網:http://its.taipei.gov.tw/ 手機&PDA版:http://its.taipei.gov.tw/m


==本魔貼心小分享==

花博公園為便利民眾暢遊園區,2013/6/29-2013/9/1每週六日推出免費接駁的戀夏巴士,載領民眾驚喜上路。
戀夏巴士搶眼的車體設計、親切的車掌解說及趣味的體驗活動,帶給民眾夏日旅遊新選擇,民眾搭車還可獲得驚喜福袋,憑袋內文宣可集章換禮、抽獎及購買火影忍者展優惠票!

花博公園是不是很貼心呀,大力推推唷!






營業時間呢?
週一公休 (國定假日及特殊節日除外)
週二至週四、週日 09:00~17:00 (16:15停止入館)
週五及週六 09:00~20:00(19:15停止入館)
自上午9時起,每15分鐘一場,每場34人次(含4名身障免票憑證),週二至四及日最後一場為16:15,共計30場;週五至六最後一場為19:15,共計42場。


==本魔貼心小分享==
本魔是週六下午時段去的,人潮稍多。
主要是家長帶著孩子來遊玩(機器人嘛!超受小孩子歡迎的!)
不過場內服務人員很多,人潮控管完全不必擔心唷。(給館內服務人員一個讚!(y))


所以各位不要在非營業時間去撲了個空啦~
到了園區裡面也別擔心會迷路,畢竟指標都指示的蠻清楚的!
不放心的話還是看個地圖吧!未來館在地圖的右手邊喔!

點圖即可放大

接下來就正式開始本魔這次的遊記囉!
本魔的運氣很好,因為這天天氣陰涼,也不用怕太陽太大

點圖即可放大

到了園區內還是可以看到很多花呢!平時還是可以來這裡拍拍照踏踏青!

點圖即可放大

本魔對花卉不是有很深入的了解,所以在花卉上也無法對各位做太多的解說
大家都知道我們今天的目的!沒錯!我們要看的是機器人!


點圖即可放大

因為本魔是路癡,所以在園區裡面也是繞了一大圈才找到臺北機器人館
點圖即可放大
終於到了臺北機器人館啦!實在是太感動了!
首先來和招牌合照一下吧!

點圖即可放大

看到本魔手的位置,就知道今天的重點了!
進入館內,馬上看到一台約一層樓高的鋼彈!超帥的啦!


這台是什麼鋼彈呢?本魔也不是很清楚,這可能要請教專業的大大了
看這台的架構,似乎和模型一樣呢,不知道關節是否能轉動



票價資訊
接著來到了售票窗口,票價也不貴喔!
票種
展館
票價 
(
新臺幣/)
適用對象
全票
臺北機器人館
50
一般國內外民眾。
團體票
臺北機器人館
35
10人以上之團體。
優待票
臺北機器人館
35
一、6歲以上未滿12歲兒童。 
二、在校學生。 
三、65歲以上老人。
套票
臺北機器人館全票套票
75
一般國內外民眾。
免費 
入場


一、身心障礙者及其必要陪伴者一人。 
二、未滿6歲或身高在115公分以下之兒童。

==本魔貼心小分享==

若是一般民眾來參觀,建議早點來,給自己多一點的時間
可以買兩場展館的套票,會比較划算唷!

本魔在機器人館參觀了大約快兩個小時,還有參與到定時導覽機器人表演
本魔算是看得很慢很慢(幾乎每項互動設備都有玩到)
一般民眾大約應該可以在一個小時左右瀏覽參觀完畢。




點圖即可放大

由於本魔還是學生,所以就購買了學生優待票入場啦!

點圖即可放大


到了準備入場的地方,牆壁上有張大大的參觀流程。

點圖即可放大

還不少小朋友呢!可以考慮來此全家遊喔,相信小朋友看到機器人也是會相當興奮的!

終於開始參觀,本魔也是相當興奮呢!
首先看看機器人歷史光廊
裡面有介紹一些世界知名的機器人,以及台灣較著名的機器人。

1939-2004


2005-2011


看完年代史的組圖,就來聽聽魔人對每個年代的細說吧!






1939年世界第一台鐵皮機器人
哇!這鐵皮機器人年紀可以當本魔的爺爺了!

1973年世界第一台工業六軸機械手臂
六軸的自由度相當的高,人手可以做到的動作它幾乎也都做得出來了

1983年台灣第一台工業用機械手臂
雖然晚了世界十年,但我相信台灣還是相當有潛力的

2004台灣第一台保全機器人
看到這台機器人,本魔都想坐下來打格鬥天王了哈哈,外觀相當像街機

2005台灣第一台清潔機器人
近幾年越來越紅的就是它啦!掃地機器人事也。

1997年世界第一台登陸火星機器人
這也是需要相當不容易的技術,用太陽能板供電,電腦自動控制,還要將影像傳輸回地球

1991年世界第一台達文西手術機器人
手術機器人真的是拯救了很多人,它可以很精密的去動手術,醫生也不用怕忘了把手術刀拿出來

2006年台灣第一台軍型導覽機器人
導覽機器人大概就顧名思議了,它會帶著你走以及介紹該地方特色吧

2000年世界第一台擬人步行機器人
沒錯!這就是可愛的Asimo,它現在可以做到很多人類的事囉!
例如辨識、倒茶等等。
有興趣可以看看youtube

2008年台灣第一台擬真人臉機器人
說真的我蠻驚訝的,下面六張表情竟然是機器人?

2001世界第一台最具治療能力寵物機器人
看它的樣子就知道相當治癒人心了!這隻Paro在機器人裡面也是相當有名的喔!
它可以感測很多東西,然後回饋給妳不同的反應

2004年世界第一台線驅動七軸機械手臂
相信各位都注意到它的手指了,多了手指的自由度後理所當然的可以做更多事情呢!

2008年台灣第一台桌上型人型機器人
二足機器人感覺就是要拿來格鬥的是吧?

2010年台灣第一台教育娛樂機器人
這台Robii相當有趣,本魔之前在機器人展時有玩過,它的感應方式實在令人驚艷

2005世界第一台軍用搬運四足機器人
這台BigDog不用多說了吧?大家都知道它的步行演算法相當厲害!
想回顧一下的話本魔在此開個傳送門

2011年台灣第一台自製雙足步行機器人
沒錯!它就是我們可愛的尼諾,雖然目前只有簡單的步行,但本魔相信會進步很快的
不知道的話這裡有youtube影片讓大家看看

才知道其實機器人在外國早在幾十年前就有開始研究了!而台灣是近十幾年才開始有發展
不過本魔相信機器人這一塊會發展得很快速的!像是十年前,沒有人會想到現在電腦的普及
走過了機器人歷史光廊真的讓本魔很有感觸,畢竟機器人真的是需要用到很多技術,歷史光廊真的讓本魔深深的體會到我們的科技以及技術相當踏實的在提升


走過時光走廊,馬上看到兩台鐵皮機器人,它們的眼睛眉毛會動喔!相當可愛
咦...?右邊那隻有點眼熟?
 接著回頭,看到一個傳送門,不對是電動門

感覺很像鋼彈系列裡面才會看到的艙門?

到了內部,藍色的光顯得相當有科技感

臺北機器人館的吉祥物為您指路
這樣子看起來應該是大魔神吧?

接著來到的是趣味機器人展示區,看到一連串的櫥窗,裡面擺著各式各樣的機器人
有一些機器人會動喔!但是怕錄影太花時間,所以只好由本魔一一解說了!

沒錯,它就是當年很紅的AIBO愛寶機械狗喔

這隻小機器人的眼睛會眨眼喔!還有後面的觸角也會動呢!

這也是一台機械狗,表情相當討喜

這是用積木拼成的機械獅子

一樣使用積木拼成的機械鱷魚

看到機械貓就想到哆啦A夢

沒錯,它是瓦力喔~樂高機器人封面的那隻

機械狗,看起來相當凶惡,感覺可以當成是緝毒犬:)

這個機器人相當的閃亮,馬達帶動齒輪後,會讓椅子上的兩個人一直接吻

名稱為大貓小貓,小貓真的是…有點看不太出來

看名子就知道這隻是拿來打架用的,有參加RBL的選手就知道這隻的兇殘程度了

很有年代的卡通,鐵人28號,看起來它散發著王者的霸氣

六足機器人,電路都一清二楚!

機械馬,他只用一顆馬達帶動四隻腳去做行走

很鐵皮的鐵皮機器人:)

蝙蝠俠,我記得她的手好像會揮動

看起來按鍵比較多的鐵皮機器人

蜘蛛人,本魔還很期待她會吐絲呢:)

依然是小鐵皮機器人

這隻大家應該很熟悉的,它就是花博的吉祥物之一喔!

這隻小鐵皮的腳是黏住的!?那他怎麼移動?

像太空人的鐵皮機器人?

鋼彈,它的槍會舉上舉下喔

機械恐龍,沒錯,它就是鴻海的Palo

Hello Kitty機器貓,女孩子應該會很想要吧?

機器人小新,本魔跟它不太熟,本魔只認得野原新之助哈哈

帥氣的薩克,它的斧頭會擺動喔!

出現了!沒有耳朵的機械貓,恩...不是本魔故意不拍它耳朵喔

這台機器人我有在網路上看過,相當像橄欖球員對吧?!

四足機器人,看起來很像外星機器呢!

伏地挺身一下二上!沒錯,它會做伏地挺身喔

輪型教具,看來是教控制用的教材

它會轉動,本魔個人認為是飛魚

本魔記得它好像會拍動翅膀

六足昆蟲,外型真的蠻像是蟲的!

二足機器人,它的手會擺動喔!

監視機器人,比起固定的監視器,這更具機動性呢!

輪型機器人,紅色相當討喜XD

小六足昆蟲,不要拿拖鞋阿!它是機器人

清潔機器人,這就是相當方便的掃地機器人囉!

微型機器人,他是使用小顆的馬達以及他的自由度較少,但這樣的自由度依然足夠走路囉

這台機器人有沒有很像遊戲王裡面的E-HERO地球人?

由於本魔沒看過星際大戰,所以不太清楚這是什麼東西

小人型機器人,它有八個關節
相撲機器人,它會推動前面的版子喔!看下面的痕跡應該可以理解

格鬥機器人,肩膀比較寬看起來就比較壯!

Kondo機器人,日本的人型機器人

沒錯,說到機器人怎麼能忘了原子小金剛呢?

似乎是星際大戰裡面的角色?

人型機器人,好像也有在RBL上看過類似的機器人呢!

這台機器人的臉會左右晃動,好像在做鬼臉的感覺

打倒雙面人!怪獸都殺光!大家都稱讚~無敵鐵金剛!

木蘭號!我只記得木蘭號會發射木蘭飛彈哈哈

會打鼓的鐵皮機器人

機像手掌,它在比YA呢!


大家來個來照囉哈哈:)





看了這麼多的趣味機器人,更能深深的體會到機器人需要多方面的技術
很多趣味機器人的機構設計都是用很少的馬達,去做到多關節的動作
看完了趣味機器人展示區,本魔來到了產業機器人展示區
產業展示區顧名思義,就是產業研究的成果囉!
畢竟是產業做的,那一定比前面看得更精彩了!

首先看到的是機械手臂,前面放上一隻筆,就變成機器人畫家囉!

模擬控制的工作環境

它的原理與印表機類似,有顏色的地方就下筆,沒顏色的地方就提筆
就這樣一行一行的掃下去,就完成了!

機械手臂畫出的圖畫,沒錯,是艾斯
機械手臂的控制相當困難呢!畢竟要用到演算法!



接著下一站看到的依然是機械手臂喔!套上了蛇的造型感覺相當可愛呢!
它後面有兩台攝影機去定位籃框的位置,投出!命中率高達99%呢!下方有影片供大家看得更清楚!
至於有些人可能會好奇為什麼要兩台攝影機呢?這是因為兩台攝影機才有辦法推算出影像的深度,這樣才能知道與籃框之間的距離喔!

投球機器人,籃框那有球的殘影,這球得分!



接著下一站看到的是NXT樂高機器人,它使用智慧手機的陀螺儀結合藍芽來控制機器人的移動,而機器人身上還有很多的感應器,如超音波、光、聲音等等,本魔很納悶的是,那機器人上的感應器好像沒用到?
不過玩起來也相當有趣呢!

NXT樂高機器人,場地布置得很像太空的感覺

接下來看到的是紡織機器人,不會刺繡沒關係,輸入圖檔後就會幫你編織漂亮的刺繡囉!
刺繡與繪畫不同的地方是它需要依照顏色來刺,以及需要去推算顏色的路徑該怎麼走,根據現場工作人員的說法,複雜的圖樣可能需要刺一天呢!
下方一樣有影片做更詳細的介紹

紡織機器人!?好大台

旁邊有正載運行的紡織機器

螢幕上顯示的就是他的圖樣,可以比對機器下紡織出的結果




看完了產業機器人,本魔跟著隊伍來到的是101 3D劇院,來到裡面首先看到的是小提琴機器人,在下方一樣有影片做介紹喔!




看完了小提琴的演奏,本魔戴起3D眼鏡,開始播放環繞式的3D電影,內容主要是講台北繁忙的一天,因為是3D投影,所以也無法多做介紹與攝影,只能請各位親自來體驗囉!



看完3D電影後,本魔跟著隊伍接著來到機器人浮空劇院,浮空劇院?劇院怎麼浮空?


一進去之後看到的是金字塔型的玻璃櫥窗,本魔立刻瞭解了,因為本魔對這個投影技術相當有興趣,它就是所謂的全息投影(也叫虛擬成像)
這種投影技術不需要帶3D眼鏡,因為它用干涉和衍射的原理,將影像投影在半空中,看起來就像是電影裡看到的情節一樣
而這項技術本魔自己有在家裡玩過,但第一次看到這麼大的全息投影讓本魔相當興奮
而這裡並不事只有看投影而已喔,它還結合了機器人的表演呢!
下方影片一樣有詳細介紹喔

上方看到方型的那就是浮空的影像喔!










看完了機器人浮空劇院之後,來到機器人互動區,看到了許多互動的機器人與一整排的鋼彈模型,鋼彈模型我看我挑幾台拍得比較好的給大家看看吧,想要看更多的話就請到現場去看囉!
整排的鋼彈模型

整排的鋼彈模型

看起來相當精緻對吧?

紅異端,拿著刀真的就是帥阿!

神威鋼彈,手都發光了,還不神威嘛?

樂高薩克,相當的精緻阿!





接著看到很多的互動機器人,大部分的互動機器人本魔都是用錄影的!所以請各位耐心的看下去吧!
接著介紹的是舉旗機器人,它是使用kinect去讀取人的動作,判斷人是舉那一手,然後機器人再舉起對應的旗子

舉旗機器人
接著看到踢球機器人,二足步行其實是相當困難的喔!要考慮到平衡與重心等問題,這是一個相當困難的課題呢!


在來看到猜拳機器人,這手的靈活度做的真好,猜想應該是使用拉動的方式來讓手指可以彎曲的吧!



接著就是精采的格鬥機器人了!剛剛說過兩隻腳走路的機器人已經很困難了,那在加上身體的重量以及揮拳動作,那麼機器人的晃動是一定會有的,所以要做一台穩定的機器人,而且又要能夠打贏對手,這可是相當的不簡單阿!



接著看到單槓機器人,相當可愛的小猴子,利用腳部的晃動造成身體也開始晃動,當力道足夠時就可以繞一整圈了!不知道這台上面有沒有裝感測器。





接著來到的是先進機器人展示平台,這裡也是有很多的互動類型的機器人本魔也是用錄影的方式,所以一樣是在下方會有影片喔!

首先來介紹互動型的四足機器人,貼紅紙的地方有感應器,感測到之後會做出相對應的動作,如握手

互動型四足機器人



熊貓機器人,應該是辨識機器人啦!這台機器人也是利用影像來做辨識,然後依照你的外型告訴你相對應的話,話說...它說我瘦耶XD




接著看到的...這...應該是神轎吧...?本魔看了很久,不過還是看不出跟機器人的關係...

神轎??

接著是舞龍舞獅機器人,放著音樂跳著舞龍舞獅,感覺相當熱鬧呢!

舞龍舞獅機器人

這台機器人就翹著二郎腿在那搧風,本魔有點不懂它的意義,是布袋戲嘛?恩...,看來可能是本魔太沒內涵吧?下方一樣有它的影片

布袋戲機器人?
最後看到的是nao機器人,本魔相當喜歡這台機器人,因為他設計得好看,而且身上的感應器相當之多呢!只是這台真的是不便宜阿,有興趣可以看看它官方的影片喔!



最後來和吉祥物合照一下,本魔絕對沒有模仿它的動作喔XD

與吉祥物合照

接著這是整段的影片,裡面還有些上面沒介紹到的機器人,大多是些跳舞機器人,本魔不太知道該如何介紹就是了,快來看看影片吧!





那這一次參觀的感覺呢?


不多說!給一個讚就對了!


Share:
技術提供:Blogger.

追蹤者