QPLocomotionPlan::QPLocomotionPlan(RigidBodyManipulator& robot, const QPLocomotionPlanSettings& settings, const std::string& lcm_channel) : robot(robot), settings(settings), start_time(std::numeric_limits<double>::quiet_NaN()), pelvis_id(robot.findLinkId(settings.pelvis_name)), foot_body_ids(createFootBodyIdMap(robot, settings.foot_names)), knee_indices(createJointIndicesMap(robot, settings.knee_names)), akx_indices(createJointIndicesMap(robot, settings.akx_names)), aky_indices(createJointIndicesMap(robot, settings.aky_names)), plan_shift(Vector3d::Zero()), shifted_zmp_trajectory(settings.zmp_trajectory) { for (int i = 1; i < settings.support_times.size(); i++) { if (settings.support_times[i] < settings.support_times[i - 1]) throw std::runtime_error("support times must be increasing"); } for (auto it = Side::values.begin(); it != Side::values.end(); ++it) { toe_off_active[*it] = false; knee_pd_active[*it] = false; knee_pd_settings[*it] = QPLocomotionPlanSettings::createDefaultKneeSettings(); foot_shifts[*it] = Vector3d::Zero(); } if (!lcm.good()) { cerr << "ERROR: lcm is not good()" << endl; } }
const std::map<Side, int> QPLocomotionPlan::createFootBodyIdMap(RigidBodyManipulator& robot, const std::map<Side, std::string>& foot_names) { std::map<Side, int> foot_body_ids; for (auto it = Side::values.begin(); it != Side::values.end(); ++it) { foot_body_ids[*it] = robot.findLinkId(foot_names.at(*it)); } return foot_body_ids; }
void App::solveGazeProblem(){ // Publish the query for visualisation in Director bot_core::pose_t goalMsg; goalMsg.utime = rstate_.utime; goalMsg.pos[0] = cl_cfg_.gazeGoal(0); goalMsg.pos[1] = cl_cfg_.gazeGoal(1); goalMsg.pos[2] = cl_cfg_.gazeGoal(2); goalMsg.orientation[0] = 1; goalMsg.orientation[1] = 0; goalMsg.orientation[2] = 0; goalMsg.orientation[3] = 0; lcm_->publish("POSE_BODY_ALT", &goalMsg); // Solve the IK problem for the neck: VectorXd q_star(robotStateToDrakePosition(rstate_, dofMap_, model_.num_positions)); VectorXd q_sol(model_.num_positions); int info = getConstraints(q_star, q_sol); if (info != 1) { std::cout << "Problem not solved\n"; return; } bool mode = 0; if (mode==0){ // publish utorso-to-head as orientation, not properly tracking but works with different orientations // Get the utorso to head frame: int pelvis_link = model_.findLinkId("pelvis"); int head_link = model_.findLinkId("head"); int utorso_link = model_.findLinkId("torso"); KinematicsCache<double> cache = model_.doKinematics(q_sol,0); Eigen::Isometry3d world_to_pelvis = matrixdToIsometry3d( model_.forwardKin(cache, Vector3d::Zero().eval(), pelvis_link, 0, 2, 0).value() ); Eigen::Isometry3d world_to_head = matrixdToIsometry3d( model_.forwardKin(cache, Vector3d::Zero().eval(), head_link, 0, 2, 0).value() ); Eigen::Isometry3d pelvis_to_head = world_to_head.inverse()*world_to_pelvis; Eigen::Isometry3d pelvis_to_utorso = matrixdToIsometry3d( model_.forwardKin(cache, Vector3d::Zero().eval(), utorso_link, 0, 2, 0).value() ).inverse()*world_to_pelvis; Eigen::Isometry3d utorso_to_head = pelvis_to_utorso.inverse()*pelvis_to_head; // Apply 180 roll as head orientation control seems to be in z-up frame Eigen::Isometry3d rotation_frame; rotation_frame.setIdentity(); Eigen::Quaterniond quat = euler_to_quat( M_PI, 0, 0); rotation_frame.rotate(quat); utorso_to_head = utorso_to_head*rotation_frame; bot_core::pose_t world_to_head_frame_pose_msg = getPoseAsBotPose(world_to_head, rstate_.utime); lcm_->publish("POSE_VICON",&world_to_head_frame_pose_msg);// for debug bot_core::pose_t utorso_to_head_frame_pose_msg = getPoseAsBotPose(utorso_to_head, rstate_.utime); lcm_->publish("DESIRED_HEAD_ORIENTATION",&utorso_to_head_frame_pose_msg);// temp }else{ // publish neck pitch and yaw joints as orientation. this works ok when robot is facing 1,0,0,0 // Fish out the two neck joints (in simulation) and send as a command: std::vector<string> jointNames; for (int i=0 ; i <model_.num_positions ; i++){ // std::cout << model.getPositionName(i) << " " << i << "\n"; jointNames.push_back( model_.getPositionName(i) ) ; } drc::robot_state_t robot_state_msg; getRobotState(robot_state_msg, 0*1E6, q_sol , jointNames); lcm_->publish("CANDIDATE_ROBOT_ENDPOSE",&robot_state_msg); std::vector<std::string>::iterator it1 = find(jointNames.begin(), jointNames.end(), "lowerNeckPitch"); int lowerNeckPitchIndex = std::distance(jointNames.begin(), it1); float lowerNeckPitchAngle = q_sol[lowerNeckPitchIndex]; std::vector<std::string>::iterator it2 = find(jointNames.begin(), jointNames.end(), "neckYaw"); int neckYawIndex = std::distance(jointNames.begin(), it2); float neckYawAngle = q_sol[neckYawIndex]; std::cout << lowerNeckPitchAngle << " (" << lowerNeckPitchAngle*180.0/M_PI << ") is lowerNeckPitchAngle\n"; std::cout << neckYawAngle << " (" << neckYawAngle*180.0/M_PI << ") is neckYawAngle\n"; bot_core::pose_t headOrientationMsg; headOrientationMsg.utime = rstate_.utime; headOrientationMsg.pos[0] = 0; headOrientationMsg.pos[1] = 0; headOrientationMsg.pos[2] = 0; Eigen::Quaterniond quat = euler_to_quat(0, lowerNeckPitchAngle, neckYawAngle); headOrientationMsg.orientation[0] = quat.w(); headOrientationMsg.orientation[1] = quat.x(); headOrientationMsg.orientation[2] = quat.y(); headOrientationMsg.orientation[3] = quat.z(); lcm_->publish("DESIRED_HEAD_ORIENTATION",&headOrientationMsg); lcm_->publish("POSE_VICON",&headOrientationMsg); // for debug } //std::cout << "Desired orientation sent, exiting\n"; //exit(-1); }
int App::getConstraints(Eigen::VectorXd q_star, Eigen::VectorXd &q_sol){ Vector2d tspan; tspan << 0, 1; // 0 Pelvis Position and Orientation Constraints int pelvis_link = model_.findLinkId("pelvis"); Vector3d pelvis_pt = Vector3d::Zero(); Vector3d pelvis_pos0; pelvis_pos0(0) = rstate_.pose.translation.x; pelvis_pos0(1) = rstate_.pose.translation.y; pelvis_pos0(2) = rstate_.pose.translation.z; Vector3d pelvis_pos_lb = pelvis_pos0; //pelvis_pos_lb(0) += 0.001; //pelvis_pos_lb(1) += 0.001; //pelvis_pos_lb(2) += 0.001; Vector3d pelvis_pos_ub = pelvis_pos_lb; //pelvis_pos_ub(2) += 0.001; WorldPositionConstraint kc_pelvis_pos(&model_, pelvis_link, pelvis_pt, pelvis_pos_lb, pelvis_pos_ub, tspan); Eigen::Vector4d pelvis_quat_des(rstate_.pose.rotation.w , rstate_.pose.rotation.x, rstate_.pose.rotation.y, rstate_.pose.rotation.z); double pelvis_tol = 0;//0.0017453292519943296; WorldQuatConstraint kc_pelvis_quat(&model_, pelvis_link, pelvis_quat_des, pelvis_tol, tspan); // 1 Back Posture Constraint PostureConstraint kc_posture_back(&model_, tspan); std::vector<int> back_idx; findJointAndInsert(model_, "torsoYaw", back_idx); findJointAndInsert(model_, "torsoPitch", back_idx); findJointAndInsert(model_, "torsoRoll", back_idx); VectorXd back_lb = VectorXd::Zero(3); VectorXd back_ub = VectorXd::Zero(3); kc_posture_back.setJointLimits(3, back_idx.data(), back_lb, back_ub); // 2 Upper Neck Constraint PostureConstraint kc_posture_neck(&model_, tspan); std::vector<int> neck_idx; findJointAndInsert(model_, "upperNeckPitch", neck_idx); VectorXd neck_lb = VectorXd::Zero(1); neck_lb(0) = 0.0; VectorXd neck_ub = VectorXd::Zero(1); neck_ub(0) = 0.0; kc_posture_neck.setJointLimits(1, neck_idx.data(), neck_lb, neck_ub); // 3 Look At constraint: int head_link = model_.findLinkId("head"); Eigen::Vector3d gaze_axis = Eigen::Vector3d(1,0,0); Eigen::Vector3d target = cl_cfg_.gazeGoal; Eigen::Vector3d gaze_origin = Eigen::Vector3d(0,0, 0);//0.45);// inserting this offset almost achieves the required look-at double conethreshold = 0; WorldGazeTargetConstraint kc_gaze(&model_, head_link, gaze_axis, target, gaze_origin, conethreshold, tspan); // Assemble Constraint Set std::vector<RigidBodyConstraint *> constraint_array; constraint_array.push_back(&kc_pelvis_pos); constraint_array.push_back(&kc_pelvis_quat); constraint_array.push_back(&kc_gaze); constraint_array.push_back(&kc_posture_back); // leave this out to also use the back constraint_array.push_back(&kc_posture_neck); // upper neck pitch // Solve IKoptions ikoptions(&model_); int info; vector<string> infeasible_constraint; inverseKin(&model_, q_star, q_star, constraint_array.size(), constraint_array.data(), q_sol, info, infeasible_constraint, ikoptions); printf("INFO = %d\n", info); return info; }