double footstepHeuristicStraight( SolverNode<FootstepState, FootstepGraph>::Ptr node, FootstepGraph::Ptr graph) { FootstepState::Ptr state = node->getState(); FootstepState::Ptr goal = graph->getGoal(state->getLeg()); Eigen::Vector3f state_pos(state->getPose().translation()); Eigen::Vector3f goal_pos(goal->getPose().translation()); return (std::abs((state_pos - goal_pos).norm() / graph->maxSuccessorDistance())); }
double footstepHeuristicFollowPathLine( SolverNode<FootstepState, FootstepGraph>::Ptr node, FootstepGraph::Ptr graph) { FootstepState::Ptr state = node->getState(); FootstepState::Ptr goal = graph->getGoal(state->getLeg()); Eigen::Vector3f goal_pos(goal->getPose().translation()); Eigen::Vector3f state_pos(state->getPose().translation()); Eigen::Vector3f state_mid_pos; if (state->getLeg() == jsk_footstep_msgs::Footstep::LEFT) { Eigen::Vector3f p(0, -0.1, 0); state_mid_pos = state->getPose() * p; } else { // Right Eigen::Vector3f p(0, 0.1, 0); state_mid_pos = state->getPose() * p; } double dist, to_goal, alp; int idx; Eigen::Vector3f foot; dist = graph->heuristic_path_->distanceWithInfo(state_mid_pos, foot, to_goal, idx, alp); //jsk_recognition_utils::FiniteLine::Ptr ln = graph->heuristic_path_->at(idx); Eigen::Vector3f dir = graph->heuristic_path_->getDirection(idx); Eigen::Quaternionf path_foot_rot; path_foot_rot.setFromTwoVectors(state->getPose().matrix().block<3, 3>(0, 0) * Eigen::Vector3f::UnitX(), dir); double path_foot_theta = acos(path_foot_rot.w()) * 2; if (path_foot_theta > M_PI) { path_foot_theta = 2.0 * M_PI - path_foot_theta; // foot_theta : [0, M_PI] } double step_cost = to_goal / graph->maxSuccessorDistance(); double follow_cost = dist / 0.02; // ??? double path_foot_rot_cost = path_foot_theta / graph->maxSuccessorRotation(); Eigen::Vector3f goal_diff = goal_pos - state_pos; Eigen::Quaternionf goal_foot_rot; goal_foot_rot.setFromTwoVectors(state->getPose().matrix().block<3, 3>(0, 0) * Eigen::Vector3f::UnitX(), goal->getPose().matrix().block<3, 3>(0, 0) * Eigen::Vector3f::UnitX()); double goal_foot_theta = acos(goal_foot_rot.w()) * 2; if (goal_foot_theta > M_PI) { goal_foot_theta = 2.0 * M_PI - goal_foot_theta; } double goal_foot_rot_cost = goal_foot_theta / graph->maxSuccessorRotation(); //return step_cost + follow_cost + (4.0 * goal_foot_rot_cost) + (0.5 * path_foot_rot_cost); return 2*(step_cost + follow_cost + (0.5 * path_foot_rot_cost)); }
double footstepHeuristicStepCost( SolverNode<FootstepState, FootstepGraph>::Ptr node, FootstepGraph::Ptr graph, double first_rotation_weight, double second_rotation_weight) { FootstepState::Ptr state = node->getState(); FootstepState::Ptr goal = graph->getGoal(state->getLeg()); Eigen::Vector3f goal_pos(goal->getPose().translation()); Eigen::Vector3f diff_pos(goal_pos - state->getPose().translation()); diff_pos[2] = 0.0; // Ignore z distance Eigen::Quaternionf first_rot; // Eigen::Affine3f::rotation is too slow because it calls SVD decomposition first_rot.setFromTwoVectors(state->getPose().matrix().block<3, 3>(0, 0) * Eigen::Vector3f::UnitX(), diff_pos.normalized()); Eigen::Quaternionf second_rot; second_rot.setFromTwoVectors(diff_pos.normalized(), goal->getPose().matrix().block<3, 3>(0, 0) * Eigen::Vector3f::UnitX()); // is it correct?? double first_theta = acos(first_rot.w()) * 2; double second_theta = acos(second_rot.w()) * 2; if (isnan(first_theta)) { first_theta = 0; } if (isnan(second_theta)) { second_theta = 0; } // acos := [0, M_PI] if (first_theta > M_PI) { first_theta = 2.0 * M_PI - first_theta; } if (second_theta > M_PI) { second_theta = 2.0 * M_PI - second_theta; } //return (Eigen::Vector2f(diff_pos[0], diff_pos[1]).norm() / graph->maxSuccessorDistance()) + std::abs(diff_pos[2]) / 0.2 + return (diff_pos.norm() / graph->maxSuccessorDistance()) + std::abs(diff_pos[2]) / 0.2 + (first_theta * first_rotation_weight + second_theta * second_rotation_weight) / graph->maxSuccessorRotation(); }
void noShip::HandleEvent(const unsigned int id) { current_ev = 0; switch(id) { // Laufevent case 0: { // neue Position einnehmen Walk(); // entscheiden, was als nächstes zu tun ist Driven(); } break; default: { switch(state) { default: break; case STATE_EXPEDITION_LOADING: { // Schiff ist nun bereit und Expedition kann beginnen state = STATE_EXPEDITION_WAITING; // Spieler benachrichtigen if(GAMECLIENT.GetPlayerID() == this->player) GAMECLIENT.SendPostMessage(new ShipPostMsg(_("A ship is ready for an expedition."), PMC_GENERAL, GAMECLIENT.GetPlayer(player).nation, pos)); // KI Event senden GAMECLIENT.SendAIEvent(new AIEvent::Location(AIEvent::ExpeditionWaiting, pos), player); } break; case STATE_EXPLORATIONEXPEDITION_LOADING: { // Schiff ist nun bereit und Expedition kann beginnen ContinueExplorationExpedition(); } break; case STATE_EXPLORATIONEXPEDITION_WAITING: { // Schiff ist nun bereit und Expedition kann beginnen ContinueExplorationExpedition(); } break; case STATE_EXPEDITION_UNLOADING: { // Hafen herausfinden MapPoint goal_pos(gwg->GetHarborPoint(goal_harbor_id)); noBase* hb = gwg->GetNO(goal_pos); if(hb->GetGOT() == GOT_NOB_HARBORBUILDING) { Goods goods; memset(&goods, 0, sizeof(Goods)); unsigned char nation = players->getElement(player)->nation; goods.goods[GD_BOARDS] = BUILDING_COSTS[nation][BLD_HARBORBUILDING].boards; goods.goods[GD_STONES] = BUILDING_COSTS[nation][BLD_HARBORBUILDING].stones; goods.people[JOB_BUILDER] = 1; static_cast<nobBaseWarehouse*>(hb)->AddGoods(goods); // Wieder idlen und ggf. neuen Job suchen StartIdling(); players->getElement(player)->GetJobForShip(this); } else { // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state state = STATE_EXPEDITION_DRIVING; HandleState_ExpeditionDriving(); } } break; case STATE_EXPLORATIONEXPEDITION_UNLOADING: { // Hafen herausfinden MapPoint goal_pos(gwg->GetHarborPoint(goal_harbor_id)); noBase* hb = gwg->GetNO(goal_pos); unsigned old_visual_range = GetVisualRange(); if(hb->GetGOT() == GOT_NOB_HARBORBUILDING) { // Späher wieder entladen Goods goods; memset(&goods, 0, sizeof(Goods)); goods.people[JOB_SCOUT] = SCOUTS_EXPLORATION_EXPEDITION; static_cast<nobBaseWarehouse*>(hb)->AddGoods(goods); // Wieder idlen und ggf. neuen Job suchen StartIdling(); players->getElement(player)->GetJobForShip(this); } else { // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state state = STATE_EXPLORATIONEXPEDITION_DRIVING; HandleState_ExplorationExpeditionDriving(); } // Sichtbarkeiten neu berechnen gwg->RecalcVisibilitiesAroundPoint(pos, old_visual_range, player, NULL); } break; case STATE_TRANSPORT_LOADING: { StartTransport(); } break; case STATE_TRANSPORT_UNLOADING: { // Hafen herausfinden remaining_sea_attackers = 0; //can be 1 in case we had sea attackers on board - set to 1 for a special check when the return harbor is destroyed to set the returning attackers goal to 0 MapPoint goal_pos(gwg->GetHarborPoint(goal_harbor_id)); noBase* hb = gwg->GetNO(goal_pos); if(hb->GetGOT() == GOT_NOB_HARBORBUILDING) { static_cast<nobHarborBuilding*>(hb)->ReceiveGoodsFromShip(figures, wares); figures.clear(); wares.clear(); // Hafen bescheid sagen, dass er das Schiff nun nutzen kann static_cast<nobHarborBuilding*>(hb)->ShipArrived(this); // Hafen hat keinen Job für uns? if (state == STATE_TRANSPORT_UNLOADING) { // Wieder idlen und ggf. neuen Job suchen StartIdling(); players->getElement(player)->GetJobForShip(this); } } else { // target harbor for unloading doesnt exist anymore -> set state to driving and handle the new state state = STATE_TRANSPORT_DRIVING; HandleState_TransportDriving(); } } break; case STATE_SEAATTACK_LOADING: { StartSeaAttack(); } break; case STATE_SEAATTACK_WAITING: { // Nächsten Soldaten nach draußen beordern if(figures.empty()) break; nofAttacker* attacker = static_cast<nofAttacker*>(*figures.begin()); // Evtl. ist ein Angreifer schon fertig und wieder an Board gegangen // der darf dann natürlich nicht noch einmal raus, sonst kann die schöne Reise // böse enden if(attacker->IsSeaAttackCompleted()) break; figures.pop_front(); gwg->AddFigure(attacker, pos); current_ev = em->AddEvent(this, 30, 1); attacker->StartAttackOnOtherIsland(pos, GetObjId()); ; }; case STATE_SEAATTACK_UNLOADING: { } break; } } break; } }
bool EnhancedIKSolver::solve_chain_keep_next_bone_pos(unsigned int root_bone, unsigned int end_bone, const float3& goal_position, int current_frame, bool force_position) { //If the end bone does not have child call the simpler method //this one is for keep the chain after end_bone in the same state if (skeleton->get_node(end_bone)->get_num_children() == 0) { return solve_chain(root_bone, end_bone, goal_position, current_frame); } std::vector<int> indices; fill_chain(root_bone, end_bone, current_frame, indices); Node* next_bone = skeleton->get_node(end_bone)->children[0].get(); osg::Vec3 next_bone_pos = next_bone->get_end_bone_global_pos(current_frame); osg::Quat next_bone_child_glob_prev_rot; if (next_bone->get_num_children() != 0) { next_bone_child_glob_prev_rot = next_bone->children[0]->get_global_rot( current_frame); } osg::Vec3 goal_pos(goal_position.x, goal_position.y, goal_position.z); //Calculate vector from next bone to goal position osg::Vec3 dir_vec = goal_pos - next_bone_pos; dir_vec.normalize(); float next_bone_length = next_bone->get_length(); //Closest point in the sphere of movement is //centre of the sphere (next_bone_pos) plus its radius ( next_bone_length ) //looking at the direction of the previous goal goal_pos = next_bone_pos + dir_vec * next_bone_length; //Calculate in root_bone coordinate system where is the goal position osg::Matrix m; skeleton->get_node(root_bone)->get_node_world_matrix_origin(current_frame, m); osg::Vec3 goal_position_start_bone = goal_pos * m; //Solve and update the rotations bool solve_succes = ik_solver.solve_chain( make_float3(goal_position_start_bone._v)); if (solve_succes || force_position) { int j = 0; for (unsigned int i = 0; i < indices.size(); i++) { Node * node = skeleton->get_node(indices[i]); float4 new_rot; ik_solver.get_rotation_joint(j, new_rot); node->quat_arr.at(current_frame).set(new_rot.x, new_rot.y, new_rot.z, new_rot.w); j++; } //Put next bone back to where it was float3 next_bone_pos_f3 = make_float3(next_bone_pos._v); //Prev rotations will be overwritten by solve_chain so //make a copy in case of failure std::vector<osg::Quat> copy_prev_rots(previous_rotations); if (!solve_chain(end_bone + 1, end_bone + 1, next_bone_pos_f3, current_frame)) { previous_rotations = copy_prev_rots; undo_rotations(indices, current_frame); return false; } //Correct next bone child rotation //If child previous global rotation was //R = R3 * R2 * R1 * R0 //Where R3 is child, R2 parent, etc //New state is //R = R3' * R2' * R1' * R0' //Solving for new R3' that maintains previous global rotation // R3' = R * inv(R2' * R1' * R0') if (next_bone->get_num_children() != 0) { next_bone->children[0]->quat_arr.at(current_frame) = next_bone_child_glob_prev_rot * next_bone->get_global_rot(current_frame).inverse(); } return true; } else { return false; } }