diff --git a/examples/example_a1_walking/main.cpp b/examples/example_a1_walking/main.cpp index 91c1ffb73..29a107c3b 100644 --- a/examples/example_a1_walking/main.cpp +++ b/examples/example_a1_walking/main.cpp @@ -108,7 +108,7 @@ int massGraph() { objectives.add( LinkObjectives(base_link->id(), k) .pose(Pose3(Rot3(), Point3(0, 0, 0.4)), Isotropic::Sigma(6, 1e-2)) - .twist(gtsam::Z_6x1, Isotropic::Sigma(6, 5e-2))); + .twist(gtsam::Vector6::Zero(), Isotropic::Sigma(6, 5e-2))); } // Add link and joint boundary conditions to FG. @@ -262,7 +262,7 @@ int oldGraph() { objectives.add( LinkObjectives(base_link->id(), k) .pose(Pose3(Rot3(), Point3(0, 0, 0.4)), Isotropic::Sigma(6, 1e-2)) - .twist(gtsam::Z_6x1, Isotropic::Sigma(6, 5e-2))); + .twist(gtsam::Vector6::Zero(), Isotropic::Sigma(6, 5e-2))); } // Add link and joint boundary conditions to FG. @@ -418,7 +418,7 @@ int newGraph() { if (i == 0) objectives.add(LinkObjectives(i, 0) .pose(link->bMcom(), Isotropic::Sigma(6, 1e-3)) - .twist(gtsam::Z_6x1, Isotropic::Sigma(6, 1e-3))); + .twist(gtsam::Vector6::Zero(), Isotropic::Sigma(6, 1e-3))); if (i == 3 || i == 6 || i == 9 || i == 12) objectives.add( LinkObjectives(i, 0).pose(link->bMcom(), Isotropic::Sigma(6, 1e-3))); @@ -435,7 +435,7 @@ int newGraph() { objectives.add( LinkObjectives(base_link->id(), k) .pose(Pose3(Rot3(), Point3(0, 0, 0.4)), Isotropic::Sigma(6, 1e-2)) - .twist(gtsam::Z_6x1, Isotropic::Sigma(6, 5e-2))); + .twist(gtsam::Vector6::Zero(), Isotropic::Sigma(6, 5e-2))); } // Constrain all Phase keys to have duration of 1 /240. diff --git a/examples/example_a1_walking/main_combined.cpp b/examples/example_a1_walking/main_combined.cpp index debdddac9..3f6c6487d 100644 --- a/examples/example_a1_walking/main_combined.cpp +++ b/examples/example_a1_walking/main_combined.cpp @@ -144,8 +144,8 @@ int CombinedRun(bool add_mass_to_body) { for (int k = 0; k <= K; k++) { objectives.add(LinkObjectives(base_link->id(), k) .pose(base_link->bMcom(), Isotropic::Sigma(6, 5e-5)) - .twist(gtsam::Z_6x1, Isotropic::Sigma(6, 5e-5)) - .twistAccel(gtsam::Z_6x1, Isotropic::Sigma(6, 5e-5))); + .twist(gtsam::Vector6::Zero(), Isotropic::Sigma(6, 5e-5)) + .twistAccel(gtsam::Vector6::Zero(), Isotropic::Sigma(6, 5e-5))); } // Add prior on A1 lower joint angles @@ -210,7 +210,7 @@ int CombinedRun(bool add_mass_to_body) { if (i == 0) boundary_objectives_CDG.add(LinkObjectives(i, 0) .pose(link->bMcom(), dynamics_model_6) - .twist(gtsam::Z_6x1, dynamics_model_6)); + .twist(gtsam::Vector6::Zero(), dynamics_model_6)); if (i == 3 || i == 6 || i == 9 || i == 12) boundary_objectives_CDG.add( LinkObjectives(i, 0).pose(link->bMcom(), dynamics_model_6)); diff --git a/examples/example_full_kinodynamic_balancing/main.cpp b/examples/example_full_kinodynamic_balancing/main.cpp index 6abfd74fd..f7b287b18 100644 --- a/examples/example_full_kinodynamic_balancing/main.cpp +++ b/examples/example_full_kinodynamic_balancing/main.cpp @@ -58,10 +58,10 @@ int main(int argc, char** argv) { // Specify boundary conditions for base and joints. gtsam::Pose3 base_pose_init = vision60.link("body")->bMcom(); - gtsam::Vector6 base_twist_init = gtsam::Z_6x1, - base_twist_final = gtsam::Z_6x1, - base_accel_init = gtsam::Z_6x1, - base_accel_final = gtsam::Z_6x1; + gtsam::Vector6 base_twist_init = gtsam::Vector6::Zero(), + base_twist_final = gtsam::Vector6::Zero(), + base_accel_init = gtsam::Vector6::Zero(), + base_accel_final = gtsam::Vector6::Zero(); gtsam::Vector joint_angles_init = gtsam::Vector::Zero(12), joint_vels_init = gtsam::Vector::Zero(12), joint_accels_init = gtsam::Vector::Zero(12), diff --git a/examples/example_spider_walking/main.cpp b/examples/example_spider_walking/main.cpp index fb0053ec8..30c149623 100644 --- a/examples/example_spider_walking/main.cpp +++ b/examples/example_spider_walking/main.cpp @@ -106,7 +106,7 @@ int main(int argc, char** argv) { objectives.add( LinkObjectives(base_link->id(), k) .pose(Pose3(Rot3(), Point3(0, 0.0, 0.5)), Isotropic::Sigma(6, 5e-5)) - .twist(gtsam::Z_6x1, Isotropic::Sigma(6, 5e-5))); + .twist(gtsam::Vector6::Zero(), Isotropic::Sigma(6, 5e-5))); } // Add link and joint boundary conditions to FG. diff --git a/examples/scripts/alejandro_yetong_01_id_four_bar.cpp b/examples/scripts/alejandro_yetong_01_id_four_bar.cpp index 226536375..c3ef8c864 100644 --- a/examples/scripts/alejandro_yetong_01_id_four_bar.cpp +++ b/examples/scripts/alejandro_yetong_01_id_four_bar.cpp @@ -52,7 +52,7 @@ int main(int argc, char** argv) { prior_factors.addPrior(PoseKey(i, 0), link->bMcom(), gtsam::noiseModel::Constrained::All(6)); prior_factors.addPrior( - TwistKey(i, 0), gtsam::Z_6x1, gtsam::noiseModel::Constrained::All(6)); + TwistKey(i, 0), gtsam::Vector6::Zero(), gtsam::noiseModel::Constrained::All(6)); } graph.add(prior_factors); diff --git a/gtdynamics.i b/gtdynamics.i index 53e0fc11a..df428896d 100644 --- a/gtdynamics.i +++ b/gtdynamics.i @@ -374,6 +374,8 @@ class KinematicsParameters : gtdynamics::OptimizationParameters { double bv_cost_model_sigma = 1e-4, double v_cost_model_sigma = 1e-4, double cv_cost_model_sigma = 1e-2); + void setJointPriorSigma(gtsam::Key joint_key, double sigma); + void setJointLimit(gtsam::Key joint_key, double lower, double upper); }; class Kinematics { diff --git a/gtdynamics/dynamics/ChainDynamicsGraph.cpp b/gtdynamics/dynamics/ChainDynamicsGraph.cpp index 3b8b3468a..12b33909c 100644 --- a/gtdynamics/dynamics/ChainDynamicsGraph.cpp +++ b/gtdynamics/dynamics/ChainDynamicsGraph.cpp @@ -125,7 +125,7 @@ NonlinearFactorGraph ChainDynamicsGraph::dynamicsFactors( std::vector wrench_keys; constexpr int root = 0; // TODO(Frank): Hard-coded for A1. - const Vector6 wrench_zero = gtsam::Z_6x1; + const Vector6 wrench_zero = gtsam::Vector6::Zero(); for (int leg = 0; leg < 4; ++leg) { bool foot_in_contact = false; diff --git a/gtdynamics/dynamics/DynamicsGraph.cpp b/gtdynamics/dynamics/DynamicsGraph.cpp index 19fb5d33f..d18c1a61e 100644 --- a/gtdynamics/dynamics/DynamicsGraph.cpp +++ b/gtdynamics/dynamics/DynamicsGraph.cpp @@ -42,7 +42,7 @@ using gtsam::PriorFactor; using gtsam::Values; using gtsam::Vector; using gtsam::Vector6; -using gtsam::Z_6x1; +using gtsam::Vector6::Zero(); namespace gtdynamics { diff --git a/gtdynamics/dynamics/DynamicsSlice.cpp b/gtdynamics/dynamics/DynamicsSlice.cpp index 3fb49ee98..31d8b5358 100644 --- a/gtdynamics/dynamics/DynamicsSlice.cpp +++ b/gtdynamics/dynamics/DynamicsSlice.cpp @@ -30,7 +30,7 @@ NonlinearFactorGraph Dynamics::aFactors( for (auto&& link : robot.links()) { if (link->isFixed()) { graph.addPrior(TwistAccelKey(link->id(), slice.k), - gtsam::Z_6x1, p_.ba_cost_model); + gtsam::Vector6::Zero(), p_.ba_cost_model); } } for (auto&& joint : robot.joints()) { diff --git a/gtdynamics/dynamics/tests/testChain.cpp b/gtdynamics/dynamics/tests/testChain.cpp index ddd2712f1..b96750ba0 100644 --- a/gtdynamics/dynamics/tests/testChain.cpp +++ b/gtdynamics/dynamics/tests/testChain.cpp @@ -986,7 +986,7 @@ gtsam::Values OldGraphOneLeg() { OptimizerSetting opt(1e-4, 1e-4, 1e-4, 1e-4); DynamicsGraph graph_builder(opt, gravity); - gtsam::Vector6 wrench_zero = gtsam::Z_6x1; + gtsam::Vector6 wrench_zero = gtsam::Vector6::Zero(); gtsam::NonlinearFactorGraph graph; @@ -1094,7 +1094,7 @@ gtsam::Values NewGraphOneLeg() { if (joint->id() > 2) continue; InsertJointAngle(&init_values, joint->id(), 0, 0.0); } - gtsam::Vector6 wrench_zero = gtsam::Z_6x1; + gtsam::Vector6 wrench_zero = gtsam::Vector6::Zero(); init_values.insert(gtdynamics::WrenchKey(0, 0, 0), wrench_zero); /// Solve the constraint problem with LM optimizer. @@ -1199,7 +1199,7 @@ gtsam::Values OldGraphFourLegs() { OptimizerSetting opt(5e-5, 5e-5, 5e-5, 5e-5); DynamicsGraph graph_builder(opt, gravity); - gtsam::Vector6 wrench_zero = gtsam::Z_6x1; + gtsam::Vector6 wrench_zero = gtsam::Vector6::Zero(); gtsam::NonlinearFactorGraph graph; @@ -1276,7 +1276,7 @@ gtsam::Values NewGraphFourLegs() { //ChainDynamicsGraph chain_graph(robot, opt, 1*(1e-4), 6*(1e-5), 10.08*(1e-5), gravity); ChainDynamicsGraph chain_graph(robot, opt, gravity); - gtsam::Vector6 wrench_zero = gtsam::Z_6x1; + gtsam::Vector6 wrench_zero = gtsam::Vector6::Zero(); auto constrained_model = gtsam::noiseModel::Constrained::All(6); auto bp_cost_model(gtsam::noiseModel::Isotropic::Sigma(6, 1e-5)); diff --git a/gtdynamics/dynamics/tests/testDynamicsGraph.cpp b/gtdynamics/dynamics/tests/testDynamicsGraph.cpp index fa90c39ad..cd9f63e3b 100644 --- a/gtdynamics/dynamics/tests/testDynamicsGraph.cpp +++ b/gtdynamics/dynamics/tests/testDynamicsGraph.cpp @@ -70,7 +70,7 @@ TEST(linearDynamicsFactorGraph, simple_urdf_eq_mass_values) { int t = 777; auto j = robot.joint("j1")->id(); InsertPose(&values, l1->id(), t, l1->bMcom()); - InsertTwist(&values, l1->id(), t, gtsam::Z_6x1); + InsertTwist(&values, l1->id(), t, gtsam::Vector6::Zero()); // Do forward kinematics. Values fk_results = robot.forwardKinematics(values, t, prior_link_name); @@ -127,7 +127,7 @@ TEST(dynamicsFactorGraph_FD, simple_urdf_eq_mass) { int i = link->id(); graph.addPrior(PoseKey(i, t), link->bMcom(), graph_builder.opt().bp_cost_model); - graph.addPrior(TwistKey(i, t), gtsam::Z_6x1, + graph.addPrior(TwistKey(i, t), gtsam::Vector6::Zero(), graph_builder.opt().bv_cost_model); } Initializer initializer; @@ -164,7 +164,7 @@ TEST(dynamicsFactorGraph_FD, four_bar_linkage_pure) { int i = link->id(); prior_factors.addPrior(PoseKey(i, 0), link->bMcom(), graph_builder.opt().bp_cost_model); - prior_factors.addPrior(TwistKey(i, 0), gtsam::Z_6x1, + prior_factors.addPrior(TwistKey(i, 0), gtsam::Vector6::Zero(), graph_builder.opt().bv_cost_model); } @@ -465,7 +465,7 @@ TEST(dynamicsFactorGraph_Contacts, dynamics_graph_simple_rr) { poseWithContactHeight(l0->bMcom(), contact_in_com, kGroundHeight), gtsam::noiseModel::Constrained::All(6)); - prior_factors.addPrior(TwistKey(l0->id(), 0), gtsam::Z_6x1, + prior_factors.addPrior(TwistKey(l0->id(), 0), gtsam::Vector6::Zero(), gtsam::noiseModel::Constrained::All(6)); graph.add(prior_factors); @@ -523,9 +523,9 @@ TEST(dynamicsFactorGraph_Contacts, dynamics_graph_biped) { auto body = biped.link("body"); prior_factors.addPrior(PoseKey(body->id(), 0), body->bMcom(), graph_builder.opt().bp_cost_model); - prior_factors.addPrior(TwistKey(body->id(), 0), gtsam::Z_6x1, + prior_factors.addPrior(TwistKey(body->id(), 0), gtsam::Vector6::Zero(), graph_builder.opt().bv_cost_model); - prior_factors.addPrior(TwistAccelKey(body->id(), 0), gtsam::Z_6x1, + prior_factors.addPrior(TwistAccelKey(body->id(), 0), gtsam::Vector6::Zero(), graph_builder.opt().ba_cost_model); graph.add(prior_factors); @@ -602,7 +602,7 @@ TEST(dynamicsFactorGraph_Contacts, dynamics_graph_simple_rrr) { poseWithContactHeight(l0->bMcom(), contact_in_com, kGroundHeight), gtsam::noiseModel::Constrained::All(6)); - prior_factors.addPrior(TwistKey(l0->id(), 0), gtsam::Z_6x1, + prior_factors.addPrior(TwistKey(l0->id(), 0), gtsam::Vector6::Zero(), gtsam::noiseModel::Constrained::All(6)); graph.add(prior_factors); diff --git a/gtdynamics/kinematics/KinematicsParameters.h b/gtdynamics/kinematics/KinematicsParameters.h index dfa80f587..d3d41d32c 100644 --- a/gtdynamics/kinematics/KinematicsParameters.h +++ b/gtdynamics/kinematics/KinematicsParameters.h @@ -13,8 +13,13 @@ #pragma once #include +#include #include +#include +#include +#include + namespace gtdynamics { /// Noise models etc specific to Kinematics class @@ -22,13 +27,20 @@ struct KinematicsParameters : public OptimizationParameters { using Isotropic = gtsam::noiseModel::Isotropic; gtsam::SharedNoiseModel p_cost_model, // pose factor g_cost_model, // goal point - prior_q_cost_model, // joint angle prior factor + prior_q_cost_model, // joint angle prior factor (default) bp_cost_model, // fixed-link pose prior factor cp_cost_model, // contact-height factor bv_cost_model, // fixed-link twist prior factor v_cost_model, // twist factor cv_cost_model; // contact-twist factor + /// Per-joint joint-angle prior models keyed by joint key; overrides + /// prior_q_cost_model for listed joints (used by kinematics IK only). + std::map joint_prior_overrides; + + /// Per-joint {lower, upper} limit overrides by joint key (IK only). + std::map> joint_limit_overrides; + KinematicsParameters() : KinematicsParameters(1e-4, 1e-2, 0.5, 1e-4, 1e-2, 1e-4, 1e-4, 1e-2) {} @@ -68,6 +80,16 @@ struct KinematicsParameters : public OptimizationParameters { Isotropic::Sigma(6, bv_cost_model_sigma), Isotropic::Sigma(6, v_cost_model_sigma), Isotropic::Sigma(3, cv_cost_model_sigma)) {} + + /// Override the joint-angle prior sigma for one joint by key. + void setJointPriorSigma(gtsam::Key joint_key, double sigma) { + joint_prior_overrides[joint_key] = Isotropic::Sigma(1, sigma); + } + + /// Override the joint-angle limits for one joint by key. + void setJointLimit(gtsam::Key joint_key, double lower, double upper) { + joint_limit_overrides[joint_key] = {lower, upper}; + } }; } // namespace gtdynamics diff --git a/gtdynamics/kinematics/KinematicsSlice.cpp b/gtdynamics/kinematics/KinematicsSlice.cpp index 33c03bd71..dfeeb84c9 100644 --- a/gtdynamics/kinematics/KinematicsSlice.cpp +++ b/gtdynamics/kinematics/KinematicsSlice.cpp @@ -302,11 +302,15 @@ NonlinearFactorGraph Kinematics::jointAngleObjectives( const Slice& slice, const Robot& robot, const Values& mean) const { NonlinearFactorGraph graph; - // Minimize the joint angles. + // Per-joint override from p_.joint_prior_overrides, else prior_q_cost_model. for (auto&& joint : robot.joints()) { const gtsam::Key key = JointAngleKey(joint->id(), slice.k); + auto it = p_.joint_prior_overrides.find(joint->key()); + const gtsam::SharedNoiseModel cost_model = + (it != p_.joint_prior_overrides.end()) ? it->second + : p_.prior_q_cost_model; graph.addPrior(key, (mean.exists(key) ? mean.at(key) : 0.0), - p_.prior_q_cost_model); + cost_model); } return graph; @@ -317,12 +321,18 @@ NonlinearFactorGraph Kinematics::jointAngleLimits( const Slice& slice, const Robot& robot) const { NonlinearFactorGraph graph; for (auto&& joint : robot.joints()) { - graph.add(JointLimitFactor( - JointAngleKey(joint->id(), slice.k), - gtsam::noiseModel::Isotropic::Sigma(1, 0.001), - joint->parameters().scalar_limits.value_lower_limit, - joint->parameters().scalar_limits.value_upper_limit, - 0.04)); // joint->parameters().scalar_limits.value_limit_threshold)); + // Override URDF limits for joints listed in p_.joint_limit_overrides. + auto it = p_.joint_limit_overrides.find(joint->key()); + const auto& limits = joint->parameters().scalar_limits; + const double lower = + (it != p_.joint_limit_overrides.end()) ? it->second.first + : limits.value_lower_limit; + const double upper = + (it != p_.joint_limit_overrides.end()) ? it->second.second + : limits.value_upper_limit; + graph.add(JointLimitFactor(JointAngleKey(joint->id(), slice.k), + gtsam::noiseModel::Isotropic::Sigma(1, 0.001), + lower, upper, 0.04)); } return graph; } diff --git a/gtdynamics/kinematics/tests/testKinematicsSlice.cpp b/gtdynamics/kinematics/tests/testKinematicsSlice.cpp index d53207d54..071fbed39 100644 --- a/gtdynamics/kinematics/tests/testKinematicsSlice.cpp +++ b/gtdynamics/kinematics/tests/testKinematicsSlice.cpp @@ -44,7 +44,7 @@ TEST(Slice, InverseKinematics) { // Set twists to zero for FK. TODO(frank): separate kinematics from velocity? for (auto&& link : robot.links()) { - InsertTwist(&values, link->id(), k, gtsam::Z_6x1); + InsertTwist(&values, link->id(), k, gtsam::Vector6::Zero()); } // Do forward kinematics @@ -422,6 +422,54 @@ TEST(Slice, BarLabPoseConstraintIK) { result.at(PoseKey(base_link->id(), k)), tol)); } +// Higher gantry prior sigmas let the gantry absorb more of the motion to goal. +TEST(Slice, BarLabGantryPriorSigma) { + using gtsam::Pose3; + using gtsam::Values; + + const Robot robot = + CreateRobotFromFile(kUrdfPath + std::string("bar_lab.urdf")) + .fixLink("columns"); + auto ee_link = robot.link("robot1_link_6"); + const auto ee_id = ee_link->id(); + const std::vector gantry_joints = { + "bridge1_joint_EA_X", "robot1_joint_EA_Y", "robot1_joint_EA_Z"}; + + // Reachable goal from a config that uses the gantry, so there is redundancy. + Kinematics goal_kinematics; + Values fk = goal_kinematics.initialValues(kSlice, robot, 0.0, + barLabConfig(robot), true); + const Pose3 wTcom_goal = fk.at(PoseKey(ee_id, k)); + PoseGoals pose_goals = {{k, PoseGoal(ee_link, Pose3(), wTcom_goal)}}; + + // Solve IK with the given gantry prior sigma; pose goal is a hard constraint. + auto solve = [&](double gantry_sigma) { + KinematicsParameters params; + params.method = OptimizationParameters::Method::AUGMENTED_LAGRANGIAN; + for (const auto& name : gantry_joints) + params.setJointPriorSigma(robot.joint(name)->key(), gantry_sigma); + return Kinematics(params).inverse(kSlice, robot, pose_goals, gtsam::Values(), + /*pose_goals_as_constraints=*/true); + }; + + // Total absolute travel of the gantry joints from their zero prior mean. + auto gantry_travel = [&](const Values& result) { + double travel = 0.0; + for (const auto& name : gantry_joints) + travel += std::fabs( + result.at(JointAngleKey(robot.joint(name)->id(), k))); + return travel; + }; + + const Values tight = solve(0.1); + const Values loose = solve(10.0); + + // Both reach the goal pose; the looser gantry priors move the gantry more. + EXPECT(assert_equal(wTcom_goal, tight.at(PoseKey(ee_id, k)), 1e-3)); + EXPECT(assert_equal(wTcom_goal, loose.at(PoseKey(ee_id, k)), 1e-3)); + EXPECT(gantry_travel(tight) < gantry_travel(loose)); +} + int main() { TestResult tr; return TestRegistry::runAllTests(tr); diff --git a/gtdynamics/kinematics/tests/testPoseFactor.cpp b/gtdynamics/kinematics/tests/testPoseFactor.cpp index d9528a090..6868391d8 100644 --- a/gtdynamics/kinematics/tests/testPoseFactor.cpp +++ b/gtdynamics/kinematics/tests/testPoseFactor.cpp @@ -34,7 +34,7 @@ using gtsam::Pose3; using gtsam::Rot3; using gtsam::Values; using gtsam::Vector6; -using gtsam::Z_6x1; +using gtsam::Vector6::Zero(); using gtsam::noiseModel::Gaussian; namespace example { diff --git a/gtdynamics/mechanics/tests/testWrenchPlanarFactor.cpp b/gtdynamics/mechanics/tests/testWrenchPlanarFactor.cpp index 5e1105126..58d96c975 100644 --- a/gtdynamics/mechanics/tests/testWrenchPlanarFactor.cpp +++ b/gtdynamics/mechanics/tests/testWrenchPlanarFactor.cpp @@ -35,7 +35,7 @@ gtsam::noiseModel::Gaussian::shared_ptr cost_model = gtsam::noiseModel::Gaussian::Covariance(gtsam::I_3x3); const DynamicsSymbol wrench_key = WrenchKey(2, 1, 777); gtsam::Pose3 kMj; // doesn't matter -auto [joint, links] = make_joint(kMj, gtsam::Z_6x1); +auto [joint, links] = make_joint(kMj, gtsam::Vector6::Zero()); } // namespace example // Test wrench planar factor for x-axis diff --git a/gtdynamics/statics/Statics.cpp b/gtdynamics/statics/Statics.cpp index fd90114f4..8c5cd1da1 100644 --- a/gtdynamics/statics/Statics.cpp +++ b/gtdynamics/statics/Statics.cpp @@ -43,7 +43,7 @@ Vector6 GravityWrench(const gtsam::Vector3 &gravity, double mass, Vector6 ResultantWrench(const std::vector &wrenches, gtsam::OptionalMatrixVecType H) { - Vector6 sum = gtsam::Z_6x1; + Vector6 sum = gtsam::Vector6::Zero(); const size_t n = wrenches.size(); for (size_t i = 0; i < n; i++) { sum += wrenches[i]; diff --git a/gtdynamics/universal_robot/Link.cpp b/gtdynamics/universal_robot/Link.cpp index 3ceb6a714..662f8f555 100644 --- a/gtdynamics/universal_robot/Link.cpp +++ b/gtdynamics/universal_robot/Link.cpp @@ -64,7 +64,7 @@ gtsam::Vector6_ Link::wrenchConstraint( } // Calculate resultant wrench. - gtsam::Vector6_ error(gtsam::Z_6x1); + gtsam::Vector6_ error(gtsam::Vector6::Zero()); for (const auto& wrench : wrenches) { error += wrench; } diff --git a/gtdynamics/utils/Initializer.cpp b/gtdynamics/utils/Initializer.cpp index 6b014816f..cf458bfe6 100644 --- a/gtdynamics/utils/Initializer.cpp +++ b/gtdynamics/utils/Initializer.cpp @@ -96,7 +96,7 @@ Values Initializer::InitializePosesAndJoints( // Compute forward dynamics to obtain remaining link poses. Pose3 wTl_i_processed = AddGaussianNoiseToPose(wTl_i, sampler); InsertPose(&fk_input, robot.link(link_name)->id(), wTl_i_processed); - InsertTwist(&fk_input, robot.link(link_name)->id(), gtsam::Z_6x1); + InsertTwist(&fk_input, robot.link(link_name)->id(), gtsam::Vector6::Zero()); auto fk_results = robot.forwardKinematics(fk_input, 0, link_name); for (auto&& link : robot.links()) { @@ -143,7 +143,7 @@ Values Initializer::InitializeSolutionInterpolation( link_name + " is fixed."); } InsertPose(&init_vals, link->id(), t, wTl_t); - InsertTwist(&init_vals, link->id(), t, gtsam::Z_6x1); + InsertTwist(&init_vals, link->id(), t, gtsam::Vector6::Zero()); init_vals = robot.forwardKinematics(init_vals, t, link_name); const Values zero_values = diff --git a/gtdynamics/utils/Trajectory.cpp b/gtdynamics/utils/Trajectory.cpp index 4c86894d4..6e9795bed 100644 --- a/gtdynamics/utils/Trajectory.cpp +++ b/gtdynamics/utils/Trajectory.cpp @@ -27,7 +27,7 @@ using gtsam::NonlinearFactorGraph; using gtsam::Point3; using gtsam::SharedNoiseModel; using gtsam::Values; -using gtsam::Z_6x1; +using gtsam::Vector6::Zero(); using std::map; using std::string; using std::to_string; diff --git a/python/tests/test_forward_inv_kinematics.py b/python/tests/test_forward_inv_kinematics.py index cf8669306..57baff0cb 100644 --- a/python/tests/test_forward_inv_kinematics.py +++ b/python/tests/test_forward_inv_kinematics.py @@ -146,6 +146,44 @@ def test_forward_inv_kinematics(self): got = gtd.JointAngle(result, j.id(), k) self.assertAlmostEqual(got, self.angle_rad[j.name()], delta=1e-2) + def test_gantry_prior_sigma(self): + """Looser gantry prior sigmas let the gantry absorb more of the motion.""" + k = self.k + # Fix the gantry base so the gantry joints lie in the chain to the EE. + robot = gtd.CreateRobotFromFile( + str(Path(gtd.URDF_PATH) / "bar_lab.urdf")).fixLink("columns") + link6 = robot.link("robot1_link_6") + gantry_joints = ["bridge1_joint_EA_X", "robot1_joint_EA_Y", + "robot1_joint_EA_Z"] + + # Reachable goal from a config that uses the gantry (so it is redundant). + config = { + "bridge1_joint_EA_X": 2.0, "robot1_joint_EA_Y": 1.5, + "robot1_joint_EA_Z": 0.5, "robot1_joint_1": 0.3, + "robot1_joint_2": 0.4, "robot1_joint_3": -0.5, + "robot1_joint_4": 0.2, "robot1_joint_5": 0.6, "robot1_joint_6": -0.3, + } + q = gtsam.Values() + for j in robot.joints(): + gtd.InsertJointAngle(q, j.id(), k, config.get(j.name(), 0.0)) + fk = robot.forwardKinematics(q, k, "columns") + pose_goals = {k: gtd.PoseGoal(link6, gtsam.Pose3(), + gtd.Pose(fk, link6.id(), k))} + slice0 = gtd.Slice(k) + + # Total gantry travel from the zero prior mean for a given gantry sigma. + def gantry_travel(gantry_sigma): + params = gtd.KinematicsParameters() + for name in gantry_joints: + params.setJointPriorSigma(robot.joint(name).key(), gantry_sigma) + result = gtd.Kinematics(params).inverse( + slice0, robot, pose_goals, gtsam.Values(), True) + return sum(abs(gtd.JointAngle(result, robot.joint(n).id(), k)) + for n in gantry_joints) + + # Looser gantry priors -> the gantry moves more to reach the goal. + self.assertLess(gantry_travel(0.1), gantry_travel(10.0)) + diff --git a/tests/testObjectiveFactors.cpp b/tests/testObjectiveFactors.cpp index 6f8fd05bc..4ec728ccf 100644 --- a/tests/testObjectiveFactors.cpp +++ b/tests/testObjectiveFactors.cpp @@ -42,7 +42,7 @@ TEST(ObjectiveFactors, PoseAndTwist) { EXPECT_LONGS_EQUAL(1, graph.size()); graph.add(LinkObjectives(id, k) .pose(Pose3(), kModel6) - .twist(gtsam::Z_6x1, kModel6)); + .twist(gtsam::Vector6::Zero(), kModel6)); EXPECT_LONGS_EQUAL(3, graph.size()); } @@ -50,8 +50,8 @@ TEST(ObjectiveFactors, TwistWithDerivatives) { NonlinearFactorGraph graph; constexpr int id = 5, k = 777; graph.add(LinkObjectives(id, k) - .twist(gtsam::Z_6x1, kModel6) - .twistAccel(gtsam::Z_6x1, kModel6)); + .twist(gtsam::Vector6::Zero(), kModel6) + .twistAccel(gtsam::Vector6::Zero(), kModel6)); EXPECT_LONGS_EQUAL(2, graph.size()); } diff --git a/tests/testSpiderWalking.cpp b/tests/testSpiderWalking.cpp index 240322a8e..903cc7006 100644 --- a/tests/testSpiderWalking.cpp +++ b/tests/testSpiderWalking.cpp @@ -116,7 +116,7 @@ TEST(testSpiderWalking, WholeEnchilada) { objectives.add( LinkObjectives(base_link->id(), k) .pose(Pose3(Rot3(), Point3(0, 0.0, 0.5)), Isotropic::Sigma(6, 5e-5)) - .twist(gtsam::Z_6x1, Isotropic::Sigma(6, 5e-5))); + .twist(gtsam::Vector6::Zero(), Isotropic::Sigma(6, 5e-5))); } // Add link and joint boundary conditions to FG.