C言語関係掲示板

過去ログ

No.318.ロボットの移動経路

[戻る] [ホームページ]

No.1975

はじめまして。ロボットの移動経路についての質問なんですけど。
投稿者---さとる(2002/07/05 18:53:07)


ポテンシャル法で移動経路を作成せよ。という課題で障害物の表現はビクターマップを使ってなんとか表現できたんですけど肝心のポテンシャル法がうまくできないで困ってます。授業でもらったプリントを参考にして作成せよっていう事なんですけど何をつけたしたらいいか全くわかりません。

授業でもらったプリントの内容を下に書きます。

ポテンシャル法


障害物までの距離


double distance_to_object
(int idx, double rx, double ry,
double *ptx, double *pty)
{
double tmp_len, tmp_x, tmp_y, len, x, y;
int i;
len = 999.0;
for (i=1; i < obj[idx].vtx; i++) {
tmp_len =
distance_to_segment(
obj[idx].x[i-1], obj[idx].y[i-1],
obj[idx].x[i ], obj[idx].y[i ],
rx, ry, &tmp_x, &tmp_y);
if (len > tmp_len) {
x = tmp_x;
y = tmp_y;
len = tmp_len;
}
}
*ptx = x;
*pty = y;
return len;
}



点と線分の距離


double distance_to_segment
(double sx, double sy,
double ex, double ey,
double orgx, double orgy,
double *ptx, double *pty)
{
double vec_x, vec_y, alpha, mx, my, len;
vec_x = ex-sx;
vec_y = ey-sy;
alpha = ( vec_x * orgx + vec_y * orgy
-vec_x * sx - vec_y * sy) /
(vec_x * vec_x + vec_y * vec_y);
mx = sx + vec_x * alpha;
my = sy + vec_y * alpha;
if (alpha < 0.0) {
len = calc_segment_length(sx, sy, orgx, orgy);
*ptx = sx;
*pty = sy;
}
else if (alpha > 1.0) {
len = calc_segment_length(ex, ey, orgx, orgy);
*ptx = ex;
*pty = ey;
}
else {
len = calc_segment_length(mx, my, orgx, orgy);
*ptx = mx;
*pty = my;
}
return len;
}



ベクトルの正規化


void vector_normalize(double vx, double vy,
double *nx, double *ny)
{
double tmp;
tmp = sqrt(vx * vx + vy * vy);
*nx = vx / tmp;
*ny = vy / tmp;
}


以上がそうです。長くて大変すみません。うち間違えてないと思います。申し訳なんですけどどなたか教えていただけるとありがたいです。


No.1989

Re:はじめまして。ロボットの移動経路についての質問なんですけど。
投稿者---かずま(2002/07/07 02:49:27)


ポテンシャル法がどういうものか全く分かりませんが、プログラムから察するところ
ロボットが多角形の複数の障害物からできるだけ遠ざかるように移動するものだと
解釈して適当に書いてみました。本当に、全く的をはずしているかもしれません。
そのときはご容赦ください。
#include <stdio.h>
#include <math.h>

#define N        3     /* 障害物(object)の個数 */
#define MAXVTX  10     /* 障害物の頂点(vertex)の最大数 */

typedef struct Object {
    int    vtx;        /* 頂点の数 + 1 */
    double x[MAXVTX];  /* 頂点の x座標 */
    double y[MAXVTX];  /* 頂点の y座標 */
} Object;

Object obj[N] = {
    { 3+1, { 0., 0., -1., 0. }, { 1.,  2.,  1.,  1. } },  /* 三角形 */
    { 3+1, { -.5, 0., .5, 0. }, { -1., -2., -1., -1.} },  /* 三角形 */
    { 4+1, { 1., 2., 2., 1., 1. }, { 0.,  0., 1., 1.,  0. } },  /* 四角形 */
};

double calc_segment_length(double x1, double y1, double x2, double y2)
{
    double x = x2 - x1, y = y2 - y1;
    return sqrt(x * x + y * y);
}

double distance_to_segment(double sx, double sy, double ex, double ey, 
    double orgx, double orgy, double *ptx, double *pty)
{
    double vec_x, vec_y, alpha, mx, my, len; 
    vec_x = ex-sx;
    vec_y = ey-sy;
    alpha = (vec_x * orgx + vec_y * orgy - vec_x * sx - vec_y * sy)
        / (vec_x * vec_x + vec_y * vec_y);
    mx = sx + vec_x * alpha;
    my = sy + vec_y * alpha;
    if (alpha < 0.0) {
        len = calc_segment_length(sx, sy, orgx, orgy);
        *ptx = sx; 
        *pty = sy;
    }
    else if (alpha > 1.0) {
        len = calc_segment_length(ex, ey, orgx, orgy);
        *ptx = ex; 
        *pty = ey;
    }
    else {
        len = calc_segment_length(mx, my, orgx, orgy);
        *ptx = mx; 
        *pty = my;
    }
    return len;
}

double distance_to_object(
    int idx, double rx, double ry, double *ptx, double *pty)
{
    double tmp_len, tmp_x, tmp_y, len, x, y;
    int i;
    len = 999.0;
    for (i=1; i < obj[idx].vtx; i++) {
        tmp_len = distance_to_segment(obj[idx].x[i-1], obj[idx].y[i-1], 
            obj[idx].x[i], obj[idx].y[i], rx, ry, &tmp_x, &tmp_y); 
        if (len > tmp_len) {
            x = tmp_x; 
            y = tmp_y; 
            len = tmp_len; 
        }
    }
    *ptx = x;
    *pty = y;
    return len;
}

void vector_normalize(double vx, double vy, double *nx, double *ny)
{
    double tmp;
    tmp = sqrt(vx * vx + vy * vy);
    *nx = vx / tmp;
    *ny = vy / tmp;
}

int main()
{
    double tx, ty;  /* 障害物までの最短点の座標     */
    double len;     /* 障害物までの最短点までの距離 */
    double vx, vy;  /* ロボットの進むべき方向       */
    double nx, ny;  /* 速度 1 の場合の進むべき方向  */
    double rx, ry;  /* ロボットの座標               */
    int t, i;

    rx = ry = 0;
    for (t = 0; t < 10; t++) {
        vx = vy = 0;
        for (i = 0; i < N; i++) {
            len = distance_to_object(i, rx, ry, &tx, &ty);
            vx += (rx - tx) / len; 
            vy += (ry - ty) / len; 
        }
        vector_normalize(vx, vy, &nx, &ny);
        rx += nx;
        ry += ny;
        printf("t=%d: rx = %g, ry = %g\n", t, rx, ry);
    }
    return 0;
}


No.2011

かずまさんへ
投稿者---さとる(2002/07/08 17:06:43)


かずまさんへ。ありがとうございます。今からやってみます。明日どうなったかここに報告します・

No.2012

かずまさんへ
投稿者---さとる(2002/07/08 17:28:29)


かくのわすれてました。障害物は下のように表現したのですけどかずまさんに作っていただいたプログラムとどうやって組み合わせたらいいのですか?あまりC言語に詳しくないのですいません。

// Vector Map

#include <stdio.h>
#include <math.h>
#include "Eg_gdk.c"
#define OBJ_MAX 10
int obj_num;
struct _obj_st {
double x[30], y[30];
int vtx;
} obj[OBJ_MAX];

void EG_main(void)
{
int i, j;
int tmp_x[30], tmp_y[30];
for (i=0; i<obj_num; i++) {
for (j=0; j<30; j++) {
tmp_x[j] = (int)obj[i].x[j];
tmp_y[j] = (int)obj[i].y[j];
}
EG_polygon_fill(obj[i].vtx,tmp_x,tmp_y,EG_GLAY);
}
}
int main(int argc, char *argv[])
{
FILE *fp;
int i, j;
fp = fopen("vec_env.dat", "r");
fscanf(fp, "%d", &obj_num);
for (i=0; i<obj_num; i++) {
fscanf(fp, "%d", &obj[i].vtx);
for (j=0; j<obj[i].vtx; j++) {
fscanf(fp, "%lf %lf",
&obj[i].x[j], &obj[i].y[j]);
}
}
fclose(fp);
EG_init(argc, argv);
EG_main();
EG_start();
return 0;
}
//

2
5
110.0 110.0
110.0 150.0
200.0 150.0
200.0 110.0
110.0 110.0
4
180.0 180.0
180.0 230.0
260.0 190.0
180.0 180.0






No.2013

すみません勘違いしてました。
投稿者---さとる(2002/07/08 19:49:56)


ロボットの移動経路というのはスタートとゴールを決めて障害物をポテンシャル法によって避けてロボットがゴールまでいくというものでした。ポテンシャル法というのは引力斥力ベクトルを計算してゴールまでいくというものです。うまくいえないのですけど引力はゴールに向かっていくもので斥力は障害物から避けるものだと思います。書いているぼくもよくわからないのですが・・。かずまさん問題を明確にしてなくてすみませんでした。
今必死に考えているのですけどどうやって表現したらよいかわかりません。

No.2014

Re:すみません勘違いしてました。
投稿者---かずま(2002/07/09 00:15:47)


> ロボットの移動経路というのはスタートとゴールを決めて障害物をポテンシャル法によって避けてロボットがゴールまで
> いくというものでした。ポテンシャル法というのは引力斥力ベクトルを計算してゴールまでいくというものです。

スタートとゴールの座標は?
それから、引力が強くないと、障害物との斥力によって、ゴールからどんどん離れて
いってしまうのではないでしょうか。
とりあえず、ロボットと障害物の質量は 1 とし、ゴールの質量を大きく取ることに
よって、引力を強くしてみました。
#include <stdio.h>
#include <math.h>

#define N        2     /* 障害物(object)の個数 */
#define MAXVTX   30    /* 障害物の頂点(vertex)の最大数 + 1 */

#define SX    300.0    /* スタートの x 座標 */
#define SY    200.0    /* スタートの y 座標 */
#define GX     80.0    /* ゴールの x 座標 */
#define GY    120.0    /* ゴールの y 座標 */
#define M     100.0    /* ゴールの質量 */

typedef struct Object {
    int    vtx;        /* 頂点の数 + 1 */
    double x[MAXVTX];  /* 頂点の x座標 */
    double y[MAXVTX];  /* 頂点の y座標 */
} Object;

Object obj[N] = {
    { 4+1, { 110, 110, 200, 200, 110 }, { 110,  150, 150, 110,  110 } },
    { 3+1, { 180, 180, 260, 180 }, { 180, 230, 190, 180 } },
};

int main()
{
    double tx, ty;  /* 障害物までの最短点の座標    */
    double len;     /* 障害物の最短点までの距離    */
    double vx, vy;  /* ロボットの進むべき方向      */
    double nx, ny;  /* 速度 1 の場合の進むべき方向 */
    double rx, ry;  /* ロボットの座標              */
    int t = 0, i;

    rx = SX; ry = SY;
    printf("%4d: (%8.3f,%8.3f)\n", t, rx, ry);
    for (t = 1; t < 1000; t++) {
        len = calc_segment_length(GX, GY, rx, ry); /* ゴールまでの距離 */
        if (len < 1) break;
        vx = M * (GX - rx) / (len * len);
        vy = M * (GY - ry) / (len * len);
        for (i = 0; i < N; i++) {
            len = distance_to_object(i, rx, ry, &tx, &ty);
            vx += (rx - tx) / (len * len); 
            vy += (ry - ty) / (len * len); 
        }
        vector_normalize(vx, vy, &nx, &ny);
        rx += nx;
        ry += ny;
        printf("%4d: (%8.3f,%8.3f)\n", t, rx, ry);
    }
    printf("%4d: (%8.3f,%8.3f)\n", t, GX, GY);
    return 0;
}


No.2023

ほんとにありがとうございます。
投稿者---さとる(2002/07/09 16:21:11)


>スタートとゴールの座標は?
>それから、引力が強くないと、障害物との斥力によって、ゴールからどんどん離れていってしまうのではないでしょうか。
>とりあえず、ロボットと障害物の質量は 1 とし、ゴールの質量を大きく取ることに
>よって、引力を強くしてみました。

丁寧にありがとうございます。スタートとゴールの座標はプログラムの中で自分で決めます。引力と斥力についてはベクトルで表します。そしてその引力ベクトルと斥力ベクトルを合成したものがロボットが次に進む座標です。だから質量は考えなくてよいとおもいます。引力ベクトルはaxとayで表すとして斥力ベクトルをvxとvyで表してそれらを足したものが次の座標です。つまりcx=ax+vx,cy=ay+vyとなります。cx,cyはロボットが進む座標です。引力ベクトルは(ゴールの座標ーロボットの座標(はじめはスタートの座標)/lenで斥力ベクトルは(最も近い障害物の座標ーロボットの座標)/lenで表現できるみたいです。
 この課題となっているのは実際に2つ障害物があってスタートからゴールまで線で結ばれるのを2Dグラフィックで表現することです。これもかいてなくてすみません。だからベクターマップをつかわなければ表現できないみたいです。ベクターマップは前の投稿にかいてます。ベクターマップはプログラムを見ていただければわかるとおもうのですがvec_env.datにプログラム中の//のあとの数値を入れて障害物を表現します。
 今僕がゆったことは口ではいえるのですがプログラムに直すことができません。スタートからゴールまでを線で表現するのもどうやったらよいかわかりません。配列を使うらしいのですが・・。もしよければ教えていただいていいですか?大変迷惑をかけてすみません。

No.2024

Re:ほんとにありがとうございます。
投稿者---さとる(2002/07/09 16:35:00)


この前のぼくがかいたのは三角形があったので長方形に訂正します。ポテンシャル法は三角形だとできないみたいなんで。これをvec_env.datのなかに入れます。たびたびすいません。

2
5
110.0 110.0
110.0 150.0
200.0 150.0
200.0 110.0
110.0 110.0
5
180.0 180.0
180.0 230.0
260.0 230.0
260.0 180.0
180.0 180.0






No.2026

今自分でプログラムを作ってみました。だけどコンパイルできませんでした。
投稿者---さとる(2002/07/09 20:56:58)


 多分基本構造はこんな感じだと思います。下にコンパイルしたときのエラー内容をのせました。エラー内容がよくわからないんですが。
 今障害物が1つの場合で作ってみました(実際は2つの場合で作らないといけないのですがとりあえず1つの場合で作ってみようと思いました)。障害物が2つの場合は障害物の斥力が次のようになるからよくわかりませんでした。2つの障害物を障害物1と障害物2として障害物の斥力は、障害物1の斥力と障害物2の斥力を合成したものになるからです。障害物の斥力をvxとしたらvx=vx1+vx2,vy=vy1+vy2となってvx1とかvx2の求め方がよくわかりませんでした。

#include <stdio.h>
#include <math.h>
#include "Eg_gdk.c"
#define OBJ_MAX 10
int obj_num;
struct _obj_st {
double x[30], y[30];
int vtx;
} obj[OBJ_MAX];

void EG_main(void)
{
int i, j, k, count,a ,b;
int tmp_x[30], tmp_y[30];
for (i=0; i<obj_num; i++) {
for (j=0; j<30; j++) {
tmp_x[j] = (int)obj[i].x[j];
tmp_y[j] = (int)obj[i].y[j];
}
EG_polygon_fill(obj[i].vtx,tmp_x,tmp_y,EG_GLAY);
//21行目
for(0 <= k <count; k=0; k++);{
EG_line(a[k],b[k],a[k+1],b[k+1],EG_RED);
}
}
}

double calc_segment_length(double x1, double y1, double x2, double y2)
{
double x = x2 - x1, y = y2 - y1;
return sqrt(x * x + y * y);
}

double distance_to_segment(double sx, double sy, double ex, double ey,
double orgx, double orgy, double *ptx, double *pty)
{
double vec_x, vec_y, alpha, mx, my, len;
vec_x = ex-sx;
vec_y = ey-sy;
alpha = (vec_x * orgx + vec_y * orgy - vec_x * sx - vec_y * sy)
/ (vec_x * vec_x + vec_y * vec_y);
mx = sx + vec_x * alpha;
my = sy + vec_y * alpha;
if (alpha < 0.0) {
len = calc_segment_length(sx, sy, orgx, orgy);
*ptx = sx;
*pty = sy;
}
else if (alpha > 1.0) {
len = calc_segment_length(ex, ey, orgx, orgy);
*ptx = ex;
*pty = ey;
}
else {
len = calc_segment_length(mx, my, orgx, orgy);
*ptx = mx;
*pty = my;
}
return len;
}

double distance_to_object(
int idx, double rx, double ry, double *ptx, double *pty)
{
double tmp_len, tmp_x, tmp_y, len, x, y;
int i;
len = 999.0;
for (i=1; i < obj[idx].vtx; i++) {
tmp_len = distance_to_segment(obj[idx].x[i-1], obj[idx].y[i-1],
obj[idx].x[i], obj[idx].y[i], rx, ry, &tmp_x, &tmp_y);
if (len > tmp_len) {
x = tmp_x;
y = tmp_y;
len = tmp_len;
}
}
*ptx = x;
*pty = y;
return len;
}

int smain(void)
{
double ptx, pty, vx, vy, len2, count, k, a, b, i; /* ptx,ptyは障害までの最短点の座標 */
/* vx,vyはロボットの座標と障害物との斥力*/
double len; /* 障害物までの最短点までの距離 */
double rx, ry; /* ロボットの座標とゴールとの引力 */
double nx, ny; /* ロボットの座標 */
double sx,sy; /* スタートのx座標 y座標*/
double gx,gy; /* ゴールのx座標 y座標 */
sx = 20.0;
sy = 20.0;
gx = 300.0;
gy = 300.0;
k=0;
count=0;
nx=sx,ny=sy;
//98行目
while(nx != gx && ny != gy);
{
len = distance_to_object(i, rx, ry, &ptx, &pty);
vx = (nx - ptx) / len;
vy = (ny - pty) / len;
len2 = calc_segment_length(gx,gy,nx,ny); /*ゴールまでの距離*/
rx = (gx - nx) / len2;
ry = (gy - ny) / len2;
nx = vx + rx;
ny = vy + ry;
a[k] = nx;
b[k] = ny;       
k = k+1
count = count + 1;
}
}

int main(int argc, char *argv[])
{
FILE *fp;
int i, j;
fp = fopen("vec_env.dat", "r");
fscanf(fp, "%d", &obj_num);
for (i=0; i<obj_num; i++) {
fscanf(fp, "%d", &obj[i].vtx);
for (j=0; j<obj[i].vtx; j++) {
fscanf(fp, "%lf %lf",
&obj[i].x[j], &obj[i].y[j]);
}
}
fclose(fp);
smain();
EG_init(argc, argv);
EG_main();
EG_start();
return 0;
}


//vec_env.datの中身

1
5
110.0 110.0
110.0 150.0
200.0 150.0
200.0 110.0
110.0 110.0

//エラー
c:\mingw32\Eg_gdk_2D>gcc a.c %GDKLIB% -o a

.c: In function `EG_main':
.c:23: subscripted value is neither array nor pointer
.c:23: subscripted value is neither array nor pointer
.c:23: subscripted value is neither array nor pointer
.c:23: subscripted value is neither array nor pointer
.c: In function `smain':
.c:109: subscripted value is neither array nor pointer
.c:110: subscripted value is neither array nor pointer
.c:110: parse error before character 0201
c: In function `EG_main':
c:23: subscripted value is neither array nor pointer
c:23: subscripted value is neither array nor pointer
c:23: subscripted value is neither array nor pointer
c:23: subscripted value is neither array nor pointer
c: In function `smain':
c:109: subscripted value is neither array nor pointer
c:110: subscripted value is neither array nor pointer
c:110: parse error before character 0201


No.2032

エラーの意味がわからないときは…
投稿者---差猫(2002/07/10 01:29:09)


日本で使うコンパイラなら日本語でエラーメッセージを出してほしいものですが
メッセージが英語で意味がわからないときは翻訳サイトを使ってみるのも手です。

subscripted value is neither array nor pointer
を翻訳したら
「サブ台本通りの値は配列でもポインターでもありません。」
と出ました。
要するに
「この行で使われている値は配列でもないしポインタでもない。正しく宣言されてるかどうかいっぺん調べてみりん。」
ということだと思います。


翻訳サイト
http://www.excite.co.jp/world/text/


No.2046

かずまさんへ
投稿者---さとる(2002/07/10 17:56:23)


なんとか配列を定義してなかったので定義してコンパイルはできたのですけど実行ができません!引力と斥力の記述がちがっているのでしょうか?あとベクトルの正規化の意味がよくわかりません。もしよければ教えてください。