test

Dependencies:   mbed ros_lib_kinetic nhk19mr2_can_info splitData SerialHalfDuplex_HM

Walk/Walk.cpp

Committer:
shimizuta
Date:
2019-02-27
Revision:
29:7d8b8011a88d
Parent:
27:79b4b932a6dd
Child:
32:dc684a0b8448

File content as of revision 29:7d8b8011a88d:

#define _USE_MATH_DEFINES
#include "math.h"
#include <stdio.h>
#include "stdlib.h"
#include "Walk.h"
 #include "pi.h"
//Orbitは足毎の軌道をあらわす。
const float kGravity = 9.8;

Orbit::Orbit(OrbitPattern pattern)
{
    pattern_ = pattern;
}
float Orbit::GetOneWalkTime()
{
    float time_s;
    switch (pattern_)
    {
    default:
        time_s = TriangleOrbit::GetOneWalkTime();
        break;
    }
    return time_s;
}
int Orbit::GetOrbit(OneLeg &leg, float phasetime_s)
{
    int ret;
    switch (pattern_)
    {
    default:
        ret = TriangleOrbit::GetOrbit(leg, phasetime_s);
        break;
    }
    return ret;
}

Walk::Walk()
{
    for (int i = 0; i < 4; i++)
        offset_multi_[i] = 0;
}
float Walk::calctime_s_;
int Walk::Cal4LegsPosi(OneLeg leg[4]) //失敗したら1を返す。成功なら0
{
    int is_out = 0;
    for (int i = 0; i < 4; i++)
    {
        float one_walk_time = orbit_[i].GetOneWalkTime();
        phasetime_s_[i] += calctime_s_;
        while (phasetime_s_[i] > one_walk_time)
            phasetime_s_[i] -= one_walk_time;
        if (orbit_[i].GetOrbit(leg[i], phasetime_s_[i]) == 1)
        {
            printf("error:leg %d in Cal4LegsPosi\r\n", i);
            is_out = 1;
        }
    }
    return is_out;
}
float Walk::GetOneWalkTime()
{
    return orbit_[0].GetOneWalkTime(); //4足全て同じ時間のはずなので一例としてorbit_[0]のものを返している.
};
void Walk::SetOffsetTime(float offset_multi0, float offset_multi1, float offset_multi2, float offset_multi3)
{
    offset_multi_[0] = offset_multi0;
    offset_multi_[1] = offset_multi1;
    offset_multi_[2] = offset_multi2;
    offset_multi_[3] = offset_multi3;
}
//軌道がリンク定義外になっていないかチェック。reutn 0:ok 1:out
int Walk::CheckOrbit(OneLeg templateleg)
{
    for (int i = 0; i < 4; i++)
    {
        //軌道が値域の外に出ないか計算で確かめる
        float one_walk_time = GetOneWalkTime();
        int step = one_walk_time / calctime_s_ * 2;
        for (float j = 0; j < one_walk_time; j += step)
        {
            if (orbit_[i].GetOrbit(templateleg, j) == 1)
            {
                printf("error:leg %d, time %f", i, j);
                return 1; //解が出ないときは1を返す
            }
        }
        phasetime_s_[i] = one_walk_time * offset_multi_[i];
    }
    return 0;
}
void Walk::SetOneOrbit(int legnum, Orbit orbit)
{
    orbit_[legnum] = orbit;
}
void Walk::SetAllOrbit(Orbit orbit)
{
    for (int i = 0; i < 4; i++)
        SetOneOrbit(i, orbit);
}
void Walk::SetOneLegStandParam(int legnum,float x_m, float y_m, float time_s)
{
    Orbit triangle(TRIANGLE);
    triangle.SetTriangleParam(x_m, y_m, 0, 0, 0, time_s, 0,0);
    SetOneOrbit(legnum, triangle);
}
void Walk::SetAllLegStandParam(float x_m, float y_m, float time_s) 
{
    for (int i = 0; i < 4; i ++)
        SetOneLegStandParam(i, x_m, y_m, time_s);
}
void Walk::SetOneLegTriangleParam(int legnum, float start_x_m, float start_y_m, float stride_m, float height_m, float buffer_height_m,
                                                                                                     float stridetime_s, float toptime_s, float buffer_time_s)
{
    Orbit triangle(TRIANGLE);
    triangle.SetTriangleParam(start_x_m, start_y_m, stride_m, height_m, buffer_height_m,
                              stridetime_s, toptime_s, buffer_time_s);
    SetOneOrbit(legnum, triangle);
}
void Walk::SetAllLegTriangleParam(float start_x_m, float start_y_m, float stride_m, float height_m, float buffer_height_m,
                                  float stridetime_s, float toptime_s, float buffer_time_s)
{
    for (int i = 0; i < 4; i++)
        SetOneLegTriangleParam(i, start_x_m, start_y_m, stride_m, height_m, buffer_height_m,
                               stridetime_s, toptime_s, buffer_time_s);
}

void TriangleOrbit::SetTriangleParam(float start_x_m, float start_y_m, float stride_m, float height_m, float buffer_height_m,
                                     float stridetime_s, float toptime_s, float buffer_time_s)
{
    reverse_tanbeta_ = 1.0 / tan(81.0 / 180.0 * M_PI); //論文よりこれが最適らしい
    start_x_m_ = start_x_m;
    start_y_m_ = start_y_m;
    stride_m_ = stride_m;
    height_m_ = height_m;               //足上げ幅
    buffer_height_m_ = buffer_height_m; //着地直前で止める高さ
    stridetime_s_ = stridetime_s;
    toptime_s_ = toptime_s;         //頂点に行くまでの時間
    buffer_time_s_ = buffer_time_s; //頂点から一時停止点までの時間.

    //事前に計算しておく
    top_x_m_ = start_x_m_ - height_m * reverse_tanbeta_;
    top_y_m_ = -height_m_ + start_y_m_;
    buffer_x_m_ = start_x_m_ - buffer_height_m_ * reverse_tanbeta_;
    buffer_y_m_ = -buffer_height_m_ + start_y_m_;
}
//足一周の時間
float TriangleOrbit::GetOneWalkTime()
{
    return stridetime_s_ + toptime_s_ + buffer_time_s_;
};
int TriangleOrbit::GetOrbit(OneLeg &leg, float phasetime_s)
{
    int ret = 0;
    if (phasetime_s < stridetime_s_)
        ret = StrideLineAccel_(leg, phasetime_s);
    else if (phasetime_s < stridetime_s_ + toptime_s_)
        ret = leg.SetXY_m(top_x_m_, top_y_m_);
    else
        ret = leg.SetXY_m(buffer_x_m_, buffer_y_m_);
    return ret;
};
int TriangleOrbit::StrideLine_(OneLeg &leg, float phasetime_s)
{
    float x_m = start_x_m_ - stride_m_ * phasetime_s / stridetime_s_;
    float y_m = start_y_m_;
    return leg.SetXY_m(x_m, y_m);
}

int TriangleOrbit::StrideLineAccel_(OneLeg &leg, float phasetime_s)
{
    ///////////x,yを計算
    float s0 = start_x_m_;
    float s1 = start_x_m_ - stride_m_;
    float g_h = sqrtf(kGravity / start_y_m_);
    float t = phasetime_s / stridetime_s_;
    float denominator = expf(g_h) - expf(-g_h); //分母

    float x_m = -(s0 * expf(-g_h) - s1) * expf(g_h * t) / denominator + (s0 * expf(g_h) - s1) * expf(-g_h * t) / denominator;
    float y_m = start_y_m_;
    //x,yを代入
    return leg.SetXY_m(x_m, y_m);
}