int main(int argc, char *argv[])
{
	int count = 0;
	Vector2d tP_B(Vector2d::Zero());
	double tth_B = 0.0;

	FootStepPlanner plan_node(0.32, 0.04);

	while(1){
		// 一歩分の蹴足位置と目標ZMPを取得
		plan_node.getNextStep(tP_B, tth_B);

		// 停止判定
		if(plan_node.getWalkState() == STOP) break;

		// 指定の歩数歩いたら終了
		count++;
		if(MAX_STEP <= count) plan_node.setStopFlag();

		// 体幹位置を一歩分移動
		tP_B += Vector2d(0.03, 0.03); tth_B += 5.0;
	}

	plan_node.plot_foot_pattern();
}
/**
 * @brief Convert a Postgres ModifyTableState with DELETE operation
 * into a Peloton DeleteNode.
 * @return Pointer to the constructed AbstractPlan.
 *
 * Just like Peloton,
 * the delete plan state in Postgres simply deletes tuples
 * returned by a subplan (mostly Scan).
 * So we don't need to handle predicates locally .
 */
std::unique_ptr<planner::AbstractPlan> PlanTransformer::TransformDelete(
    const ModifyTablePlanState *mt_plan_state, const TransformOptions options) {
  // Grab Database ID and Table ID

  Oid database_oid = mt_plan_state->database_oid;
  Oid table_oid = mt_plan_state->table_oid;

  /* Get the target table */
  storage::DataTable *target_table = static_cast<storage::DataTable *>(
      catalog::Manager::GetInstance().GetTableWithOid(database_oid, table_oid));

  if (target_table == nullptr) {
    LOG_ERROR("Target table is not found : database oid %u table oid %u",
              database_oid, table_oid);
    return nullptr;
  }

  LOG_INFO("Delete :: database oid %u table oid %u: %s", database_oid,
           table_oid, target_table->GetName().c_str());

  // Create the peloton plan node
  bool truncate = false;
  std::unique_ptr<planner::AbstractPlan> plan_node(
      new planner::DeletePlan(target_table, truncate));

  // Add child plan node(s)
  TransformOptions new_options = options;
  new_options.use_projInfo = false;

  auto sub_planstate = mt_plan_state->mt_plans[0];
  auto child_plan_node = TransformPlan(sub_planstate, new_options);

  plan_node.get()->AddChild(std::move(child_plan_node));

  return plan_node;
}
/**
 * @brief Convert a Postgres HashState into a Peloton HashPlanNode
 * @return Pointer to the constructed AbstractPlan
 */
std::unique_ptr<planner::AbstractPlan> PlanTransformer::TransformHashJoin(
    const HashJoinPlanState *hj_plan_state) {
  std::unique_ptr<planner::AbstractPlan> result;
  PelotonJoinType join_type =
      PlanTransformer::TransformJoinType(hj_plan_state->jointype);
  if (join_type == JOIN_TYPE_INVALID) {
    LOG_ERROR("unsupported join type: %d", hj_plan_state->jointype);
    return nullptr;
  }

  LOG_INFO("Handle hash join with join type: %d", join_type);

  /*
  std::vector<planner::HashJoinPlan::JoinClause> join_clauses(
      BuildHashJoinClauses(mj_plan_state->mj_Clauses,
                            mj_plan_state->mj_NumClauses);
  */

  expression::AbstractExpression *join_filter = ExprTransformer::TransformExpr(
      reinterpret_cast<ExprState *>(hj_plan_state->joinqual));

  expression::AbstractExpression *plan_filter = ExprTransformer::TransformExpr(
      reinterpret_cast<ExprState *>(hj_plan_state->qual));

  std::unique_ptr<const expression::AbstractExpression> predicate(nullptr);
  if (join_filter && plan_filter) {
    predicate.reset(expression::ExpressionUtil::ConjunctionFactory(
        EXPRESSION_TYPE_CONJUNCTION_AND, join_filter, plan_filter));
  } else if (join_filter) {
    predicate.reset(join_filter);
  } else {
    predicate.reset(plan_filter);
  }

  /* Transform project info */
  std::unique_ptr<const planner::ProjectInfo> project_info(nullptr);

  project_info.reset(BuildProjectInfoFromTLSkipJunk(hj_plan_state->targetlist));

  if (project_info.get() != nullptr) {
    LOG_INFO("%s", project_info.get()->Debug().c_str());
  } else {
    LOG_INFO("empty projection info");
  }

  std::shared_ptr<const catalog::Schema> project_schema(
      SchemaTransformer::GetSchemaFromTupleDesc(
          hj_plan_state->tts_tupleDescriptor));

  std::vector<oid_t> outer_hashkeys =
      BuildColumnListFromExpStateList(hj_plan_state->outer_hashkeys);

  bool non_trivial = (project_info.get() != nullptr &&
                      project_info.get()->isNonTrivial());
  if (non_trivial) {
    // we have non-trivial projection
    LOG_INFO("We have non-trivial projection");
    result = std::unique_ptr<planner::AbstractPlan>(
        new planner::ProjectionPlan(std::move(project_info), project_schema));
    // set project_info to nullptr
    project_info.reset();
  } else {
    LOG_INFO("We have direct mapping projection");
  }

  std::unique_ptr<planner::HashJoinPlan> plan_node(new planner::HashJoinPlan(
      join_type, std::move(predicate), std::move(project_info), project_schema,
      outer_hashkeys));

  std::unique_ptr<planner::AbstractPlan> outer{std::move(
      PlanTransformer::TransformPlan(outerAbstractPlanState(hj_plan_state)))};
  std::unique_ptr<planner::AbstractPlan> inner{std::move(
      PlanTransformer::TransformPlan(innerAbstractPlanState(hj_plan_state)))};

  /* Add the children nodes */
  plan_node->AddChild(std::move(outer));
  plan_node->AddChild(std::move(inner));

  if (non_trivial) {
    result->AddChild(std::move(plan_node));
  } else {
    result.reset(plan_node.release());
  }

  LOG_INFO("Finishing mapping Hash join, JoinType: %d", join_type);
  return result;
}