ã¤ãã°ãƒãƒ£ãƒ¬ãƒ³ã‚¸2010: レーザスキャナã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³

2010-08-01
By
レーザスキャナã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³

レーザスキャナã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚·ãƒ§ãƒ³

北陽電機ã®ã‚¹ã‚­ãƒ£ãƒŠå¼ãƒ¬ãƒ³ã‚¸ã‚»ãƒ³ã‚µUTM-30LXã®ã‚·ãƒŸãƒ¥ãƒ¬ãƒ¼ã‚¿ã‚’作りã¾ã—ãŸï¼ŽURGã®APIを実装ã—ã¦ã„ãªã„ã®ã§ä¸å®Œå…¨ã§ã™ï¼Žã€€ODEã§ã®RAYジオメトリã®ä½¿ã„æ–¹ã¯å‚考ã«ãªã‚‹ã¨æ€ã„ã¾ã™ï¼Ž

ã“ã“ã‹ã‚‰ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’å–å¾—ã§ãã¾ã™ï¼Žã»ã¨ã‚“ã©ãƒ†ã‚¹ãƒˆã—ã¦ã„ãªã„ã®ã§é–“é•ã„ãŒã‚ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“.無ä¿è¨¼ã§ã™ï¼Žè‡ªç”±ã«ä½¿ã£ã¦ãã ã•ã„.ã“ã“ã‹ã‚‰ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰localization100731.zipをダウンロードã§ãã¾ã™ï¼ŽWindows用Codeblocksã®ãƒ—ロジェクトファイルã—ã‹ã‚りã¾ã›ã‚“.

以下,関係ã®ã‚る部分ã®ã‚½ãƒ¼ã‚¹ã‚³ãƒ¼ãƒ‰ã‚’紹介ã—ã¾ã™ï¼Ž

/*** レーザスキャナã®ä½œæˆ ***/
static void makeLaserScanner()
{
    dMass mass;

    // レーザスキャナ 
    laser.body  = dBodyCreate(world);
    dMassSetZero(&mass);
    dMassSetCylinderTotal(&mass,LASER_M,3,LASER_R, LASER_L);
    dBodySetMass(laser.body,&mass);
    dBodySetPosition(laser.body,START_X, START_Y, START_Z+NECK_L+SENSOR_L+LASER_L/2);

    // レーザビーム.Rayジオメトリã§å®Ÿè£….ボディã¯ãªã„.
    for (int i=0; i < BEAM_NUM; i++)
    {
        beam[i] =  dCreateRay(space, 0);
        dGeomRaySetLength(beam[i], BEAM_LENGTH);
    }
}

/*** レーザー光ã®ç™ºå°„ ***/
static void emitLaser()
{
    dMatrix3 R1, R2, R3, R4, R5;

    const dReal *p = (const dReal *) dBodyGetPosition(laser.body);
    dReal heading_angle = -heading();
    dReal pitch  = dJointGetHingeAngle(laser_joint);

    dRFromAxisAndAngle(R1,1,0,0, -M_PI/2);
    dRFromAxisAndAngle(R4,1,0,0, pitch);

    for (int i=urg.first_index; i < urg.last_index; i+=urg.skip_lines)
    {
        for (int j=0; j < 3; j++)
        {
            contact_pos[i][j] = -1;
        }

        dRFromAxisAndAngle(R2,0,0,1,
                           heading_angle +(double) (i - (BEAM_NUM/2))/(BEAM_NUM/2) * LASER_LO_LIMIT * (M_PI/180));
        dMultiply0(R3,R2,R1,3,3,3);
        dMultiply0(R5,R4,R3,3,3,3);
        dGeomSetPosition(beam[i], p[0], p[1], p[2]);
        dGeomSetRotation(beam[i],R5);
    }
}

/*** ãƒ¬ãƒ¼ã‚¶ã®æç”»ã€€***/
void drawLaser()
{
    const dReal *pos;
    dsSetColorAlpha(1.0, 0.0, 0.0, 0.5);
    static int skip = 6; // æç”»ã‚’高速ã«ã™ã‚‹ãŸã‚ã®é–“å¼•ãæ•°

    pos = dBodyGetPosition(laser.body);
    for (int i = 0; i < BEAM_NUM; i++)
    {
        if (!((contact_pos[i][0] == -1) && (contact_pos[i][1] == -1) &&
                (contact_pos[i][2] == -1)))
        {
            // æç”»ã‚’高速ã«ã™ã‚‹ãŸã‚ã«é–“引ã
            if ((i % skip) == 0)dsDrawLine(pos,(const double *) contact_pos[i]);
        }
    }
}

/*** コールãƒãƒƒã‚¯é–¢æ•° ***/
static void nearCallback (void *data, dGeomID o1, dGeomID o2)
{
    int i,n;
    dBodyID b1 = dGeomGetBody(o1);
    dBodyID b2 = dGeomGetBody(o2);

    if (b1 && b2 && dAreConnectedExcluding(b1,b2,dJointTypeContact)) return;

    static const int N = 10;
    dContact contact[N];
    n = dCollide(o1,o2,N,&contact[0].geom,sizeof(dContact));
    if (n > 0)
    {
        for (i=0; i<n; i++)
        {
            if ((o1 == wheel[FRONT].geom) || (o2 == wheel[FRONT].geom) ||
                    (o1 == wheel[REAR].geom)  || (o2 == wheel[REAR].geom))
            {
                contact[i].surface.mode = dContactSoftERP | dContactSoftCFM | dContactApprox1;
                //contact[i].surface.mode = dContactSoftERP | dContactSoftCFM ;
                contact[i].surface.mu = 0.0; // dInfinity; // 摩擦係数0
                contact[i].surface.soft_erp = 1.0;       // 地é¢ã®ERP
                contact[i].surface.soft_cfm = 1e-5;      // 地é¢ã®CFM
            }
            else
            {
                // レーザビームã®è¡çªåˆ¤å®š
                if (dGeomGetClass(o1) == dRayClass || dGeomGetClass(o2) == dRayClass)
                {
                    for (int k=0; k < BEAM_NUM; k++)
                    {
                        if (o1 == beam[k] || o2 == beam[k])
                        {
                            // 物体をã¤ããªã‘ãªã„ãŸã‚ã«
                            if ((contact_pos[k][0] == -1) && (contact_pos[k][1] == -1)
                                    && (contact_pos[k][2]==-1))
                            {
                                for (int j=0; j < 3; j++)
                                    contact_pos[k][j] = contact[i].geom.pos[j];
                            }
                            else
                            {
                                return; 
                            }
                        }
                    }
                    return; // 接触点を見ã¤ã‘ã‚‹ã ã‘ãªã®ã§æˆ»ã‚‹
                }

                contact[i].surface.mode = // dContactSlip1 | dContactSlip2 |
                    dContactSoftERP | dContactSoftCFM | dContactApprox1 | dContactMu2;
                contact[i].surface.mu  = 1.0; // dInfinity; // 摩擦係数無é™å¤§
                contact[i].surface.slip1    = 0.001;      // 第1摩擦方å‘ã®æ»‘り
                contact[i].surface.slip2    = 0.001;      // 第2摩擦方å‘ã®æ»‘り
                contact[i].surface.soft_erp = 1.0;       // 地é¢ã®ERP
                contact[i].surface.soft_cfm = 1e-5;      // 地é¢ã®CFM
            }
            dJointID c = dJointCreateContact(world,contactgroup,&contact[i]); //接触ジョイントã®ç”Ÿæˆ
            dJointAttach(c,b1,b2);                   // ジョイントã®çµåˆ
        }
    }
}

/*** レーザã®ãƒ‡ãƒ¼ã‚¿å–得 ***/
void laser_receiveData(laser_t *urg, long data[], int data_max)
{
    const dReal *pos;

    pos = dBodyGetPosition(laser.body);
    for (int i = 0; i < BEAM_NUM; i++)
    {
        if (!((contact_pos[i][0] == -1) && (contact_pos[i][1] == -1) &&
                (contact_pos[i][2] == -1)))
        {
            // æç”»ã‚’高速ã«ã™ã‚‹ãŸã‚ã«é–“引ã
            dReal d2 = 0;
            for (int j = 0; j < 3; j++)
            {
                d2 += (pos[j]-contact_pos[i][j]) * (pos[j] - contact_pos[i][j]);
            }
            data[i] = (long) (1000 * sqrt(d2));
            // printf("Laser dist[%d]=%.2f \n",i,laser_dist[i]);
        }
        else
        {
            data[i] = -1;
        }
    }
}

void laser_setSkipLines(laser_t *urg, int skip_lines)
{
    urg->skip_lines = skip_lines;
}

void laser_requestData(laser_t *urg, laser_request_type request_type, int first_index, int last_index)
{
    if ((first_index < 0)||(first_index > BEAM_NUM)|| (first_index > last_index))
    {
        printf("first index error \n");
    }
    else
    {
        urg->first_index = first_index;
    }

    if ((last_index < 0) || (last_index > BEAM_NUM) || (last_index < first_index))
    {
        printf("last index error \n");
    }
    else
    {
        urg->last_index  = last_index;
    }
}

/*** シミュレーションループ ***/
static void simLoop(int pause)
{
    double vel = 10.0;
    static double laser_angle = 0;
    static double diff = 1;

    emitLaser(); // レーザー光発射
    if (!pause)
    {
        controlWheel(v_r, v_l);

        if ((laser_angle >= M_PI/4) || (laser_angle <= - M_PI/4))
        {
            diff *= -1;
        }
        swingLaser(laser_angle += 5.0 * diff * M_PI/180.0);

        deadReckoning();
        //navigation(vel);

        dSpaceCollide(space,0,&nearCallback);
        dWorldQuickStep(world, STEP_SIZE);
        dJointGroupEmpty(contactgroup);
    }

    laser_receiveData(&urg, laser_data,laser_data_max);
    //for (int i=0; i < laser_data_max;i++) {
    //    printf("Laser dist[%d]=%d \n",i,laser_data[i]);
    //}

    //drawParticles();
    drawRobot();
    if (show) drawLaser();
    drawWall();
    steps++;
}

/*** レーザスキャナã®åˆæœŸåŒ– ***/
void initLaser()
{
    laser_data = (long*)malloc(sizeof(long) * laser_data_max);
    if (laser_data == NULL)
    {
        perror("malloc");
        exit(1);
    }
    laser_setSkipLines(&urg,2);
    laser_requestData(&urg, URG_MD, URG_FIRST, URG_LAST);
}

/*** メイン関数 ***/
int main(int argc, char *argv[])
{
    setDrawStuff(); // æç”»é–¢æ•°ã®è¨­å®š
    srand(time(NULL));
    dInitODE();
    world        = dWorldCreate();              // ワールドã®ç”Ÿæˆ
    space        = dHashSpaceCreate(0);         // スペースã®ç”Ÿæˆ
    contactgroup = dJointGroupCreate(0);        // 接触点グループã®ç”Ÿæˆ
    ground       = dCreatePlane(space,0,0,1,0); // 地é¢ã®ç”Ÿæˆ

    dWorldSetGravity(world, 0, 0, -9.8); // é‡åŠ›åŠ é€Ÿåº¦ã®è¨­å®š
    //dWorldSetCFM(world,1e-5); // CFMã®è¨­å®š
    dWorldSetERP(world,1.0);  // ERPã®è¨­å®š 0.8

    makeRobot(); // ロボットã®ç”Ÿæˆ
    makeWall(); // å£ã®ç”Ÿæˆ
    initLaser(); // レーザスキャナã®åˆæœŸåŒ–

    dsSimulationLoop(argc,argv,800,480,&fn); // シミュレーションループ

    dJointGroupDestroy(contactgroup);  // 接触点グループã®ç ´å£Š
    dSpaceDestroy(space);              // スペースã®ç ´å£Š
    dWorldDestroy(world);              // ワールドã®ç ´å£Š
    dCloseODE();
    return 0;
}

コメントをã©ã†ãž

メールアドレスãŒå…¬é–‹ã•れるã“ã¨ã¯ã‚りã¾ã›ã‚“。

437 views  (Since 2010-08-11)