顯示具有 C 標籤的文章。 顯示所有文章
顯示具有 C 標籤的文章。 顯示所有文章

2012年8月15日 星期三

在 Android ICS 下新增 userspace cosole application 的方法

1. 比照 external 內的資料夾,新增一個 project folder ,內容比照辦理。

2. 進入 device 資料夾,加入新的 application 定義

3. 可參考內建程式:tinymix, tinycap, tinyplay…

2012年5月16日 星期三

20120516 工作筆記

1. 在 linux console 下設定 proxy:
export http_proxy=”
http://hostname:portnumber”

2. SD card (sdb1、sdb2) mount 完成後(假設 mount 在 /media/boot/ 和 /media/rootfs/ 下),將 foo.tar.bz2 解壓到 /media/rootfs/:
tar jxfv foo.tar.bz2 –C /media/rootfs

3. 將 foo.tar.gz 解壓到 /myfolderpath/
tar zxfv foo.tar.gz –C /myfolderpath/

4. check out SVN server 中第 38 個版本:
svn co –r 38 –username MYNAME –password PASSWORD svn://hostip/folder/subfolder

5. 搜尋 FOLDER 資料夾中含有關鍵字 KEYWORD 的檔案並標示行數:
grep –r –n “KEYWORD” FOLDER

6. 讓自己寫的 script 開機後自動執行:
/etc/profile.d/my_script.sh

7. universalIndentGUI => save config file => create batch file (config and batch files shoud be at the same directory)

8. Vim 中的長字串自動完成:ctrl-p 或 ctrl-n

9. Good to use 共用資料夾 in VirtualBox guest OS, it's easy and powerful.

10. shift + right click folder => open command here

11. in 64bit Win7, 32bit-chrome will download 32bit Java by default

12. MSN minimize to system tray => Vista Mode

13. gtags 好像只能在 WinXP 32bit 下面才能正常運作,Win7 x64 無法, 但是在Ubuntu下可以正常運作

14. Good to use easygui in Python

15. win7 刪除服務 sc delete servicename

16. virtualbox network bridge 不能用混合模式

17. mount box.net: https://www.box.net/dav

18. mkmmc-android.sh

   1: #!/bin/bash
   2:  
   3: # Copyright (C) 2009 Andrei Dolnikov <dolnikov.andrei@gmail.com>
   4: #
   5: # Licensed under the Apache License, Version 2.0 (the "License");
   6: # you may not use this file except in compliance with the License.
   7: # You may obtain a copy of the License at
   8: #
   9: #      http://www.apache.org/licenses/LICENSE-2.0
  10: #
  11: # Unless required by applicable law or agreed to in writing, software
  12: # distributed under the License is distributed on an "AS IS" BASIS,
  13: # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14: # See the License for the specific language governing permissions and
  15: # limitations under the License.
  16:  
  17: if [[ -z $1 || -z $2 || -z $3 || -z $4 ]]
  18: then
  19:     echo "mkmmc-android Usage:"
  20:     echo "    mkmmc-android <device> <board name> <uImage> <rootfs tar.bz2 archive>"
  21:     echo "    Example: mkmmc-android /dev/sdc beagleboard uImage rootfs.tar.bz2"
  22:     exit
  23: fi
  24:  
  25: if [[ -z `which mkimage` ]]
  26: then
  27:     echo "Please, install mkimage on your host"
  28:     echo "    On Ubuntu systems: sudo apt-get install uboot-mkimage"
  29:     exit
  30: fi
  31:  
  32: if ! [[ -e $2 ]]
  33: then
  34:     echo "Incorrect board name!"
  35:     exit
  36: fi
  37:  
  38: if ! [[ -e $3 ]]
  39: then
  40:     echo "Incorrect uImage location!"
  41:     exit
  42: fi
  43:  
  44: if ! [[ -e $4 ]]
  45: then
  46:     echo "Incorrect rootfs tarball location!"
  47:     exit
  48: fi
  49:  
  50: echo "All data on "$1" now will be destroyed! Continue? [y/n]"
  51: read ans
  52: if ! [ $ans == 'y' ]
  53: then
  54:     exit
  55: fi
  56:  
  57: echo "[Partitioning $1...]"
  58:  
  59: dev_sz=`fdisk -l $1 | grep $1: | awk '{print$(NF-1)}'`
  60: cyl=$(expr $dev_sz / 512 / 63 / 255)
  61: fat_end=$(expr $cyl / 2)
  62:  
  63: fdisk "$1" &> /dev/null << EOF
  64: o
  65: x
  66: h
  67: 255
  68: s
  69: 63
  70: c
  71: $cyl
  72: r
  73: n
  74: p
  75: 1
  76:  
  77: $fat_end
  78: t
  79: c
  80: a
  81: 1
  82: n
  83: p
  84: 2
  85:  
  86:  
  87: w
  88: EOF
  89:  
  90: echo "[Making filesystems...]"
  91:  
  92: mkfs.vfat -F 32 -n boot "$1"1 &> /dev/null
  93: mkfs.ext3 -L rootfs "$1"2 &> /dev/null
  94:  
  95: echo "[Copying files...]"
  96:  
  97: mount "$1"1 /mnt
  98: cp $3 /mnt/uImage
  99: mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n $2/normal/boot.script -d $2/normal/boot.script $2/normal/boot.scr &> /dev/null
 100: cp $2/normal/boot.scr /mnt
 101: umount "$1"1
 102:  
 103: mount "$1"2 /mnt
 104: tar jxvf $4 -C /mnt &> /dev/null
 105: chmod 755 /mnt
 106: umount "$1"2
 107:  
 108: echo "[Done]"

2009年11月8日 星期日

ICP ( Iterative Closest Point )演算法實作( C 語言)


ICP ( Iterative Closest Point )演算法是用來將兩群點集合( point set )
對齊的演算法,這是我在去年修資工系王傑智老師的課「機器人知覺
與學習」學到的。


簡單解釋:

假設有兩個點集合 P 和 Q ,其中 P 和 Q 裡面的點數目未必一樣。
如果我知道 P 裡面的每個點都能在 Q 裡面找到相對應的點,另外我
假設經過一次平移和旋轉,可以讓 P 和 Q 之間的誤差最小(誤差的
算法:加總 P 裡面的所有點和 Q 中相對應的點之間的距離),那麼
一定可以經由計算得知所需的平移和旋轉量是多少。

##CONTINUE##不過,以上的敘述在現實應用上有個大問題,就是怎樣得知 P 、 Q
裡面的點的對應關係呢?

在這個演算法中,就是武斷的認定 Q 中「最近距離」的點就是對應
點,接著平移旋轉後,用新的點集合 P' 再迭代一次,得到 P'' ,
就這樣迭代到誤差收斂為止。

以下是我自己寫的 C 程式碼,因為學弟想要把它實驗在 DSP 裡面,
用 C 語言是比較直接的作法。


// icp.h

#ifndef _ICP_H
#define _ICP_H

typedef struct Point2D
{
double x;
double y;
} Point2D;

double p2p_length(Point2D p, Point2D q);

Point2D find_closest_point(Point2D target, Point2D* refPset, int size);

void icp_step(double* dx, double* dy, double* dth, Point2D* tgtPset, int t_size, Point2D* refPset, int r_size);

double icp(double* dx, double* dy, double* dth, Point2D* tgtPset, int t_size, Point2D* refPset, int r_size);

#endif


// icp.c

#include " icp.h "
#include < math.h >
#include < stdlib.h >
#include < stdio.h >

double p2p_length(Point2D p, Point2D q)
{
return sqrt(pow(p.x - q.x, 2)+pow(p.y - q.y, 2));
}

Point2D find_closest_point(Point2D target, Point2D* refPset, int size)
{
Point2D ret;
double min_distance;
int i;

ret = refPset[0];
min_distance = p2p_length(target, refPset[0]);
for(i=1; i < size; i++){
if(p2p_length(target, refPset[i]) < min_distance){
ret = refPset[i];
min_distance = p2p_length(target, refPset[i]);
}
}
return ret;
}

void icp_step(double* dx, double* dy, double* dth, Point2D* tgtPset, int t_size, Point2D* refPset, int r_size)
{
double sum_bx_times_ay;
double sum_by_times_ax;
double sum_bx_times_ax;
double sum_by_times_ay;
double mean_bx;
double mean_by;
double mean_ax;
double mean_ay;

Point2D* a = (Point2D*)malloc(t_size*sizeof(Point2D));
// accroding to paper, a is the closest point set
// according to paper, b is the target point set (tgtPset in this function)

int i;

// find closest point set
for(i=0; i < t_size; i++){
a[i] = find_closest_point(tgtPset[i], refPset, r_size);
}

// initialize dx, dy, dth
*dx = 0;
*dy = 0;
*dth = 0;
mean_bx = 0;
mean_by = 0;
mean_ax = 0;
mean_ay = 0;

for(i=0; i < t_size; i++){
mean_bx += tgtPset[i].x;
mean_by += tgtPset[i].y;
mean_ax += a[i].x;
mean_ay += a[i].y;
}

mean_bx = mean_bx / t_size;
mean_by = mean_by / t_size;
mean_ax = mean_ax / t_size;
mean_ay = mean_ay / t_size;

sum_bx_times_ay = 0;
sum_by_times_ax = 0;
sum_bx_times_ax = 0;
sum_by_times_ay = 0;

for(i=0; i < t_size; i++){
sum_bx_times_ay += (tgtPset[i].x - mean_bx)*(a[i].y - mean_ay);
sum_by_times_ax += (tgtPset[i].y - mean_by)*(a[i].x - mean_ax);
sum_bx_times_ax += (tgtPset[i].x - mean_bx)*(a[i].x - mean_ax);
sum_by_times_ay += (tgtPset[i].y - mean_by)*(a[i].y - mean_ay);
}

*dth = atan2(sum_bx_times_ay - sum_by_times_ax, sum_bx_times_ax + sum_by_times_ay);
*dx = mean_ax - ((mean_bx * cos(*dth)) - (mean_by * sin(*dth)));
*dy = mean_ay - ((mean_bx * sin(*dth)) + (mean_by * cos(*dth)));

}

double icp(double* dx, double* dy, double* dth, Point2D* tgtPset, int t_size, Point2D* refPset, int r_size)
{
double error = 0;
double pre_err = 0;
double step_dx, step_dy, step_dth;
double tmp_x, tmp_y;
Point2D* step_tgtPset = (Point2D*)malloc(t_size*sizeof(Point2D));

int i, iter_count;

for(i=0; i < t_size; i++){
step_tgtPset[i] = tgtPset[i];
}

*dx = 0;
*dy = 0;
*dth = 0;
iter_count = 0;
do{
iter_count++;

icp_step(&step_dx, &step_dy, &step_dth, step_tgtPset, t_size, refPset, r_size);

pre_err = error;
error = 0;
for(i=0; i < t_size; i++){
tmp_x = (step_tgtPset[i].x * cos(step_dth)) - (step_tgtPset[i].y * sin(step_dth)) + (step_dx);
tmp_y = (step_tgtPset[i].x * sin(step_dth)) + (step_tgtPset[i].y * cos(step_dth)) + (step_dy);
step_tgtPset[i].x = tmp_x;
step_tgtPset[i].y = tmp_y;

error += (pow(step_tgtPset[i].x - refPset[i].x, 2) + pow(step_tgtPset[i].y - refPset[i].y, 2));
}
error /= t_size;

*dx += step_dx;
*dy += step_dy;
*dth += step_dth;

// just for debug
printf("iter[%d]: err = %lf, dx = %lf, dy = %lf, dth = %lf\n", iter_count, error, *dx, *dy, *dth);
system("pause");
//
} while(fabs(error - pre_err) > 0.00001);

return error;
}


// test_main.c
// just for debug and test

#include "icp.h"
#include < stdlib.h >
#include < math.h >
#include < stdio.h >

double randomNumber(int hi) //the correct random number generator for [0,hi]
{
// scale in range [0,1)
double scale;
scale = (double)rand();
scale /= (double)(RAND_MAX);
// return range [0,hi]
return (scale*hi); // implicit cast and truncation in return
}
void GenerateRandomPointSet(Point2D* pSet, int p_size)
{
int i;
for(i=0; i < p_size; i++){
pSet[i].x = randomNumber(1000);
pSet[i].y = randomNumber(1000);
}
}

void MovePointSet(Point2D* pSet, int p_size, double dx, double dy)
{
int i;
for(i=0; i < p_size; i++){
pSet[i].x += dx;
pSet[i].y += dy;
}
}

void RotatePointSet(Point2D* pSet, int p_size, double dth)
{
int i;
double tmp_x, tmp_y;
for(i=0; i < p_size; i++){
tmp_x = pSet[i].x * cos(dth) - pSet[i].y * sin(dth);
tmp_y = pSet[i].x * sin(dth) + pSet[i].y * cos(dth);
pSet[i].x = tmp_x;
pSet[i].y = tmp_y;
}
}

int main()
{
Point2D tgtPset[1000];
Point2D refPset[1000];
double error;
double dx, dy, dth;

int i;

GenerateRandomPointSet(tgtPset, 1000);

for(i=0; i < 1000; i++){
refPset[i] = tgtPset[i];
}

MovePointSet(tgtPset, 1000, 10, 12);
RotatePointSet(tgtPset, 1000, 0.02);

error = icp(&dx, &dy, &dth, tgtPset, 1000, refPset, 1000);

printf("final result: err = %lf, dx = %lf, dy = %lf, dth = %lf\n", error, dx, dy, dth);
system("pause");
return 0;
}

最後補充幾點值得注意的事情:
1. 這程式碼本身是最單純的 ICP ,完全沒有任何別的加速技巧。
2. 所謂的加速技巧主要有二,其一是如何 down sampling ,因為ICP 需要的運算量很大,如果不做 down sampling ,需要 real time 的 ICP 大概就掛了。
3. 另一加速技巧在於改善點集合的資料結構,其中最有名的適合 ICP 演算法的資料結構是 K-D tree ,因為它的資料格式和距離有關,用 K-D tree 可以在尋找對應點的時候大幅降低運算時間。