Quantcast
Channel: demura.net
Viewing all 757 articles
Browse latest View live

Juliusディクテーション実行キットのインストール

$
0
0

julius

Juliusディクテーション実行キットのインストールメモ

このページの説明を読んでUbuntu14.04にインスト−ルした。以下、手順をまとめる。なお、ディクテーションキットの出力はEUC-JPなので、Ubuntuのgnome-terminalで実行すると文字化けするのでktermをインストールする。実行した結果、認識精度が結構高い。さすが、DNN版。

  • インストール
    • $ sudo apt-get install kterm
    • $ cd  src
    • $ git  clone  https://github.com/julius-speech/dictation-kit.git
    • $ cd ~/src/dictation-kit
    • $ chmod +x run-linux-dnn.sh
    • $ cd bin/linux
    • $ chmod +x *
    • $ ~/src/dictation-kit/bin/common
    • $ chmod +x dnnclient.py
  • 実行
    • $ kterm
    • 上のコマンドで新しいktermとよばれる端末が開くので、以下のコマンドはそこに打ち込む。
    • $ cd ~/src/dictation-kit
    • $  ./run-linux-dnn.sh

終わり


ロボットプログラミングⅡ:第13週 ロボットアーム

$
0
0

arm2-gazebo

arm2-rviz

今週はgazeboを使い2自由度のロボットアームを作り、関節を動かします。2自由度ロボットアームのURDFは参考リンクを参照してください。このサンプルでは参考リンクのrrbot.xacroをベースに作っています。

ソース
Turtlebtをテレオペしたソースコードをベースに ~/catkin_ws/src/armbot2/src/teleop.cppを作成しました。ジョイント1とジョイント2の目標角度をパブリッシュし、/armbot2/joint_statesトピックをサブスクライブしジョイントの現在値を取得しています。この例では、目標角度に追従するのに時間がかかるのでループ毎に1秒スリープしてから現在値を取得しています。

 
// ~/catkin_ws/src/armbot2/src/teleop.cpp
#include "ros/ros.h"  // rosで必要はヘッダーファイル
#include "std_msgs/Float64.h"
#include "sensor_msgs/JointState.h"
#include "nav_msgs/Odometry.h"

using namespace std;
std_msgs::Float64 tmp_joint1, tmp_joint2;
double pos_x, pos_y, pos_z;

void monitorJointState(const sensor_msgs::JointState::ConstPtr& jointstate)
{
  tmp_joint1.data = jointstate->position[0];
  tmp_joint2.data = jointstate->position[1]; 
}

int main(int argc, char **argv)
{
  ros::init(argc, argv, "teleop");  // ノードの初期化
  ros::NodeHandle nh; // ノードハンドラ  
  ros::Publisher  pub_joint1, pub_joint2;  // パブリッシャの作成
  ros::Subscriber sub_joints, sub_sensor;  // サブスクライバの作成

  std_msgs::Float64 target_joint1, target_joint2;

  pub_joint1 = nh.advertise<std_msgs::Float64>("/armbot2/joint1_position_controller/command", 100);
  pub_joint2 = nh.advertise<std_msgs::Float64>
("/armbot2/joint2_position_controller/command", 100);
  sub_joints = nh.subscribe("/armbot2/joint_states", 100, monitorJointState);

  target_joint1.data = 0;
  target_joint2.data = 0;

  while (ros::ok()) { // このノードが使える間は無限ループ
    char key;  // 入力キーの値

    ROS_INFO("[Input] j: Joint1++, f: Joint1--, k: Joint2++, d:Joint2--");
    cin >> key; 
    cout << key << endl;

    switch (key) {
    case 'j': target_joint1.data  +=  5 * M_PI/180.0; break;
    case 'f': target_joint1.data  -=  5 * M_PI/180.0; break;
    case 'k': target_joint2.data  +=  5 * M_PI/180.0; break;
    case 'd': target_joint2.data  -=  5 * M_PI/180.0; break;
    default: ROS_INFO("Input j,f,k,d");
    }
      
    pub_joint1.publish(target_joint1); // 角度を送信    
    pub_joint2.publish(target_joint2);
    ROS_INFO("Targe: Joint1=%f Joint2=%f", target_joint1.data, target_joint2.data);

    usleep(1000*1000); // 制御に時間がかかるので1秒寝て待つ
    ros::spinOnce();   // コールバック関数を呼ぶ
    ROS_INFO("Tmp:Joint1=%f Joint2=%f", tmp_joint1.data,    tmp_joint2.data);
  }
  
  return 0;
}

なお、ジョイントのPIDゲインやコントローラーは以下のファイルに記述されています。詳細については参考リンクをご覧ください。
~/catkin_ws/src/armbot2/config/armbot2_control.yaml
準 備

  • $ sudo apt-get update
  • $ sudo apt-get install ros-indigo-gazebo-ros-pkgs ros-indigo-gazebo-ros-control
  • $ sudo apt-get install ros-indigo-gazebo-plugins  ros-indigo-gazebo-ros
  • $ sudo apt-get install ros-indigo-moveit-*
  • $ sudo apt-get install ros-indigo-ros-control ros-indigo-ros-controllers  ros-indigo-joint-state-controller ros-indigo-effort-controllers ros-indigo-position-controllers ros-indigo-joint-trajectory-controller
  • $ sudo apt-get install liburdfdom-tools

プログラムとビルド

  • 以下をホームディレクトリ(/home/ユーザ名)にダウンロードする。
  • $ cd
  • $ cp  armbot2-150108.tgz  ~/catkin_ws/src
  • $ cd  ~/catkin_ws/src
  • $ tar  xvzf  armbot2-150108.tgz
  • $ cd  ~/catkin_ws
  • $ catkin_make

実 行
端末を2つ開き、次のコマンドを実行する。

  • $ roslaunch  armbot2  armbot2.launch
  • $ rosrun armbot2 armbot2
    • armbot2を実行している端末をクリックし、j, k, f, dコマンドを入力する毎にEnterキーを入力するとロボットアームが動く。各コマンドを入力する度にEnterキーを押さなければ動きません。jは第1関節を正方向、fは負方向、 kは第2関節を正方向、dは負方向に目標角度を5度ずつ変化させる。
  • 成功するとrvizとgazeboの2つのウインドウが開く。そのままではrvizにロボットモデルが表示されないので、次の設定を行う。

rvizの設定

rviz-gazebo

  • 次の操作を行う
    1. (1) Global Option -> Fixed Frameをbase_linkに設定
    2. (2) Addボタンをクリックする
    3. (3) RobotModelを追加する

ノードグラフ

ノードグラフは次のとおり。端末を開き、次のコマンドを実行。

  • $ rqt_graph

rqt_graph

参考リンク

 

ロボットプログラミングⅡ:第15週 ロボットアームと位置センサ

$
0
0

arm_sensor
今週は先週作った2自由度のロボットアームの先端に位置センサを取り付け、先端位置を取得するプログラムを作ります。

位置センサ用プラグインの追加
gazeboのロボットモデルに位置センサを取り付けるために、~/catkin_ws/src/armbot2_sensor/urdf/armbot2_sensor.gazeboに以下のプラグインを追加します。

 
 <gazebo>
    <plugin name="p3d_base_controller" filename="libgazebo_ros_p3d.so">
      <alwaysOn>true</alwaysOn>
      <updateRate>100.0</updateRate>
      <bodyName>link_sensor</bodyName>
      <topicName>/armbot2_sensor/pose_ground_truth</topicName>
      <gaussianNoise>0</gaussianNoise>
      <frameName>base_link</frameName>
      <xyzOffsets>0 0 0</xyzOffsets> 
      <rpyOffsets>0 0 0</rpyOffsets>
    </plugin>
  </gazebo>

ソース
前週のソースコードにgroundTruthCallback関数を追加し、トピック/armbot2_sensor/pose_ground_truthTurtlebtをサブスクライブするだけ。

 
#include "ros/ros.h"  // rosで必要はヘッダーファイル
#include "std_msgs/Float64.h"
#include "sensor_msgs/JointState.h"
#include "nav_msgs/Odometry.h"

using namespace std;

std_msgs::Float64 tmp_joint1, tmp_joint2;
double pos_x, pos_y, pos_z;


void groundTruthCallback(const nav_msgs::Odometry::ConstPtr& msg)
{ 
  //msg->pose.pose.position, msg->pose.pose.orientation, 
  pos_x = msg->pose.pose.position.x;
  pos_y = msg->pose.pose.position.y;
  pos_z = msg->pose.pose.position.z;
  ROS_INFO("Pose: x=%f y=%f \n",pos_x,pos_y);
}

void monitorJointState(const sensor_msgs::JointState::ConstPtr& jointstate)
{
  tmp_joint1.data = jointstate->position[0];
  tmp_joint2.data = jointstate->position[1]; 
}


int main(int argc, char **argv)
{
  ros::init(argc, argv, "teleop_sensor"); 
  // initでROSを初期化して、my_teleopという名前をノードにつける                        
  // 同じ名前のノードが複数あってはいけないので、ユニークな名前をつける

  ros::NodeHandle nh;
  // ノードハンドラの作成。ハンドラは必要になったら起動される。
  ros::Publisher  pub_joint1, pub_joint2;
  // パブリッシャの作成。トピックに対してデータを送信。

  ros::Subscriber sub_joints, sub_sensor;
  // サブスクライバの作成

  ros::Rate rate(10);
  // ループの頻度を設定。この場合は10Hz、1秒間に10回数、1ループ100ms。

  std_msgs::Float64 target_joint1, target_joint2;

  pub_joint1 = nh.advertise<std_msgs::Float64>("/armbot2_sensor/joint1_position_controller/command", 100);
  pub_joint2 = nh.advertise<std_msgs::Float64>("/armbot2_sensor/joint2_position_controller/command", 100);
  sub_sensor = nh.subscribe<nav_msgs::Odometry>("/armbot2_sensor/pose_ground_truth", 100, groundTruthCallback);
  sub_joints = nh.subscribe("/armbot2_sensor/joint_states", 100, monitorJointState);

  target_joint1.data = 0;
  target_joint2.data = 0;

  int loop = 0;
  while (ros::ok()) { // このノードが使える間は無限ループ
    char key;  // 入力キーの値

    ROS_INFO("[Input] j: Joint1++, f: Joint1--, k: Joint2++, d:Joint2--");
    cin >> key; 
    cout << key << endl;

    switch (key) {
    case 'j': target_joint1.data  +=  5 * M_PI/180.0; break;
    case 'f': target_joint1.data  -=  5 * M_PI/180.0; break;
    case 'k': target_joint2.data  +=  5 * M_PI/180.0; break;
    case 'd': target_joint2.data  -=  5 * M_PI/180.0; break;
    default: ROS_INFO("Input j,f,k,d");
    }
      
    pub_joint1.publish(target_joint1); // 角度を送信    
    pub_joint2.publish(target_joint2);
    ROS_INFO("Targe: Joint1=%f Joint2=%f", target_joint1.data, target_joint2.data);

    usleep(1000*1000);
    ros::spinOnce(); // コールバック関数を呼ぶ
    ROS_INFO("Tmp:   Joint1=%f Joint2=%f", tmp_joint1.data,    tmp_joint2.data);
    //rate.sleep();     // 指定した周期でループするよう寝て待つ
  }
 
  return 0;
}

準 備(ロボットプログラミングⅡ:第13週 ロボットアームで実施した場合は必要なし)

  • $ sudo apt-get update
  • $ sudo apt-get install ros-indigo-gazebo-ros-pkgs ros-indigo-gazebo-ros-control
  • $ sudo apt-get install ros-indigo-gazebo-plugins  ros-indigo-gazebo-ros
  • $ sudo apt-get install ros-indigo-moveit-*
  • $ sudo apt-get install ros-indigo-ros-control ros-indigo-ros-controllers  ros-indigo-joint-state-controller ros-indigo-effort-controllers ros-indigo-position-controllers ros-indigo-joint-trajectory-controller
  • $ sudo apt-get install liburdfdom-tools

プログラムとビルド

  • $ cd
  • $ cp  armbot2_sensor-160122.tgz  ~/catkin_ws/src
  • $ cd  ~/catkin_ws/src
  • $ tar  xvzf  armbot2_sensor-160122.tgz
  • $ cd  ~/catkin_ws
  • $ catkin_make

実 行
端末を2つ開き、次のコマンドを実行する。

  • $ roslaunch  armbot2_sensor  armbot2_sensor.launch
  • $ rosrun armbot2_sensor armbot2_sensor
    • armbot2を実行している端末をクリックし、j, k, f, dコマンドを入力する毎にEnterキーを入力するとロボットアームが動く。各コマンドを入力する度にEnterキーを押さなければ動きません。jは第1関節を正方向、fは負方向、 kは第2関節を正方向、dは負方向に目標角度を5度ずつ変化させる。

演 習
(1) 運動学
運動学の計算結果と位置センサの出力を比較し、プログラムが正しいか確認する。
(2) 逆運動学
逆運動学を実装する。2自由度の場合は解が2つあるので、数字キー1を押すと解1、数字キー2を押すと解2を選択するにしなさい。

参考リンク

 

ROS-Gazeboを使ったHappy Miniシミュレータリリース

Mecab (形態素解析エンジン)のインストールメモ

$
0
0

@Homeのタスクで形態素解析する必要がでてきたので、MECABをUbunt14.04にパッケージでインストールしたときのメモ。ユーザ辞書の作成で少しはまった。

以下のサイトを参照した。

  • https://gist.github.com/YoshihitoAso/9048005
  • https://gist.github.com/Haroperi/48dbd30b557c585ad287

インストール

  • $ sudo apt-get install mecab libmecab-dev mecab-ipadic
  • $ sudo aptitude install mecab-ipadic-utf8
  • $ sudo apt-get install python-mecab

ユーザ辞書の作成

  • ユーザ辞書の元になるcsvファイルを作成する。ここではファイル名をuser.dicとする。
    • グリーンティ,,,1,名詞,一般,*,*,*,*,グリーンティ,グリーンティ,グリーンティ
  • csvファイルのあるディレクトリへ移動
    • 例: cd  ~/catkin_ws/src/restaurant_voice
  • 辞書を作成する
    • $ `mecab-config –libexecdir`/mecab-dict-index -d /usr/share/mecab/dic/ipadic -u user.dic -f utf-8 -t utf-8 user.csv
  • mecabの設定ファイルを編集する
    • ユーザ辞書登録
      /etc/mecabrcの9行目を以下のように設定
      userdic = /home/user_name/catkin_ws/src/restaurant_voice/user.dic

終わり

ロボカップジャパンオープン2016優勝!

$
0
0

victory2
2016年3月25日から27日の間、愛知工業大学で開催されたロボカップジャパンオープン2016のRoboCup@Home Educationリーグで金沢工業大学夢考房RoboCup@HomeプロジェクトとDKTの合同チームWinKIT@DKTが優勝しました。 夢考房プロジェクトがロボカップの大会で初優勝したのは2003年で、実に13年ぶりの快挙となりました。なお、RoboCup@Homeリーグは生活支援ロボットの技術開発を促進する目的があります。今大会では参加者約400名のうち、約170名が@Homeリーグ参加者であり、現在、最も人気の高いリーグです。その激戦を勝ち抜いての優勝です。

WinKIT@DKTのメンバーは次のとおりです。なお、出村賢聖君は夢考房JuniorのSROP(student research opportunity program)研究員です。
指導教員 金沢工業大学 ロボティクス学科 出村公成
メンバー  金沢工業大学 ロボティクス学科 3年 永島 一樹
メンバー      同          2年 榎本 光洋
メンバー 明聖高校3年(KIT夢考房Jr.所属) 出村 賢聖

@Home Education リーグの結果は次のとおりです。
1位 WinKIT@DKT 85.00点 (RoboCup2015世界大会9位) 
2位 Kame Rider(東京大学・他海外大合同) 80.61点 (RoboCup2015世界大会7位)
3位 TanichuCluster (立命館大学) 66.78点

なお、2位のKame Riderチームは東京大学生産技術研究所、中国南海大学、マレーシア工科大学
の三ヶ国連合チームで、昨年の世界大会で7位でした。WinKIT@DKTチームは今年の世界大会の出場権を獲得しています。昨年は初出場で世界9位でしたので、今年の世界大会では更なる活躍が期待されます。

RoboCup@Home: ナビゲーションテスト

$
0
0

nav3nav1 nav2RoboCup@Homeのルール説明をします。@Homeは家庭での暮らしに役に立つロボットの研究開発を促進するためのプロジェクトで、その技術レベルを評価する競技会が開催されています。ジャパンオープン@Home Educationでは、以下の4種目が開催されました。

  1. ナビゲーションテスト
  2. 音声認識テスト
  3. レストラン
  4. ファイナル(自由デモ・プレゼンテーション)

ここでは、ナビゲーションテストを紹介します。ナビゲーションテストはその名のとおり、事前に決められた幾つかの経由点を順番に通り、途中で通路がふさがれて経路を再計画したり、経由点を人が取り囲んでいる状態で、人を認識し、どいてもらうよう発話したり、経由点に人が立っていて、その人を追跡して指定されていない経由点へ行き到着したら、音声指示により元の経由点の戻り、最後は出口から会場を退出する一連の動作を競います。評価方法は、進んだ経由点の数や決められたタスクをこなした数による点数制です。

WinKIT@DKTチームのロボットMiniは、ROSで動いており、ナビゲーションにはmove_base、人の追跡には、下に取り付けてあるHokuyoの2次元レーザスキャナで人の足を検出するプログラムを実装しています。

なお、ジャパンオープン2016では、後半の人の後をついていくタスク時に、歩行者についていけずに失敗になりました。Kobukiの最高速度は0.7 [m/s]なので、ルールにどおりに自然に歩かれると追跡が困難です。昨年まではゆっくり歩いていましたが、今年はルールどおり厳格になりました。今まで考えていなかったのですが、見失ったときに歩行者を探すような探索プログラムの追加が必要なことがわかりました。世界大会までに実装します。

RoboCup@Home: 音声認識&オーディオ検出テスト

$
0
0

speech_recog

ロボカップジャパンオープン2016の@Home Educationで実施された、音声認識&オーディオ検出テスト(Speech recognition & Audio detection)のルール概要を説明します。

このテストは、ロボットの音声認識能力を測ることを目的としています。事前に、50問の質問とその答が与えられています。まず、ランダムに5問選び、ロボットの正面方向から0.75~1[m]の距離で人間が質問を話して、ロボットがそれに音声で回答します。次に、質問する人間が同じ距離で方位を変えて5問質問し、ロボットが答えます。ロボットは1回だけ聞き直すことができます。点数は正当数に応じて加点されます。

なお、質問は以下のようなものがあり、ジャパンオープンで使われた質問リストはこれです。

  • アメリカ合衆国の初代の大統領は誰ですか?
  • タイタニック号が建造された都市はどこですか?
  • マリリンモンローが生まれつき持っていた奇形は何ですか?

また、ルールは毎年変わり、2年に一度大きく変わります。このテストがいつまであるかわかりません。2016年のルールは複数人の話者がロボットを取り囲み、誰か一人が話すものになり難易度がより高くなっています。


C/C++統合開発環境Code::Blocks16.01のインストール (Windows)

$
0
0

codeblocks

CodeBlocks(コードブロックス)というフリーでオープンソースなC/C++統合開発環境のインストール法を説明します.日本では,Codeblocksはあまり馴染みがないかもしれませんが,オープンソースであり、Windows, Mac, Linuxで使える優れものです。Visual Studioと比較して機能がシンプルで、ハードディスクの容量を食わないことが魅力です。

では,これからCodeBlocks16.01のインストール方法をご説明します。

注:CodeBlocks13.12をインストール済みの方はアンインストールするかc:\Program Files(x86)\share\CodeBlocksのファイル名をc:\Program Files(x86)\share\CodeBlocks13.12などに変更してから以下の作業をしてください。

  • 1. ダウンロード・インストール
    • Code::Blocksのウェブサイトからダウンロードする.
    • 左にあるMainのDownloadsをクリック
    • Download the binary releaseをクリックし、すると以下の画面になるので,Windows 2000/XP/Vista/7/8.x/10ををクリックする
    • codeblocks-16.01mingw-setup.exeを選択する. これにはmingwからのgccやgdbが含まれています.必ずこちらをダウンロードしてください.重要!
    • デスクトップに保存し,codeblocks-16.01mingw-setup.exeをダブルクリックし実行する.
    • 「次の不明な発行元からのプログラムにこのコンピュータの変更を求めています。許可しますか」と聞かれるので、「はい」をクリック
    • CodeBlocks Installationの窓になり,「Next>」をクリック
    • License Agreementの窓になり,読んでから「I Agree」をクリックする.同意しないとインストールできません.
    • Choose Componentsの窓になり,全部チェック(レ印)を入っていることを確認する。チェックが入っていない場合は、空白のクリックしてチェックを入れる。チェックが入ると。四角にレ点が付く。「Next >」をクリック。
    • Choose Install Locationの窓になる.Destination Folderを変更せずに,「Install」をクリック
    • 「Do you want to run Code::Blocks now?」と表示さるので、「いいえ(N)」をクリックする。
    • Completedと表示されるので、「Next>」をクリックする。
    • Completing the CodeBlocks Setu Wizardの窓になるので、「Finish」をクリックしてインストールを終了する。
  • 2. 日本語化
    • Code::Blocks非公式な日本語化のウェブサイトに再度行き、「.moファイル」のファイル:codeblocks.moをクリックしてデスクトップへcoldeblocks20140303.zipをダウンロードする。解凍するとCodeBlocksというフォルダができるので、次のフォルダの中へコピーする。
      c:\Program Files (x86)

      成功すると次のファイルができる。

      c:\Program Files(x86)\share\CodeBlocks\locale\ja_JP\codeblocks.mo
      
      
    • 電脳スピーチblogからをwxstd.zipをダウンロードして解凍すると。wxstd.moができるので、それを以下のフォルダにコピーする。
      c:\Program Files(x86)\share\CodeBlocks\locale\ja_JP\LC_MESSAGES
    • Code::Blocksを起動する.日本語化の設定をしていないので,次のように英語表示される.
      codeblocks2
    • メニューバー(ウインドウのタイトルのすぐ下)の右から2番目にあるSettings -> Environment…を選択
    • 「目玉」のアイコンのViewをクリック. Internationalizationにチェックを入れ,Japaneseを選択し,「OK」をクリック.日本語化するためには再起動が必要なので,目ミューバーFile→Quitを選択.
      cb1312-3
    • Layout Changedの画面が出て,”The layout ‘Code::Blocks default’ has changed. Do you want to save it?”と設定を保存するか聞いてくるので聞かれるので「Yes」をクッリクする.
    • CodeBlocksを起動する.トップ画像のように日本語になっていればOK.おつかれさま.

以上です.

でむ

Harkインストールメモ

$
0
0

これはHarkインストールのメモです。

環 境

  • Ubuntu14.04.4 (64bit)

インストール

  • http://www.hark.jp/wiki.cgi?page=HARK+Installation+Instructions
    に従ってバイナリをインストールした。
  • Harkリポジトリの設定。この部分だけ少し変更。公式サイトではechoにオプションをつけていないが、私の環境では/bin/shがbashにシンボリックリンクされていたので、これだと\nで改行してくれないので、echo -eに変更。通常、Ubuntu14.04の/bin/shは/bin/dashにシンボリックがはられているので公式サイトのとおりで問題ない。
    • sudo sh -c 'echo -e "deb http://winnie.kuis.kyoto-u.ac.jp/HARK/harkrepos trusty non-free\ndeb-src http://winnie.kuis.kyoto-u.ac.jp/HARK/harkrepos trusty non-free" > /etc/apt/sources.list.d/hark.list'
  • GPGキーの設定
    • wget -q -O - http://winnie.kuis.kyoto-u.ac.jp/HARK/harkrepos/public.gpg | sudo apt-key add -
  • Harkサーバーのインデックス再構築
    • sudo apt-get update
  • Harkインストール
    • sudo apt-get install harkfd hark-designer
    • sudo apt-get install julius-4.2.3-hark-plugin
    • sudo apt-get install harktool4
    • sudo apt-get install harktool5
    • sudo apt-get install librasp-netapi
  • Hark-ROSのインストール
    • sudo apt-get install hark-ros-indigo hark-ros-stacks-indigo
  • Hark-Pythonのインストール
    • sudo apt-get install hark-python

以 上

物理エンジンODEで学ぶC言語2016[Step1:物体の描画]

$
0
0
step1の実行画面

step1の実行画面

 

物理エンジンODEを使い,ゲームを作りながらC言語をマスターすることを目指して連載します。ODEのバージョンは0.13に対応しています。なお、KITロボティクス学科の講義「コンピュータ工学Ⅰ」と連動しており、今年度から学習の進んだ学生のみプチプロジェクトを取り組むことになりました。我こそはと思う学生は是非、チャレンジしてください。

今回は何もなかった仮想空間に物体を表示させてみましょう.ODEではいろいろな形状がサポートされています.ここではその中でも使い方が最も簡単な球を表示させます.

/* step1 球の表示 */
#include "dm1.h"

dMatrix3 R;                    // ODEの3x3行列の型 回転行列(姿勢)
double r = 0.2;                // 半径 [m]
double p[3] = {0.0, 0.0, 1.0}; // 位置(x,y,z)[m]
double p2[3] = {0.0, 1.0, 1.0}; // 位置(x,y,z)[m]
double sides[3] ={0.1, 0.2, 0.3}; // サイズ(x,y,z)[m]

void simLoop(int pause)        /***  シミュレーションループ ***/
{
  dsSetColor(1.0, 0.0, 0.0);    // 赤色の設定(赤成分,緑成分,青成分)
  dsDrawSphere(p,R,r);         // 球の描画

  dsSetColor(0.0, 0.0, 1.0);
  dsDrawBox(p2, R, sides);    // 直方体の描画
}

int main()         /*** main関数 ***/
{
  dmLoop(800, 600, simLoop); // シミュレーションループ ウインドウの幅,高
  return 0;
}

まず,2行目のdm1.hはODEをより簡単に使うためのヘッダーファイルです.Step1ではまだ説明しません.

一般的に物体を3次元空間上に表示させるためには,物体の位置と姿勢を決める必要があります.ODEでは姿勢を回転行列とよばれる行列で表しています.その行列の要素を格納するのが配列R[12]です.回転行列は3×3の行列なので,1次元配列では要素数が9個で十分ですが,ODEでは高速化のために要素数12個の配列を用意します.配列の4, 8, 12番目の様子は0になっています.なお,R[12]には謎のヘッダファイルdm1.hの中で単位行列が設定されています.

また,位置は要素数3個のdouble型の配列p[3]に格納しています.位置のx座標(手前方向)を表す変数pの1番目の要素p[0]には0.0[m],y座標(右方向), z座標(高さ方向)を表すp[1], p[2]には0.0[m], 1.0[m]が設定されています.座標系は右手系です。上の図では中心から赤いピラミッドの方向がx軸の正,青いピラミッドの方向がy軸の正,上空方向がz軸の正です.ODEでは単位系はSI単位系で,長さはm,質量はkg,力はNとなります.

ソースコードのなかほどにあるsimLoop関数にシミュレーションでやりたいことを書きます.
12行目のdsSetColor()は色を設定する関数です.引数は光の3原色の値を3個取り,1番目は赤,2番目は緑,3番目は青成分で0以上1以下の値となります.ちなみに,全部0だと黒,全部1.0だと白です.
13行目は,球を表示したいのでdsDrawSphere関数を使って,位置p,姿勢R, 半径rの球を描画しています.なお、このソースコードだけではわかりませんが、simLoop関数はdmLoop関数の中で毎回呼び出されています。
同様にして15行目で青色を設定し、16行目で直方体を描画しています。

今回はこれで終わりです.簡単でしたね.なお,この説明でわからない場合は,わからない部分をコメントに書いて頂けると補足説明します.

  • 演習
    1. step1-160525.zipをダウンロードし,実行してください.
    2. 手順
      • ode-0.13がインストールされていなかったらこの説明に従いインストールする
      • ダウンロードしたファイルをc:\ode-0.13\myprogの中に保存する.デスクトップではなく、このフォルダに保存しないと失敗するので注意.
      • そこで解凍する.c:\ode-0.13\myprog\step1というフォルダが作られます.
      • c:\ode-0.13\myprog\step1\step1.cbpをダブルクリックしてcodeblocksを起動しビルド・実行する.ダブルクリックするファイルの拡張子はcbpです.間違ってcppをダブルクリックしないように!
    3. 球の位置と大きさを変更してみましょう.
      • プロトタイプ宣言
        • void dsDrawSphere(const double p[3], const double R[12],  double r)
      • 引数p[3]は位置,R[12]は姿勢,rは半径.
      • ヒント
        • プロトタイプ宣言では仮引数は宣言していますが,呼び出す(使う)ときは宣言してはいけません.ソースコードsimLoop内のdsDrawSphereの使い方を参考にしてください.また,姿勢を表す回転行列Rは見えないところで単位行列に初期化しています.現時点では配列の各要素に値を代入する必要はないので配列名Rを引数として使ってください.
    4. 直方体の位置と大きさを変更してみよう.
      • プロトタイプ宣言
        • void dsDrawBox(const double p[3], const double R[12], const double sides[3])
      • 上は関数のプロトタイプ宣言の形式なので,呼び出すときはconst doubleなどの型名を入れてはいけません.引数が配列の場合は,サンプルプログラムのように配列名だけを入れてください.
        例 dsDrawBox(p, R, sides);  // 呼び出す場合は配列名だけ
      • 1, 2番目の引数はdsDrawSphereのときと同じです.3番目の引数は直方体のx,y,z方向のサイズ[m]が入っている要素数3個の配列です.位置を表す配列pと同じように初期化すれば大丈夫です.
      • なお, doubleの前にあるconstは値を変えてはいけないという意味です。円柱を表示させてください
    5. 円柱を表示させましょう.
      • プロトタイプ宣言
        • void dsDrawCylinder(const double p[3], const double R[12],  double l, double r );
      • ここで,lは長さ,rは半径です.
    6. カプセルを表示させてください.
      • プロトタイプ宣言
        • void dsDrawCapsule(const double  p[3], const double R[12], double l,  float r );
    7. 3で制作した球の色を黄色に替えよう
      • プロトタイプ宣言
        • void dsSetColor(float r, float g, float b)
          r, g, bは光の3原色の赤、緑、青成分。値は0以上1以下のfloat型。例えば、緑にしたかったらrとbは0.0、gには1.0を代入する。

以上

Kaldiインストールメモ

$
0
0

音声認識エンジンKaldi関連プログラムのインストールメモ

0.準備
$ sudo apt-get install build-essential gfortran libgfortran3 libblas-dev libatlas-base-dev cython zlib1g-dev
automake libtool autoconf

$ sudo wget http://distfiles.macports.org/openfst/openfst-1.3.4.tar.gz

1. Kaldiのインストール
端末を開き、以下のコマンドを実行する。
$ cd ~/src
$ git clone https://github.com/kaldi-asr/kaldi.git

2. 関連ライブラリのインストール
$ cd ~/src/kaldi/src/tools
$ ./extras/check_dependencies.sh
$ sudo wget http://distfiles.macports.org/openfst/openfst-1.3.4.tar.gz
$ tar xvzf openfst-1.3.4.tar.gz
$ cd openfst-1.3.4/src/include/fst
$ patch -p0 -N < ../../../../openfst-1.3.4.patch
$ cd ~/src/kaldi/src/tools
$ ln -s openfst-1.3.4  openfst
$ cd openfst
$ ./configure –enable-static=no
$ make
$ sudo make install
$ cd ~/src/kaldi/tools/extras/openfst-1.3.4/src/lib
$ cp -a /usr/local/lib/libfst.*   .
$ cp -a /usr/local/lib/libfstscript.*  .

3. Kaldiのビルド

$ ~/src/kaldi/src
$ ./configure --shared
atlasやopenfstのヘッダーファイルやライブラリがないと怒られたら、configureファイルを開いて該当箇所を探し、オプションで次のように指定する。
$ ./configure –shared –fst-root=../tools/extras/openfst-1.3.4/src  –atlas-root=../tools/extras/ATLAS

上のコマンドでkaldi.mkファイルが生成されるので、その中のCXXFLAGSの$(EXTRA_CXXFLAGS)の後に-O3 -DNDEBUG -ldlを挿入し保存する。該当部分は下図のようになる。
cxx

引き続き、同じディレクトリで以下のコマンドを実行する。
$ make depend -j 4
$ make -j 4
$ make ext -j 4

私の環境core i7-4500U、memory 8GBでコンパイルに1時間ぐらい要した。

2. kaldi-gstreamer-serverのインストール

$ sudo pip install tornado
$ sudo pip install --upgrade tornado
$ sudo pip install ws4py==0.3.2
$ cd ~/src
$ git clone https://github.com/alumae/kaldi-gstreamer-server.git
$ cd ~/src/kaldi-gstreamer-server/test/models
$ ./download-tedlium-nnet2.sh

3. kaldinnet2onlinedecoderのインストール

$ cd ~/src
$ git clone https://github.com/alumae/gst-kaldi-nnet2-online.git
$ sudo apt-get install gstreamer1.0-plugins-bad gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-pulseaudio gstreamer1.0-plugins-ugly gstreamer1.0-tools libgstreamer1.0-dev
$ sudo apt-get install libjansson-dev
$ cd ~/src/gst-kaldi-nnet2-online/src
Makefileの中をKALDI_ROOT=/home/demulab/src/kaldi
と書き換える.
$ make depend
$ make
$ cp -a libgstkaldionline2.so ~/src/kaldi/src/gst-plugin/.
$ cd
.bashrcの最後に以下を追加する。
export GST_PLUGIN_PATH=~/src/gst-kaldi-nnet2-online/src

物理エンジンODEで学ぶC言語 [Step2:switch文]キーボード操作

$
0
0
step3サンプルプログラムの実行画面

step3サンプルプログラムの実行画面

今回は、switch文を使ったキー処理の方法を学びます.キーボード入力の処理にswitch文はうってつけです。 ゲームではキーボード入力によりレーザービームを発射したり,車を操縦しますね.switch文を使って,キーボードからのキー入力を処理する方法を学びます.

  • switch文とキー処理

新しく登場したのが11行目のcommand関数です.これは,キーボードからのキー入力を引数cmdとして受け取ります.このサンプルプログラムではswitch文を使いキー入力の値に応じて分岐させ違う処理をさせています.zが入力されると初期位置のz成分を0.1m増加させます.つまり,zキーを押すたびに直方体全体が上空へ上がっていきます.その下のbreak文は忘れないでください.忘れるとdefaultに対応する21行目の文を実行し常にInput z keyと表示されてしまいます.

その他のキーを入力するとdefaultにある”Input z key”という文字列がコンソール画面に表示されます. なお、switch文の変わりにif文でもできますが、キー入力が増え分岐が多くなるとswitch文の方がすっきりした読みやすいプログラムを書けます。

  • 乱 数

ODEとは関係ありませんがゲームやシミュレータでは乱数も活躍します.乱数を使う場合は”stdlib.h”をインクルードします.ここではtime()関数も使っているので”time.h”もインクルードしています.

乱数を使用する場合は、まず,main関数の42行目にあるように乱数を初期化します.そのためにvoid srand(unsigned seed)関数を使います。引数seedは乱数を発生させる種を入れます.それが同じ値の場合は,常に同じ乱数系列が発生します.srand(time(NULL))は実行時に乱数の種を変更する一般的な方法です. ちなみに、time(NULL)は万国標準時1970年1月1日からの経過秒数です。大きな数値になるのでパット見意味がわからりづらいですね.

実際に乱数を発生させているのがsimLoop関数の30行目のrand関数です.rand関数のプロトタイプ宣言はint rand(void)なので引数は取らず,int型の値を返します.RAND_MAXは乱数の最大値なので,30行目は0以上1以下の乱数を発生させ,それを赤成分の値に代入します.なお,rand()とRAND_MAXの割り算をするとint型になり小数点以下が切り捨てられるのでfloat型にキャスト(型変換)することを忘れないようにしましょう.これによって,表示されている直方体(以下ボックスと表記)の赤成分の色だけが変わることになります.

今回は2つのことを学びました.特に乱数はゲームで使うと非常に面白いゲームになるのでしっかり覚えておきましょう.

でむ

/* step2 キー入力 switch文 */
#include "dm2.h"
#include <time.h>
#include <stdlib.h>

// Rは回転行列の各要素が格納される配列. 4, 8, 12番目の要素は高速化のために常に0
double R[12] ={1,0,0,0, 0,1,0,0, 0,0,1,0};
double p[3] = {0.0, 0.0, 0.05};   // 重心の位置
double p[3] = {0.0, 0.0, 0.05};   // 位置(x,y,z)[m]
double sides[3] = {0.1, 0.1, 0.1}; // 直方体のサイズ(x, y, z)[m]
double start_x = 0.0, start_y = 0.0, start_z = 0.0; // 初期位置

void command(int cmd)
{
    float xyz[3], hpr[3];
    switch (cmd) {
        case 'z':
            start_z += 0.1;
            break;
        default:
            printf("Input z key \n");
    }
}

void simLoop(int pause)        /***  シミュレーションループ ***/
{
  int i, j, num = 11;          // 直方体の数
  static float red = 0.0, green = 0.0, blue = 0.0; // 赤,緑,青成分

  for (i = 0; i < num; i++) {
      for (j = 0; j < num; j++) {
        red = (float) rand()/RAND_MAX;   // 赤成分を乱数で決定
        dsSetColor(red, green, blue);    // 色の設定
        p[0] = start_x;                  // 位置のx成分
        p[1] = i * 0.2 - 1.0  + start_y; // 位置のy成分
        p[2] = j * 0.2 + 0.05 + start_z; // 位置のz成分
        dsDrawBox(p,R,sides); // 直方体の表示
      }
  }
}

int main()         /*** main関数 ***/
{
  srand(time(NULL)); // 乱数の初期化
  dmLoop(800, 600, simLoop, command);  // ウインドウの横,縦,シミュレーション関数,コマンド関数
 return 0;
}

演習

  1. step2-160608.zipをダウンロードして実行しよう.
  2. jキーを押すと右,fキーを押すと左にボックス全体が移動するようにしよう.
  3. 3行(jの値が2)、4列(iの値が3)目のボックスだけをキー操作でx, y, z軸の正負方向へ移動できるようにしよう.つまり,6個のキーを割り当てる必要があります.simLoop関数の中でif文を使う必要があります.
  4. まず、ボックスを全て白色に変更し,乱数を使い1つのボックスだけ黒色に描画するプログラムを書こう.
  5. まず、ボックスを全て白にし、数字0を黒いブロックを複数使い電光掲示板のように表示するプログラムを書こう.
  6. [発展問題」 まず、ボックスを全て白にし、9から0までの数字を黒いブロックを複数使いカウントダウン表示する電光掲示板を作りましょう。0から9までの数字を表示する部分はそれぞれ関数にすること。

物理エンジンODEで学ぶC言語 [STEP3:関数]動力学計算

$
0
0
落下する赤い球

落下する赤い球

ODEで学ぶC言語のStep3です.今回は私がODEのAPIを元に作成した関数を使い,赤い球を落下させるプログラムを説明します.

今までのプログラムでは描画だけでしたが,今回からシミュレーションやゲームを作るために必要な動力学計算や衝突検出計算も含んでいます.サンプルプログラムとしては,物理シミュレーションで最も簡単な物体の落下を取り上げます.C言語などのプログラミングの教科書では初めの例題はHello Worldを表示する例が定番です。ここではHello Worldの物理シミュレーション版を紹介します.

 

  • API

    ここでは簡単にするためにODEのAPIを元に,超簡単なAPIを作成しました.ただし、ODEのAPIのように細かいことはできません。

    • void dmInit();
      シミュレーションを初期化します.
    • void dmCreateSphere(dmObject *obj, double p[3], double R[12], double m, double r, double color[3]);
      球を作成します.引数のp[3]は位置(x,y,z)[m],R[12]は姿勢(回転行列), mは質量[kg],rは半径[m],color[3]は色(赤,緑,青各成分、値は0以上1以下)です.
    • void dmSimStep();
      シミュレーションを1ステップ進めます.
    • dmDraw(MyObject obj);
      引数のオブジェクトobjを描画する.
  • ソースコード
        次に、詳しいコメントのついたソースコードを以下に示します。main関数から読んでください。
    /* step3 リンゴ(林檎)の落下  */
    #include "dm3.h"
    
    dmObject apple;  // リンゴ
    
    void simLoop(int pause)           /***  シミュレーションループ ***/
    {
        dmSimStep(); // シミュレーションを1ステップ進める
        dmDraw(apple);   // リンゴの描画
    }
    
    int main()   /*** main関数 ***/
    {
        double p1[3] = {0.0, 0.0, 2.0}; // 位置 [m]
        double R[12] = {1,0,0,0, 0,1,0,0, 0,0,1,0}; // 姿勢(回転行列)
    
        double red[3]    = {1.0, 0.0, 0.0}; // 赤色
        double r = 0.2, m = 1.0;  // 半径[m],質量[kg]
    
        dmInit(); // 初期化
        dmCreateSphere(&apple, p1, R, m, r, red); // 球の作成
        dmLoop(800, 600, simLoop, NULL);  // ウインドウの幅,高, ループ関数,コマンド関数
        dmClose(); // 終了処理
    
        return 0;
    }
    • これは赤い玉の自由落下のプログラムです。まず、dmInit()でシミュレーションを初期化します。
    • 次に物体を作ります.球を作るAPIはdmCreateSphere()です.
    • 物体の生成が終わったら、次はシミュレーションを1ステップ進めます。dmLoop()の中身はwhileループになっていて、繰り返しsimLoop関数が呼び出しています。dmLoop()の一番最後の引数がNULLになっているのは、このサンプルプログラムではキー操作可能なcommand関数がないからです。前回の例のようにcommand関数がある場合はNULLの代わりにcommandを入れてください。
    • お次は物体の描画です.dmDraw(apple)で落下する球を表示しています。dmDraw()の引数は表示したい物体をいれてください。
    • 最後にシミュレーションをdmClose()で終了します.なお、小文字のdmで始まる関数は私がこの講義用にODEのAPI(application interface)を元に作成したものです.
  • ホームワーク
    1. step3-160615.zipをダウンロードして実行しよう!
    2. 次のAPIを使い青いボックスを位置p[3]={0.0, 1.0, 2.0}に作成し,落下させるプログラムを作ってください.
      • void dmCreateBox(dmObject *obj, double p[3], double R[12], double m, double side[3],  double color[3]);
      • 物体 obj, 位置 p[3],  姿勢(回転行列)R[12],  質量 m, サイズ(x,y,z) side[3], 色 color[3]
      • なお、回転行列は3×3行列ですが、ODEでは高速化のために3×4行列として各行の最後に0を追加しています。
    3. 今度は緑色の円柱を位置(0.0, -1.0, 2.0)に作成し,落下させなさい.
      • void dmCreateCylinder(dmObject *obj, double p[3], double R[12], double m, double r, double l, double color[3]);
      • 物体 obj, 位置 p[3],  姿勢 R[12],  サイズ sides[3], 半径 r, 長さ l, 質量 m, 色 color[3]
    4. 最後に,黄色のカプセルを位置(-1, 0, 2)に作成し,落下させなさい.
      • dBodyID  dmCreateCapsule(dmObject *obj, double p[3], double R[12], double m, double r, double l, double color[3]);
      • 物体 obj, 位置 p[3],  姿勢 R[12],  サイズ sides[3], 半径 r, 長さ l, 質量 m, 色 color[3]

 

物理エンジンODEで学ぶC言語 [STEP4:構造体]力とトルクの与え方

$
0
0

ブロック崩しを作ろう!

物理エンジンで学ぶC言語のStep4です.今回は構造体と物体へ力やトルクを加える方法,さらにシミュレーションのリセット法などを学びます.構造体の概要については既にわかっているものとし,サンプルコードを示すことにより具体的な使い方を学びます.例として、Step4とStep5でスティーブン・ジョブスがAtari社時代に、アップルの共同設立者ウォズニアックと開発に携わったBreakout(ブロック崩し)風のゲームを作ってみましょう。

○ 構造体

配列では同じ型しかまとめることができませんでしたが,構造体では違う型をまとめて扱うことができるのでシミュレーションなど物体に多くの属性がある場合に便利です.このサンプルプログラムでは物体をdmObjectという構造体で次のように表しています.dm4.hの16行目に定義しています.

typedef struct{
    dBodyID body; // ボディのID
    dGeomID geom; // ジオメトリのID
    const double *p; // x, y, z [m]
    const double *R;   // 回転行列 要素数4x3
    double m; // 質量 [kg]
    double r,l; // 半径 [m], 長さ [m]
    const double *side; // サイズ x,y,z
    const double *color; // 色 r,g,b
} dmObject;

また、STEP3まではdmLoop関数の引数にstep関数やcommand関数を渡していましたが、ここでは関数のポインタを要素に持つ構造体dmFunctionsを定義します。今まではdmLoopに渡す関数が増えるとその数だけ引数が多くなってしまいましたが、この構造体だけを引数として渡せば良いのでプログラムがすっきりします。

typedef struct
{
    void (*start)();            // 初期化関数
    void (*step) (int pause);	// ステップ関数
    void (*command) (int cmd);	// キー関数
} dmFunctions;

 衝突検出だけ働く物体の作り方

物理エンジンODEでは物体は2つの属性からできています。一つは動力学計算の対象となるbody(ボディ)、もう一つは衝突検出の対象となるgeometry(ジオメトリ)です。ゲームでは動かない建物や壁など動力学計算を働かせる必要のない物体は衝突検出計算だけを適応すれば計算処理が軽くて済みます。ここでは、衝突検出計算だけ働く物体を作るAPIを紹介します。

  • void dmCreateBoxStatic(dmObject *obj, double p[3], double R[12], double m, double side[3], double color[3]);

衝突検出計算しか作用しない物体を作成します.dmCreateBoxの後にStatic(静的)を付け加えたAPI名です。引数のp[3]は位置(x,y,z)[m],R[12]は姿勢(回転行列), mは質量[kg],sideは直方体の各辺の長さ[m],color[3]は色(赤,緑,青各成分、値は0以上1以下)です.同様なAPIとして、dmCreateSphereStatic, dmCreateCylinderStatic, dmCreateCapsuleStaticがあります。

姿勢の変更

物体の姿勢を変更するためには次のAPIを使い回転行列Rの値を変更します.ここで,Rは回転行列が格納されている配列へのポインタ,ax, ay, axは回転軸ベクトル.angleは回転角度となります.なお,dだけで始まるAPIはODEのAPIです.

  • dRFromAxisAndAngle(double R[12], double  ax, doulbe  ay, double  az, double angle);

○ 力,トルクの加え方

  • void dmAddForce(dmObject *obj, double fx, double fy, double fz)
    • 物体objの重心に力(fx,fy,fz)を加える
  • void dmAddTorque(dmObject *obj, double fx, double fy, double fz)
    • 物体objの重心にトルク(fx, fy, fz)を加える.fx,fy,fzはそれぞれx, y, z軸まわりのトルク

○ 高速なシミュレーション

前回のサンプルではシミュレーションのステップ関数としてdmWorldStep()を使いましたが,ここではより高速なdmWorldQuickStep()を使います.ただし,dmWorldStep()と比較して精度が悪くなります.

○ シミュレーションのリセット

rまたはRキーを押すと,resetSim関数が呼ばれてシミュレーションがリセットされます.resetSimの中身はシミュレーションループが1回以上呼び出されたときにdmInit関数を呼び出して初期化し,物体を再度生成しています.

○ ソースコード

/* step4 ブロック崩し 2016-06-22  */
#include "dm4.h"

static int STEPS = 0;   // シミュレーションのステップ数
double red[3]     = {1.3, 0.0, 0.0}; // 赤色
double yellow[3] = {1.3, 1.3, 0.0}; // 黄色
double green[3] = {0.0, 0.8, 0.0}; // 緑色

dmObject ball, field, fence[3], bar; // ドミノ, フィールド, 柵
dmFunctions dmf; // 描画関数の構造体

/***  シミュレーションループ ***/
void simLoop(int pause)
{
    int i;
    dmAddForce(&ball, 0.0001, 0, 0); // ボールの落下速度を決める
    dmWorldQuickStep(); // シミュレーションを1ステップ進める(高速版)

    dmDraw(&ball);
    dmDraw(&bar);
    dmDraw(&field);
    for (i =0; i < 3; i++)
    {
        dmDraw(&fence[i]);
    }

    STEPS++;
}

void resetSim(int n)
{
    double m = 0.1; // 質量
    double side[3] = {0.2, 0.05, 0.5}; // サイズ
    double R[12] = {1,0,0,0, 0,1,0,0, 0,0,1,0}; // 姿勢
    double ball_pos[3]={-0.91, 0.25, 0.7}, ball_r = 0.03, ball_m = 0.1; // ボールの位置、半径、質量
    double bar_pos[3]={-0.08, 0, 0.6}, bar_side[3] = {0.01, 0.1, 0.1}, bar_m = 0.1; // ボールの位置、半径、質量
    double field_pos[3]={-0.5, 0, 0.5}, field_side[3] = {1, 1, 0.01}, field_m; // フィールドの位置、サイズ, 質量
    double fence_pos[3][3] = {{-1.0, 0, 0.6}, {-0.5, -0.5, 0.6},{-0.5, 0.5, 0.6}}; // 柵の位置
    double fence_side[3][3] = {{0.05, 1.05, 0.1}, {1.0, 0.05, 0.1}, {1.0, 0.05, 0.1}};
    double fence_m[3] = {0.1, 0.1, 0.1};
    int i;

    // シミュレーションの終了
    if (STEPS != 0)
    {
        dmClose();
    }

    dmInit(); // 初期化

    //  ボールの生成
    dmCreateSphere(&ball, ball_pos, R, ball_m, ball_r, red);

    // バーの生成
    dmCreateBoxStatic(&bar, bar_pos, R, bar_m, bar_side, yellow);

    // フィールドの生成
    dmCreateBoxStatic(&field, field_pos, R, field_m, field_side, green);
    for (i =0; i < 3; i++) {
        dmCreateBoxStatic(&fence[i], fence_pos[i], R, fence_m[i], fence_side[i], green);
    }
}

/*** キ―入力関数 ***/
void command(int cmd)
{
    switch (cmd)
    {
    case 'r':
    case 'R':
        resetSim(0);
        break;
     default:
        printf("Input r, R, f, F key \n");
        break;
    }
}

/*** カメラの位置と姿勢設定 ***/
void setCamera()
{
    float x =  -0.5, y = 0.0, z = 1.5;    // カメラの位置
    float roll = 0, pitch = -90, yaw = -180; // カメラの方向[°]
    dmSetCamera(x,y,z,roll,pitch,yaw);  // カメラの設定
}

/*** 描画用構造体の設定 ***/
void setDraw()
{
    dmf.start       = &setCamera;
    dmf.step        = &simLoop;
    dmf.command = &command;
}

/*** main関数 ***/
int main()
{
    resetSim(0); // シミュレーションのリセット
    setDraw();   // 描画関数の設定
    dmLoop(800, 600, &dmf);  // ウインドウの幅,高, ループ関数,コマンド関数
    dmClose(); // 終了
    return 0;
}

ホームワーク5

  1. step4-160622.tgzをダウンロードして実行しよう!
  2. 黄色のバーをfまたはFキーを押すと左、jまたはJキーを押すと右にバーが動くように変更しよう!
    ヒント: 黄色のバーには動力学を適応させていないのでdGeomSetPosition(dGeomID geom, double x, double y, double z);を使って強制的に位置を移動させる。ここで、1番目の引数にはbar.geomを入れればよい。2から4番目の引数は、絶対座標系での位置のx, y, z成分。
  3. ボールが斜めに落ちるように、初めに横方向に力を加えよう!
    ヒント:dmAddForce(dmObject *obj, double fx, double fy, double fz); を使おう。resetSim関数内のdmCreateSphere関数のすぐ後にdmAddForceを入れよう。なお、力の方向や大きさを乱数を使って変化させるとゲームが面白くなる。
  4. ブロックを3行10列、合計30個表示しよう!各行で色を変えると見栄えがするよ。
    ヒント: dmObject  fence[3]; ボール落下防止用の柵に関するコードを参考にすると良い。
  以上

物理エンジンODEで学ぶC言語 [STEP5:まとめ]

$
0
0

ブロック崩し風ゲーム。未完成。続きを作ろう!

今回でこの講座は終わりです。先週作り始めたブロック崩し風ゲームを完成させましょう。

この手のゲームで必要になることは、ボールがブロックの当たったときにブロックの消す処理です。このサンプルプログラムではブロックを3個用意し、それぞれの当たりを判定する変数をblock1_hit, block2_hit, block3_hitとして0で初期化します。

ボールとブロックが衝突したらその変数を1に設定し、そのブロックを破壊し表示しないという処理を行っています。

// step5.cpp
int block1_hit = 0, block2_hit = 0, block3_hit = 0; // ブロックにボールが衝突すれば1、しないと0

/***  シミュレーションループ ***/
void simLoop(int pause)
{
    int i, j;

    dmWorldQuickStep(); // シミュレーションを1ステップ進める(高速版)

    dmDraw(&ball);
    dmDraw(&bar);
    dmDraw(&field);

    for (i =0; i < 3; i++)
    {
        dmDraw(&fence[i]);
    }

    // ブロックがボールに衝突していない場合はブロックを表示し
    // ブロックがボールに衝突した場合はブロックを破壊する。
    if (block1_hit==0) dmDraw(&block1);
    else                  dmDestroyBox0(&block1);

    if (block2_hit==0) dmDraw(&block2);
    else                  dmDestroyBox0(&block2);

    if (block3_hit==0) dmDraw(&block3);
    else                  dmDestroyBox0(&block3);

    STEPS++;
}

次に、今まで秘密のベールに包まれていたdm6.cppを説明します。このファイルでODEを簡単に使う関数を作っています。まず、2,3行目のexternで始まる変数の宣言は、dm6.cpp以外のファイルで宣言しているよとコンパイラーに教えています。これらの行がないとblock1, block1_hitが宣言されていないとエラーになり、externを付けないとstep6.cppでも宣言されているので2重定義でエラーになってしまいます。大きなプログラムは複数のファイルで構成されるのでこのexternは覚えておきましょう。

お次は、衝突検出を説明します。これはdm6.cpp内のnearCallback関数で行われています。if else文でブロック1のジオメトリ(block1.geom)、ブロック2のジオメトリ(block2.geom)、ブロック3のジオメトリ(block3.geom)がボールのジオメトリ(ball.geom)がo1, o2のどちらかなら衝突しているので、衝突判定用の変数block1_hit, block2_hit, block3_hitに1を代入しています。なお、ジオメトリとはODEで衝突判定に使われる物体の属性です。

また、nearCallback関数は2つの物体(正確にはジオメトリ)が接近して衝突しそうになったら自動で呼び出せれる関数です。このような関数をコールバック関数と呼びます。電話のコールバックをイメージしてください。引数のジオメトリo1, o2は衝突しそうな2つのジオメトリです。

このサンプルプログラムでたった3個のブロック崩し風ゲームは完成です。後は、いろいろ工夫して自分だけのゲームを完成させてください。

終わり。

// dm5.cpp
extern dmObject ball, field, fence[3], bar, block1, block2, block3;
extern int block1_hit, block2_hit, block3_hit;

/*** 衝突検出関数(コールバック関数) ***/
void nearCallback(void *data, dGeomID o1, dGeomID o2)
{
    static const int N = 10; // 接触点数の最大値
    dContact contact[N];     // 接触点

    // 衝突情報の生成 nは衝突点数
    int n = dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact));

    for (int i = 0; i < n; i++)
    {
        contact[i].surface.mode = dContactBounce; // 接触面の反発性を設定

        // ボールとバーが接触したら反発係数を1.5に設定
        if(((ball.geom == o1) && (bar.geom == o2)) || ((ball.geom == o2) && (bar.geom == o1)))
        {
            contact[i].surface.bounce = 1.5;          // 反発係数(実際の世界では0.0から1.0)
        }
        // ボールと床が接触したら反発係数を0.5に設定
        else if (((ball.geom == o1) && (field.geom == o2)) || ((ball.geom == o2) && (field.geom == o1)))
        {
            contact[i].surface.bounce = 0.5;
        }
        // ボールとブロック1が接触したら。block1_hitを1に設定
        else if (((ball.geom == o1) && (block1.geom == o2)) || ((ball.geom == o2) && (block1.geom == o1)))
        {
             block1_hit = 1;
        }
        // ボールとブロック2が接触したら。block2_hitを1に設定
        else if (((ball.geom == o1) && (block2.geom == o2)) || ((ball.geom == o2) && (block2.geom == o1)))
        {
             block2_hit = 1;
        }
         // ボールとブロック3が接触したら。block2_hitを1に設定
        else if (((ball.geom == o1) && (block3.geom == o2)) || ((ball.geom == o2) && (block3.geom == o1)))
        {
             block3_hit = 1;
        }
        // その他は反発係数を0.8に設定
        else
        {
            contact[i].surface.bounce = 0.8;
        }

        // contact[i].surface.bounce_vel = 0.05;      // 反発に必要な最低速度
        contact[i].surface.mu = 0.0;// dInfinity;        // 摩擦係数

        // 接触ジョイントの生成
        dJointID c = dJointCreateContact(world,contactgroup,
                                         &contact[i]);
        // 接触している2つの剛体を接触ジョイントにより拘束
        dJointAttach(c,dGeomGetBody(contact[i].geom.g1),
                     dGeomGetBody(contact[i].geom.g2));
    }
}

ホームワーク

  1. step5-160713.zipをダウンロードして実行しよう!
  2. ブロックの数を1個増やそう。
  3. 3で作ったブロックの色を黒に変更しよう。
  4. ブロックの数を増やし、競技盤の半分ぐらいは埋め尽くそう。配列を使うのが望ましい。
  5. ボールの初期位置と飛び出す方向をランダムに変えよう。
  6. バーが競技盤を飛び出してしまいます。飛び出さないようにしよう。
  7. 得点を表示する機能を付けよう。標準出力にprintfでもかまいません。
  8. いろいろ工夫して自分だけのブロック崩し風ゲームを作ろう!遊ぶためにゲームの説明を文字ウインドウに表示しよう。

物理エンジンODEで学ぶC言語 [STEP6:補講] ジョイントの生成と制御

$
0
0

 

STEP6: 玉突きロボット

 

ODEで学ぶC言語のStep6です.Step5で一応終了しましたが、要望の多かったジョイントの使い方と制御を説明します。補講となります。

ジョイントは我々の周りでは、折畳み携帯のヒンジやドアの蝶番に相当します。小難しくいうと、2つのボディの位置や姿勢をある一定の関係に保つ拘束がジョイントとなのです。ODEではジョイントと拘束を同じ意味で使っています。

ODEのジョイント(関節)は2つのボディ(剛体,body)をつなげるものです。1つのジョイントで3個以上のボディをつなげることはできませんし,1個のボディだけをつなげることもできません.必ず2個のボディを1つのジョイントでつなげなければなりません.

また,ODEのジョイントは摩擦がありませんし,可動域を設定しないと+dInfinity(+無限大)から-dInfinity(-無限大)まで回転または移動します.角度は[rad]です.

 

  • ジョイントの使い方
  1. ***ジョイントの生成      dmJointCreate***()
  2. ***ジョイントとボディの結合  dJointAttach(dJointID, dBodyID, dBodyID)
  3. ***ジョイントの中心点を設定 dJointSet***Anchor()
  4. ***ジョイントの回転軸を設定 dJointSet***Axis()

上で***にはジョイントのタイプが入ります。タイプにはHinge(ヒンジ)、Slider(スライダー)があります。サンプルプログラムではヒンジジョイントと直動式のスライダージョイントを使います.

  • ジョイントのパラメータ設定
  1. 可動域の設定
    dJointSetHingeParam(dJointID, dParamLoStop, 可動域の下限);
    dJointSetHingeParam(dJointID, dParamHiStop, 可動域の上限);
  2. 目標角速度とそれを実現するための最大トルクの設定
    dJointSetHingeParam(dJointID, dParamVel, 目標角速度);

    dJointSetHingeParam(dJointID, dParamFMax, 最大トルク);

パラメータとしては、関節可動域の下限を示すdParamLoStop、上限を示すdParamHiStop、角速度(ヒンジジョイント)または速度(直動式関節)を示すdParamVel、最大トルクを示すdParaFMaxなどがあります。なお、ODEでは関節にモータが標準で組み込まれているので、dParamVelやdParaFMaxを指定すると関節が動きます。

ソースコード
少し長くなりますが,ソースコードを掲載します.このコードは今まで習った,キー操作関数,シミュレーションの再スタート,ボディへ力を加えるなどのほかに,ジョイントの生成と制御法など簡単なゲームやシミュレータを作るために必要なことは一通り入っています.

/* step6 */

#define START_X 0.0
#define START_Y 0.0
#define START_Z 0.1

dmObject torso, leg[2], ball;
static int STEPS = 0;      // シミュレーションのステップ数
double S_LENGTH  = 0.0;    // スライダー長
double H_ANGLE   = 0;      //ヒンジの角度

// ロボットの生成
void createMonoBot()
{
    int i;
    double l_leg = 0.75; // 長さ
    double m_leg = 1.0;  // 質量
    double r_leg[2] = {0.05, 0.03}; // 半径
    double m_torso = 100.0; // 胴体の質量
    double r_torso = 0.25;  // 胴体の半径
    double l_torso = 0.2;   // 胴体の高さ
    double r_ball = 0.11;   // ボールの半径
    double m_ball = 0.5;    // ボールの質量
    double p_ball[3] = {START_X, START_Y+2*l_leg+0.1, START_Z}; // ボールの位置
    double p_torso[3] = {START_X, START_Y, START_Z};  // 位置
    double p_leg[2][3] = {{START_X, START_Y+0.5*l_leg, START_Z},
        {START_X, START_Y+l_leg, START_Z}
    };
    double p_anchor[3] = {START_X, START_Y, START_Z};
    double R[12];   // 回転行列

    static double  red[3] = {1.0, 0.0, 0.0}; // 色
    static double  color_leg[2][3] = {{0.0, 0.0, 1.0},{1.3, 1.3, 1.3}};

    dRSetIdentity(R);  //回転行列を単位行列で初期化
    dmCreateSphere(&ball, p_ball,R,m_ball, r_ball, red); // ボールの生成
    dmCreateCylinder(&torso,p_torso,R,m_torso,r_torso,l_torso,red); // 胴体の生成

    dRFromAxisAndAngle(R, 1, 0, 0, M_PI/2);
    for (i = 0; i < 2; i++)
    {
        dmCreateCapsule(&leg[i],p_leg[i],R,m_leg,r_leg[i],l_leg,color_leg[i]); // 脚の生成
    }

    // ヒンジジョイント
    leg[0].joint = dmJointCreateHinge();
    dJointAttach(leg[0].joint, torso.body,leg[0].body);
    dJointSetHingeAnchor(leg[0].joint, p_anchor[0],p_anchor[1],p_anchor[2]);
    dJointSetHingeAxis(leg[0].joint, 0, 0, 1);

    // スライダージョイント
    leg[1].joint = dmJointCreateSlider();
    dJointAttach(leg[1].joint, leg[0].body,leg[1].body);
    dJointSetSliderAxis(leg[1].joint, 0, 1, 0);
    dJointSetSliderParam(leg[1].joint, dParamLoStop, -0.25);
    dJointSetSliderParam(leg[1].joint, dParamHiStop,  0.25);
}

// ヒンジジョイントの制御
static void controlHinge(dReal target)
{
    static dReal kp = 10.0, fmax = 1000;

    dReal tmp   = dJointGetHingeAngle(leg[0].joint);
    dReal diff  = target - tmp;
    if (diff >=   M_PI) diff -= 2.0 * M_PI; // diffが2πより小さく
    if (diff <= - M_PI) diff += 2.0 * M_PI; // diffが-2πより大きく
    dReal u     = kp * diff;

    dJointSetHingeParam(leg[0].joint, dParamVel,  u);
    dJointSetHingeParam(leg[0].joint, dParamFMax, fmax);
}

// スライダの制御 プログラム2.4
static void controlSlider(dReal target)
{
    static dReal kp   = 25.0;                       // 比例定数
    static dReal fmax = 1000;                        // 最大力[N]
    double tmp, u;

    tmp  = dJointGetSliderPosition(leg[1].joint);  // スライダの現在位置
    u    = kp * (target - tmp);                    // 残差
    dJointSetSliderParam(leg[1].joint, dParamVel,  u);
    dJointSetSliderParam(leg[1].joint, dParamFMax, fmax);
}

// シミュレーションのリセット
static void resetSim()
{
    STEPS    = 0;      // ステップ数の初期化
    H_ANGLE  = 0.0;    // ヒンジ角度の初期化
    S_LENGTH = 0.0;

    if (STEPS != 0) dmClose(); // シミュレーションの終了

    dmInit();  // シミュレーションの初期化
    createMonoBot();
}

// キー操作
void command(int cmd)
{
    switch (cmd)
    {
    case 'j':
        S_LENGTH =   0.25;
        break;
    case 'l':
        S_LENGTH = - 0.25;
        break;
    case 'i':
        H_ANGLE +=   0.25;
        if (H_ANGLE  >   M_PI) H_ANGLE  =  -M_PI;
        break;
    case 'm':
        H_ANGLE -=   0.25;
        if (H_ANGLE  <  -M_PI) H_ANGLE  =   M_PI;
        break;
    case 'r':
        resetSim();
        break;
    case 'a':
        dBodyAddForce(torso.body, 0, -500, 0);
        break;
    case 'w':
        dBodyAddForce(torso.body, -500, 0, 0);
        break;
    case 'd':
        dBodyAddForce(torso.body, 0,  500, 0);
        break;
    case 'x':
        dBodyAddForce(torso.body,  500, 0, 0);
        break;
    case 's':
        dBodySetLinearVel(torso.body,  0, 0, 0);
        dBodySetAngularVel(torso.body, 0, 0, 0);
        break;
    default :
        printf("key missed \n");
        break;
    }
}

void simLoop(int pause)           /***  シミュレーションループ ***/
{
    int i;
    int s = 1000;                   // 跳躍する周期(ステップ)

    if (!pause)
    {
        printf("STEPS=%d \n",STEPS++); //  ステップ数

        // スライダーの伸縮
        //if ((0 <= (STEPS%s)) && ((STEPS%s) <= 10)) S_LENGTH = 0.6;
        //else if ((11 <= (STEPS%s)) && ((STEPS%s) <= 15)) S_LENGTH = 0.0;

        controlSlider(S_LENGTH); // スライダージョイントの制御
        controlHinge(H_ANGLE);   // ヒンジジョイントの制御

        dmSimStep(); // シミュレーションを1ステップ進める
    }

    dmDraw(&ball); // ボールの描画
    // ロボットの描画
    dmDraw(&torso);   // 胴体の描画
    for (i = 0; i < 2; i++)dmDraw(&leg[i]); //脚の描画
    STEPS++;
}

int main()         /*** main関数 ***/
{
    dmInit(); // ODEの初期化
    resetSim();   // ロボットの生成
    dmLoop(800, 600, simLoop, command);  // シミュレーションループ ウインドウの幅,高
    dmClose();          // ODEの終了
    return 0;
}

ホームワーク

  • step6-160713a.zipをダウンロードして実行してみましょう.
  • サンプルプログラムを改良してビリヤードをプレイするロボットを作りましょう.

RoboCup2016世界大会8位でした!

$
0
0

welcome

6月28日から7月4日までドイツのライプチヒ市で開催されたRoboCup2016世界大会に出場した金沢工業大学demura.netチームが@Homeリーグで23チーム中8位の成績を収めました。

RoboCup世界大会は人工知能を搭載した自律ロボットによる競技会で、今年の大会には世界45ヶ国から3500名の参加者、1200台のロボットが参加した世界最大のロボット競技会の一つで、年々規模が大きくなりオリンピックの様相を呈してきました。その中で@Homeリーグは人間の生活を支援するロボットの研究開発促進のために設立されたリーグで、家庭を模した会場で顔認識、物体認識、音声認識、ナビゲーションなどの一連の技術を競います。

今回参加したdemura.netチームは金沢工業大学夢考房RoboCup@Homeプロジェクト、夢考房Junior、ロボティクス学科出村研究室の合同チームで、メンバーは次のとおりです。

メンバー

  • ロボティクス学科 教授 出村公成:指導責任者
  • ロボティクス学科4年 永島一輝:音声認識担当
  • ロボティクス学科3年 榎本光洋:チームリーダー、ナビゲーション担当
  • ロボティクス学科2年 山川武聖:ハードウェア担当
  • 明聖高校3年 出村賢聖:顔認識・物体認識・プレゼン担当

競技は、Stage1、Stage2、Finalと進み、Stage1に出場した23チームから上位12チームがStage2に進出し、Stage2の上位5チームがFinalへ進出できます。今回、demura.netチームはFinalへの進出を目標としていました。

Stage 1

Stage1はRIPS(Robot Inspections)、Follow&Guide、GPSR (General Purpose Service Robot)、Manipulation、Person Recogntion、Speech Recognitionの6種目の競技合計点を競います。
demura.netチームは日本大会ではSpeech Recognitionテストで満点を取得しました。この競技は会会場で与えられた50問の質問のうちランダムで10問選び、人がロボットに質問し、ロボットが解答し、その正解数を競います。10問のうち5問はロボットの正面から、残りの5問は正面以外の5方向からロボットに質問し、ロボットはその音源を定位しなければなりません。そのため、システムインフロンティア製の8chマイクロフォンアレーTAMAGOを装備して、HarkとKaldiを使いソフトウェアを開発しました。研究室内の練習では150点満点中コンスタントに130点を取得しており、かなり自信を持って臨みました。本番では、周りの環境音と比較して話者の声が小さく55点と振る舞わず、思うように得点できませんでした。結果が出るまで気が気でありませんでしたが、何とか11位でStage2に進むことができました。



mini_navi2

facerecog

stage1

Stage2

Stage2はRestaurant、EEGPSR(Enhanced Endurance General Purpose Service Robot)、Open Challengeの3競技でStage1の合計点を合わせた上位5チームがFinalへ進出します。Restaurantは会場の実際のレストランを使い、ロボットウェートレスとしての機能を競います。この競技はぶっけ本番です。場所も本番の直前に教えられるので全く未知の環境で競技を行わなければならない非常に難易度の高い競技です。demura.netチームはテーブルの場所を覚えるところまででき、3番目得点を獲得できました。

EEGPSRはStage1のGPSR(General Purpose Service Robot: 汎用目的サービスロボット)をさらに難しくしたもので、難易度によって6つのカテゴリに分かれています。例えば、「キッチンへ行き、テーブルの上のコーラを取って、リビングルームにいるトムに渡しなさい。」、あるいは、命令が矛盾してタスクを遂行できないといった問題もあります。その場合は、何が矛盾しているかロボットが音声で伝える必要があります。demura.netチームはミスもあり、得点できませんでした。

最後の、Open Challengeは各チームの日頃の研究を発表する自由デモンストレーションです。持ち時間は10分で、説明3分以内、残りはロボットのデモとなります。demura.netチームは紙の絵本を読むデモンストレーションを行いました。絵本は文字が背景画像の中に描かれているので文字認識がとても難しいもので、スクリーンに映像が映らないというミスはあったものの112点と比較的高得点を取得できました。

picturebook

結局、合計301点となり、全体では8位となりFinal進出を逃しました。7位の東大・中国南開大学・シンガポール工科大学・芝浦工大連合チームとの得点差はわずが4点でした。昨年はRoboCup世界大会初出場で9位、得点167点でした。今年は得点もほぼ倍増し、自分たちの足りない点もわかり、確かな手ごたえを掴みました。来年のRoboCup世界大会は名古屋で開催されます。日本開催の有利を活かして表彰台を狙います!

members

stage2

なお、今回、世界大会に参加できたのは、以下のスポンサー様の暖かいご支援によるものです。

sponser

  • プラチナスポンサー:
    株式会社 都筑製作所
  • ゴールドスポンサー:
    中村留精密工業株式会社
    三光合成株式会社
  • シルバースポンサー:
    株式会社 システムインフロンティア
    東京ドロウイング株式会社
    マスプロ電工株式会社
    アーテック株式会社
  • ブロンズスポンサー:
    株式会社 金沢エンジニアリングシステムズ
    株式会社 第1システムエンジニアリング
    株式会社 アイ・ティー・ケー
    丸文通商株式会社

ありがとうございました。

RoboCup2016世界大会報告会7月29日(金)17時~

$
0
0

110

RoboCup2016世界大会報告会を以下の予定で実施します。今、ロボット業界が注目しているRoboCup、その中でも一番ホットなのが@Homeリーグです。学生が世界大会に参加して何を見て、感じ、得たものは何か。学生の皆さん、是非お越しください。

日時:7月29日(金)17時~18時
場所:KIT扇が丘キャンパス12号館4階イノベーションホール
演者:4年永島一輝、3年榎本光洋、2年山川武聖

http://www.kanazawa-it.ac.jp/kitnews/2016/20160720_robocup.html

 

ロボットプログラミングⅡ-2016 環境設定

$
0
0

この記事は私が担当している講義ロボットプログラミングⅡ用です。

turtlebot

ロボットプログラミングⅡでは、フレームワークとしてROSロボットシミュレータとしてGAZEBOを使用します。インストールは次の手順です。Panasonic Let’s Note CF-LX3 (Windows 8.1, Core i7, Memory 8GB)で試しています。

では、以下のリンクに従って第2週の授業までに作業を進めてください。

  1. VirtualBox5.0 + Ubuntu14.04のインストール
    注:仮想マシンの登録と起動 (2) に誤植がありました。バージョンは[Ubuntu(64-bit)]を選択してください。32-bitだと起動に失敗します。お詫びして訂正します(2015年10月4日17:15)。
  2. VirtualBox5.0の設定
  3. Ubuntu14.04のWindowマネージャー設定
  4. Ubuntu14.04のネットワーク設定
  5. ROS Indigoのインストール

以上

Viewing all 757 articles
Browse latest View live