test

Dependencies:   mbed ros_lib_kinetic nhk19mr2_can_info splitData SerialHalfDuplex_HM

Revision:
29:7d8b8011a88d
Parent:
27:79b4b932a6dd
Child:
32:dc684a0b8448
--- a/Walk/Walk.cpp	Wed Feb 27 01:25:01 2019 +0000
+++ b/Walk/Walk.cpp	Wed Feb 27 12:16:18 2019 +0000
@@ -6,145 +6,6 @@
  #include "pi.h"
 //Orbitは足毎の軌道をあらわす。
 const float kGravity = 9.8;
-void EllipseOrbit::SetParam(float stridetime_s, float risetime_s,
-                            float stride_m, float height_m, float ground_m,
-                            float ellipsecenter_x_m, float ellipsecenter_y_m)
-{
-    stridetime_s_ = stridetime_s;
-    risetime_s_ = risetime_s;
-    stride_m_ = stride_m;
-    height_m_ = height_m;
-    ground_m_ = ground_m;
-    ellipsecenter_x_m_ = ellipsecenter_x_m;
-    ellipsecenter_y_m_ = ellipsecenter_y_m;
-}
-
-//着地中の動き.直線軌道.等速
-int EllipseOrbit::StrideLine_(OneLeg &leg, float phasetime_s)
-{
-    float x_m = -stride_m_ * phasetime_s / stridetime_s_ + stride_m_ * 0.5 + ellipsecenter_x_m_;
-    float y_m = ellipsecenter_y_m_;
-    return leg.SetXY_m(x_m, y_m);
-}
-int EllipseOrbit::StrideLineAccel_(OneLeg &leg, float phasetime_s)
-{
-    ///////////x,yを計算
-    float s0 = stride_m_ * 0.5 + ellipsecenter_x_m_;
-    float s1 = -stride_m_ * 0.5 + ellipsecenter_x_m_;
-    float g_h = sqrtf(kGravity / ground_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 = ground_m_;
-    //x,yを代入
-    return leg.SetXY_m(x_m, y_m);
-}
-//空中の動き.半分にきれいに切れる楕円軌道
-int EllipseOrbit::RiseEllipse_(OneLeg &leg, float phasetime_s)
-{
-    float rad = M_PI * (phasetime_s - stridetime_s_) / risetime_s_ + M_PI;
-    float x_m = stride_m_ * 0.5 * cosf(rad) + ellipsecenter_x_m_;
-    float y_m = height_m_ * sinf(rad) + ellipsecenter_y_m_;
-    return leg.SetXY_m(x_m, y_m);
-}
-//空中の動き.完全に半分には切れない楕円軌道
-int EllipseOrbit::RiseEllipse2_(OneLeg &leg, float phasetime_s)
-{
-    ///////////x,yを計算
-    float ellipselong_m = stride_m_ * 0.5 / cosf(asinf(ground_m_ - ellipsecenter_y_m_));
-    float ellipseshort_m = 2 * (height_m_ - ground_m_ + ellipsecenter_y_m_);
-    float theta1 = acosf(stride_m_ / ellipselong_m * 0.5);      //stride の始まりの位置の角度(数学基準)
-    float theta2 = acosf(-stride_m_ / ellipselong_m * 0.5);     //stride の終わりの位置の角度(数学基準)
-    float omega = (2 * M_PI - theta2 + theta1) / risetime_s_;   //楕円軌道における角速度、一定の値とする(適当)
-    float rad = (phasetime_s - stridetime_s_) * omega + theta2; //角度の基準はtheta1とする(適当)
-    float x_m = ellipselong_m * cos(rad) + ellipsecenter_x_m_;
-    float y_m = ellipseshort_m * sin(rad) + ellipsecenter_y_m_;
-    //x,yを代入
-    return leg.SetXY_m(x_m, y_m);
-}
-//楕円軌道
-int EllipseOrbit::GetOrbit(OneLeg &leg, float phasetime_s)
-{
-    if (phasetime_s < stridetime_s_)
-        return StrideLine_(leg, phasetime_s);
-    else
-        return RiseEllipse_(leg, phasetime_s);
-}
-float EllipseOrbit::GetOneWalkTime()
-{
-    return stridetime_s_ + risetime_s_;
-}
-void EllipseOrbit::ChangeOneParam(EllipseParams param, float val)
-{
-    switch (param)
-    {
-    case STRIDE_M:
-        stride_m_ = val;
-        break;
-    case HEIGHT_M:
-        height_m_ = val;
-        break;
-    case GROUND_M:
-        ground_m_ = val;
-        break;
-    case ELLIPSE_CENTER_X_M:
-        ellipsecenter_x_m_ = val;
-        break;
-    case ELLIPSE_CENTER_Y_M:
-        ellipsecenter_y_m_ = val;
-        break;
-    }
-}
-void FreeLineOrbit::SetFreeLinesParam(LineParam lineparams[], int point_num)
-{
-    point_num_ = point_num;
-    if (point_num_ == 1)
-    {
-        printf("error:point_num = 1. You should put >=2 to make line.");
-        while (1)
-            ;
-    }
-    for (int i = 0; i < point_num_; i++)
-        lineparams_[i] = lineparams[i];
-}
-int FreeLineOrbit::GetOrbit(OneLeg &leg, float phasetime_s)
-{
-    ;
-    //現在の最終到達pointを決定
-    int arrived_point;
-    float sum_time = 0;
-    for (arrived_point = 0; arrived_point < point_num_ - 2; arrived_point++) //arrived_point = point_num-1(これが配列の最大index)の状態で終わらないように-2している
-    {
-        sum_time += lineparams_[arrived_point].time_s;
-        if (phasetime_s < sum_time)
-            break;
-    }
-    //x,yを計算
-    float x_m, y_m;
-    x_m = lineparams_[arrived_point].x_m +
-          (lineparams_[arrived_point + 1].x_m - lineparams_[arrived_point].x_m) * phasetime_s / lineparams_[arrived_point].time_s;
-    y_m = lineparams_[arrived_point].y_m +
-          (lineparams_[arrived_point + 1].y_m - lineparams_[arrived_point].y_m) * phasetime_s / lineparams_[arrived_point].time_s;
-    return leg.SetXY_m(x_m, y_m);
-}
-float FreeLineOrbit::GetOneWalkTime() //足一周の時間
-{
-    float sum_time = 0;
-    for (int i = 0; i < point_num_; i++)
-        sum_time += lineparams_[i].time_s;
-    return sum_time;
-}
-void FreeLineOrbit::SetStandParam(float x_m, float y_m, float time_s)
-{
-    point_num_ = 1;
-    lineparams_[0].x_m = x_m;
-    lineparams_[0].y_m = y_m;
-    lineparams_[0].time_s = time_s;
-    lineparams_[1].x_m = x_m;
-    lineparams_[1].y_m = y_m;
-    lineparams_[1].time_s = 0;
-}
 
 Orbit::Orbit(OrbitPattern pattern)
 {
@@ -155,12 +16,8 @@
     float time_s;
     switch (pattern_)
     {
-    case FREELINES:
-        time_s = FreeLineOrbit::GetOneWalkTime();
-        break;
-
     default:
-        time_s = EllipseOrbit::GetOneWalkTime();
+        time_s = TriangleOrbit::GetOneWalkTime();
         break;
     }
     return time_s;
@@ -170,11 +27,8 @@
     int ret;
     switch (pattern_)
     {
-    case FREELINES:
-        ret = FreeLineOrbit::GetOrbit(leg, phasetime_s);
-        break;
     default:
-        ret = EllipseOrbit::GetOrbit(leg, phasetime_s);
+        ret = TriangleOrbit::GetOrbit(leg, phasetime_s);
         break;
     }
     return ret;
@@ -186,22 +40,28 @@
         offset_multi_[i] = 0;
 }
 float Walk::calctime_s_;
-void Walk::Cal4LegsPosi(OneLeg leg[4])
+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;
-        orbit_[i].GetOrbit(leg[i], phasetime_s_[i]);
+        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::SetOffset(float offset_multi0, float offset_multi1, float offset_multi2, float offset_multi3)
+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;
@@ -219,7 +79,10 @@
         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];
     }
@@ -234,21 +97,86 @@
     for (int i = 0; i < 4; i++)
         SetOneOrbit(i, orbit);
 }
-
-void Walk::ChangeOneParam(int legnum, EllipseParams param, float val)
+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) 
 {
-    orbit_[legnum].ChangeOneParam(param, val);
+    for (int i = 0; i < 4; i ++)
+        SetOneLegStandParam(i, x_m, y_m, time_s);
 }
-void Walk::SetAllLegEllipseParam(float stridetime_s, float risetime_s,
-                                 float stride_m, float height_m, float ground_m,
-                                 float ellipsecenter_x_m, float ellipsecenter_y_m)
+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++)
-        orbit_[i].SetParam(stridetime_s, risetime_s, stride_m, height_m, ground_m, ellipsecenter_x_m, ellipsecenter_y_m);
+        SetOneLegTriangleParam(i, start_x_m, start_y_m, stride_m, height_m, buffer_height_m,
+                               stridetime_s, toptime_s, buffer_time_s);
 }
-void Walk::SetAllLegStandParam(float x_m, float y_m, float 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)
 {
-    Orbit stand(FREELINES);
-    stand.SetStandParam(x_m, y_m, time_s); //defaultとなる軌道設定
-    SetAllOrbit(stand);                    //4足にコピー
+    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);
+}
\ No newline at end of file