void inPointCallback(const geometry_msgs::Point& pt_msg) {
    Eigen::Affine3d des_gripper1_wrt_base;

    g_des_point(0) = pt_msg.x;
    g_des_point(1) = pt_msg.y;
    g_des_point(2) = pt_msg.z;
    cout << "received des point = " << g_des_point.transpose() << endl;
    g_des_gripper_affine1.translation() = g_des_point;
    //convert this to base coords:
    g_des_gripper1_wrt_base = g_affine_lcamera_to_psm_one.inverse() * g_des_gripper_affine1;
    //try computing IK:
    if (g_ik_solver.ik_solve(g_des_gripper1_wrt_base)) {
        ROS_INFO("found IK soln");
        g_got_new_pose = true;
        g_q_vec1_start = g_q_vec1_goal;
        g_q_vec1_goal = g_ik_solver.get_soln();
        cout << g_q_vec1_goal.transpose() << endl;
        g_trajectory_point1 = g_trajectory_point2; //former goal is new start

        for (int i = 0; i < 6; i++) {
            g_trajectory_point2.positions[i] = g_q_vec1_goal[i]; //leave psm2 angles alone; just update psm1 goal angles
        }
        //gripper_affines_wrt_camera.push_back(affine_gripper_frame_wrt_camera_frame_);
        //    des_trajectory.joint_names.push_back("right_s0"); //yada-yada should fill in names
        g_des_trajectory.header.stamp = ros::Time::now();

        g_des_trajectory.points[0] = g_des_trajectory.points[1]; //former goal is new start
        g_des_trajectory.points[1] = g_trajectory_point2;



        // copy traj to goal:
        g_goal.trajectory = g_des_trajectory;
    } else {
        ROS_WARN("NO IK SOLN FOUND");
    }

}
int main(int argc, char** argv) {
    ros::init(argc, argv, "test_cart_path_planner_lib");
    ros::NodeHandle nh; //standard ros node handle   

    ROS_INFO("instantiating an ArmMotionInterface: ");
    ArmMotionInterface armMotionInterface(&nh);


    //can do this, if needed: A = cartTrajPlanner.get_fk_Affine_from_qvec(Vectorq7x1 q_vec)    

    cout << "instantiating a traj streamer" << endl; // enter 1:";
    //cin>>ans;
    // let the streamer be owned by "main"
    Baxter_traj_streamer baxter_traj_streamer(&nh); //instantiate a Baxter_traj_streamer object and pass in pointer to nodehandle for constructor to use  
    // warm up the joint-state callbacks;
    cout << "warming up callbacks..." << endl;
    for (int i = 0; i < 100; i++) {
        ros::spinOnce();
        //cout<<"spin "<<i<<endl;
        ros::Duration(0.01).sleep();
    }
    cout << "getting current right-arm pose:" << endl;
    g_q_vec_right_arm[0] = 1000;
    while (fabs(g_q_vec_right_arm[0]) > 3) { // keep trying until see viable value populated by fnc
        g_q_vec_right_arm = baxter_traj_streamer.get_qvec_right_arm();
        ros::spinOnce();
        ros::Duration(0.01).sleep();
    }
    cout << "r_arm state:" << g_q_vec_right_arm.transpose() << endl;

    //let's leave this in main:

    ROS_INFO("instantiating an action client of trajActionServer");
    actionlib::SimpleActionClient<baxter_traj_streamer::trajAction> traj_streamer_action_client("trajActionServer", true);

    // attempt to connect to the server:
    ROS_INFO("waiting for server trajActionServer: ");
    bool server_exists = false;
    while ((!server_exists)&&(ros::ok())) {
        server_exists = traj_streamer_action_client.waitForServer(ros::Duration(5.0)); // wait for up to 5 seconds
        ros::spinOnce();
        ros::Duration(0.5).sleep();
        ROS_INFO("retrying...");
    }

    // something odd in above: does not seem to wait for 5 seconds, but returns rapidly if server not running
    // if (!server_exists) {
    //     ROS_WARN("could not connect to server; will wait forever");
    //    return 0; // bail out; optionally, could print a warning message and retry
    //}
    //server_exists = action_client.waitForServer(); //wait forever 

    ROS_INFO("connected to action server"); // if here, then we connected to the server;    


    bool unpackok;
    Eigen::Vector3d delta_p;
    bool is_valid;
    bool finished_before_timeout;
    baxter_traj_streamer::trajGoal goal;
    Vectorq7x1 q_vec_goal_vq7; //goal pose in joint space, expressed as a 7x1 vector
    moveit_msgs::DisplayTrajectory display_trajectory;
    ros::Publisher  display_traj_pub = nh.advertise<moveit_msgs::DisplayTrajectory>("/preview_traj", 1, true);

    // start servicing requests:
    while (ros::ok()) {
        g_q_vec_right_arm = baxter_traj_streamer.get_qvec_right_arm(); // update the current sensed arm angles
        //decide if should start processing a new request:
        if (armMotionInterface.newRqst()&&!armMotionInterface.isBusy()) {
            armMotionInterface.setNewRqst(false); //g_received_new_request_=false; // reset trigger to receive a new request
            armMotionInterface.setIsBusy(true); //g_busy_working_on_a_request_= true; // begin processing new request
        }
        if (armMotionInterface.isBusy()) {
            switch (armMotionInterface.get_cmd_mode()) {
                case ARM_TEST_MODE:
                    ROS_INFO("responding to request TEST_MODE: ");
                    cout << "unpacking q_vec_start from request message..." << endl;
                    unpackok = armMotionInterface.unpack_qstart();
                    if (unpackok) {
                        cout << "start qvec rqst: " << armMotionInterface.get_start_qvec().transpose() << endl;
                    }
                    unpackok = armMotionInterface.unpack_qend();
                    if (unpackok) {
                        cout << "end qvec rqst: " << armMotionInterface.get_end_qvec().transpose() << endl;
                    }
                    //reply w/ populating q_vec_start in response:

                    armMotionInterface.setIsBusy(false);
                    break;
                    
                case ARM_PLAN_JSPACE_PATH_CURRENT_TO_QGOAL: 
                    ROS_INFO("case ARM_PLAN_JSPACE_PATH_CURRENT_TO_QGOAL");
                    //get the start q_vec = current arm pose:
                    cout << "getting current right-arm pose:" << endl;
                    g_q_vec_right_arm[0] = 1000;  //Vectorq7x1 g_q_vec_right_arm;
                    while (fabs(g_q_vec_right_arm[0]) > 3) { // keep trying until see viable value populated by fnc
                        g_q_vec_right_arm = baxter_traj_streamer.get_qvec_right_arm();
                        ros::spinOnce();
                        ros::Duration(0.01).sleep();
                    }
                    //get the goal q_vec, per request message:
                    armMotionInterface.unpack_qend();
                    q_vec_goal_vq7= armMotionInterface.get_end_qvec(); //need to convert from VectorXd to Vectorq7x1
                    is_valid = armMotionInterface.plan_jspace_path_qstart_to_qend(g_q_vec_right_arm,q_vec_goal_vq7);
                    if (is_valid) ROS_INFO("computed valid path");
                    else ROS_INFO("no valid path found");
                    armMotionInterface.setIsBusy(false);
                    break;                    
                

                case ARM_PLAN_PATH_CURRENT_TO_PRE_POSE:
                    ROS_INFO("responding to request PLAN_PATH_CURRENT_TO_PRE_POSE");
                    armMotionInterface.plan_path_to_predefined_pre_pose();
                    armMotionInterface.setIsBusy(false);
                    break;

                case ARM_PLAN_PATH_CURRENT_TO_GOAL_POSE:
                    cout << "getting current right-arm pose:" << endl;
                    g_q_vec_right_arm[0] = 1000;
                    while (fabs(g_q_vec_right_arm[0]) > 3) { // keep trying until see viable value populated by fnc
                        g_q_vec_right_arm = baxter_traj_streamer.get_qvec_right_arm();
                        ros::spinOnce();
                        ros::Duration(0.01).sleep();
                    }
                    //armMotionInterface.unpack_qstart(); // fills in q_vec_start_rqst_--no...use current arm pose
                    armMotionInterface.unpack_goal_pose(); //fills in a_flange_end_;  should check return status   
                    //    bool plan_path_qstart_to_Agoal(Vectorq7x1 q_start); // provide q_start; assumes use of a_flange_end_ and fills in g_optimal_path 
                    is_valid = armMotionInterface.plan_path_qstart_to_Agoal(g_q_vec_right_arm);
                    if (is_valid) ROS_INFO("computed valid path");
                    else ROS_INFO("no valid path found");
                    armMotionInterface.setIsBusy(false);
                    break;
                    
                case ARM_DISPLAY_TRAJECTORY:
                    cout << "getting current joint states:" << endl;
                    g_q_vec_right_arm[0] = 1000;
                    while (fabs(g_q_vec_right_arm[0]) > 3) { // keep trying until see viable value populated by fnc
                        g_q_vec_right_arm = baxter_traj_streamer.get_qvec_right_arm();
                        ros::spinOnce();
                        ros::Duration(0.01).sleep();
                    } 
                    //if here, then joint_states_ is valid
                    //populate the moveit message to preview the trajectory plan;
                    //display_trajectory.model_id = "robot_description"; // not sure what goes here;  "baxter"??
                    //declare joint_states_ as start state of display
                    display_trajectory.trajectory_start.joint_state = baxter_traj_streamer.get_joint_states(); // get the joint states from Baxter; 
                    baxter_traj_streamer.stuff_trajectory(g_optimal_path, g_des_trajectory);//convert planned path to trajectory
                    display_trajectory.trajectory.resize(1); //display only 1 trajectory
                    display_trajectory.trajectory[0].joint_trajectory = g_des_trajectory; //the one we care about
                    display_traj_pub.publish(display_trajectory); // and publish this to topic "/preview_traj"
                    armMotionInterface.setIsBusy(false);
                    break;

                case ARM_DESCEND_20CM:
                    ROS_INFO("responding to request DESCEND_20CM");
                    delta_p << 0, 0, -0.2; //specify delta-p for a 20cm descent
                    // find a joint-space path to do this, holding R fixed

                    cout << "getting current right-arm pose:" << endl;
                    g_q_vec_right_arm[0] = 1000;
                    while (fabs(g_q_vec_right_arm[0]) > 3) { // keep trying until see viable value populated by fnc
                        g_q_vec_right_arm = baxter_traj_streamer.get_qvec_right_arm();
                        ros::spinOnce();
                        ros::Duration(0.01).sleep();
                    }

                    is_valid = armMotionInterface.plan_cartesian_delta_p(g_q_vec_right_arm, delta_p);
                    armMotionInterface.setPathValid(is_valid);
                    armMotionInterface.incrementPathID();
                    armMotionInterface.setIsBusy(false);
                    break;
                case ARM_DEPART_20CM:
                    ROS_INFO("responding to request ARM_DEPART_20CM");
                    delta_p << 0, 0, 0.2; //specify delta-p for a 20cm descent
                    // find a joint-space path to do this, holding R fixed

                    cout << "getting current right-arm pose:" << endl;
                    g_q_vec_right_arm[0] = 1000;
                    while (fabs(g_q_vec_right_arm[0]) > 3) { // keep trying until see viable value populated by fnc
                        g_q_vec_right_arm = baxter_traj_streamer.get_qvec_right_arm();
                        ros::spinOnce();
                        ros::Duration(0.01).sleep();
                    }

                    is_valid = armMotionInterface.plan_cartesian_delta_p(g_q_vec_right_arm, delta_p);
                    armMotionInterface.setPathValid(is_valid);
                    armMotionInterface.incrementPathID();
                    armMotionInterface.setIsBusy(false);
                    break;

                    //case DEPART_20CM:
                    //case CART_MOVE_DELTA_P: unpack_delta_p()...
                    //case PLAN_PATH_QSTART_TO_ADES:
                    //case PLAN_PATH_QSTART_TO_QGOAL:
                    //case PLAN_PATH_ASTART_TO_QGOAL:

                case ARM_EXECUTE_PLANNED_PATH: //assumes there is a valid planned path in g_optimal_path
                    ROS_INFO("responding to request EXECUTE_PLANNED_PATH");
                    if (armMotionInterface.getPathValid()) {
                        // convert path to a trajectory:
                        baxter_traj_streamer.stuff_trajectory(g_optimal_path, g_des_trajectory); //convert from vector of 7dof poses to trajectory message   
                        goal.trajectory = g_des_trajectory;
                        ROS_INFO("sending action request to traj streamer node");
                        traj_streamer_action_client.sendGoal(goal, &doneCb); // we could also name additional callback functions here, if desired
                        //    action_client.sendGoal(goal, &doneCb, &activeCb, &feedbackCb); //e.g., like this

                        finished_before_timeout = traj_streamer_action_client.waitForResult(ros::Duration(20.0));

                        if (!finished_before_timeout) {
                            ROS_WARN("EXECUTE_PLANNED_PATH: giving up waiting on result");
                            // should set status in service request here...
                        } else {
                            ROS_INFO("finished before timeout");
                            // should set status in service request here...
                        }
                    } else {
                        ROS_WARN("requested move without valid path! doing nothing");
                    }
                    armMotionInterface.setIsBusy(false);
                    break;
                default:
                    ROS_WARN("this command mode is not defined: %d", armMotionInterface.get_cmd_mode());
                    //clean up/terminate:
                    armMotionInterface.setIsBusy(false);
            }
        }
        ros::spinOnce();
        //cout<<"main loop..."<<endl;
        ros::Duration(0.1).sleep(); //don't consume much cpu time if not actively working on a command
    }

    return 0;
}
int main(int argc, char **argv) {
    ros::init(argc, argv, "baxter_kinematics_test_main");
    ros::NodeHandle nh;
    ros::Subscriber joint_state_sub = nh.subscribe("robot/joint_states", 1, jointStatesCb);
    q_vec_right_arm<< 0,0,0,0,0,0,0;
    q_in << 0,0,0,0,0,0,0;
    //q_in << 0.1, 0.2, 0.3, 0.4, 0.5, 0.6;
    tf::TransformListener tfListener;
    tf::StampedTransform tfResult;
    
// set up and initialize joint publishers:
  ros::Publisher pub_right, pub_left; //Create a 'publisher' object
  baxter_core_msgs::JointCommand right_cmd,left_cmd;  // define instances of these message types, to control arms
  left_cmd.mode = 1; // set the command modes to "position"
  right_cmd.mode = 1;

// define the joint angles 0-6 to be right arm, from shoulder out to wrist;
  right_cmd.names.push_back("right_s0");
  right_cmd.names.push_back("right_s1");
  right_cmd.names.push_back("right_e0");
  right_cmd.names.push_back("right_e1");
  right_cmd.names.push_back("right_w0");
  right_cmd.names.push_back("right_w1");
  right_cmd.names.push_back("right_w2");
// same order for left arm
  left_cmd.names.push_back("left_s0");
  left_cmd.names.push_back("left_s1");
  left_cmd.names.push_back("left_e0");
  left_cmd.names.push_back("left_e1");
  left_cmd.names.push_back("left_w0");
  left_cmd.names.push_back("left_w1");
  left_cmd.names.push_back("left_w2");

  // do push-backs to establish desired vector size with valid joint angles
  for (int i=0;i<7;i++) {
     right_cmd.command.push_back(0.0); // start commanding 0 angle for right-arm 7 joints
     left_cmd.command.push_back(0.0); // start commanding 0 angle for left-arm 7 joints
   }

//set up the publisher to publish to /robot/limb/right/joint_command with a queue size of 1
  pub_right = nh.advertise<baxter_core_msgs::JointCommand>("/robot/limb/right/joint_command", 1); 
//do same for left limb:
  pub_left = nh.advertise<baxter_core_msgs::JointCommand>("/robot/limb/left/joint_command", 1);    
    
   bool tferr=true;
    ROS_INFO("waiting for tf between base and right_hand...");
    while (tferr) {
        tferr=false;
        try {
                //try to lookup transform from target frame "odom" to source frame "map"
            //The direction of the transform returned will be from the target_frame to the source_frame. 
             //Which if applied to data, will transform data in the source_frame into the target_frame. See tf/CoordinateFrameConventions#Transform_Direction
                tfListener.lookupTransform("right_arm_mount","right_hand", ros::Time(0), tfResult);
            } catch(tf::TransformException &exception) {
                ROS_ERROR("%s", exception.what());
                tferr=true;
                ros::Duration(0.5).sleep(); // sleep for half a second
                ros::spinOnce();                
            }   
    }
    ROS_INFO("tf is good");
    //right_upper_shoulder is located at bottom of first shoulder jnt
    // from now on, tfListener will keep track of transforms    
    tfListener.lookupTransform("right_arm_mount", "right_lower_shoulder", ros::Time(0), tfResult);
    tf::Vector3 pos = tfResult.getOrigin();
    ROS_INFO("shoulder x,y, z = %f, %f, %f",pos[0],pos[1],pos[2]);

    tfListener.lookupTransform("right_arm_mount","right_lower_elbow", ros::Time(0), tfResult);
    pos = tfResult.getOrigin();
    ROS_INFO("elbow x,y, z = %f, %f, %f",pos[0],pos[1],pos[2]);
    tfListener.lookupTransform("right_arm_mount","right_lower_forearm",  ros::Time(0), tfResult);
    pos = tfResult.getOrigin();
    ROS_INFO("wrist x,y, z = %f, %f, %f",pos[0],pos[1],pos[2]);     
    tfListener.lookupTransform("right_arm_mount","right_hand",  ros::Time(0), tfResult);
    pos = tfResult.getOrigin();
    ROS_INFO("hand x,y, z = %f, %f, %f",pos[0],pos[1],pos[2]);   
    
    Baxter_fwd_solver baxter_fwd_solver; //instantiate a forward-kinematics solver
    Baxter_IK_solver baxter_IK_solver;  // instantiate an IK solver
    
    
    //Baxter_IK_solver ik_solver;
    Eigen::Affine3d A_fwd_DH;
    Eigen::Matrix4d A_wrist,A_elbow,A_shoulder,A_flange;    
    Eigen::Matrix3d R_hand;
    std::cout << "==== Test for Baxter kinematics solver ====" << std::endl;

    Eigen::Matrix3d R_flange_wrt_right_arm_mount;
    Eigen::Vector3d wrist_pt_wrt_right_arm_frame1;
    Eigen::Vector3d w_err;
    int ans;
    int nsolns;
    bool valid;
    Vectorq7x1 q_vec_display,q_precise,q_soln_w_wrist_precise;
    std::vector<Vectorq7x1> q_solns;   
  // try new fnc:     
    //int Baxter_IK_solver::ik_solve_approx_wrt_torso_given_qs0(Eigen::Affine3d const& desired_hand_pose_wrt_torso,double q_s0, std::vector<Vectorq7x1> &q_solns) {
        q_snapshot = q_vec_right_arm;
        cout<<"qvec right arm: "<<endl;
        cout<< q_snapshot.transpose() <<endl;
        // from this test pose, establish a viable hand frame:
    Eigen::Affine3d Affine_flange_wrt_torso = baxter_fwd_solver.fwd_kin_flange_wrt_torso_solve(q_snapshot); //fwd_kin_solve
    
    Eigen::Affine3d Affine_flange_wrt_arm_mount = 
            baxter_fwd_solver.transform_affine_from_torso_frame_to_arm_mount_frame(Affine_flange_wrt_torso);
    R_flange_wrt_right_arm_mount = Affine_flange_wrt_arm_mount.linear();
    nsolns = baxter_IK_solver.ik_solve_approx_wrt_torso_given_qs0(Affine_flange_wrt_torso,q_snapshot[0],q_solns);
    cout<<"ik_solve_approx_wrt_torso_given_qs0 found nsolns = "<<nsolns<<endl;
    for (int i=0;i<nsolns;i++) {
        cout<<q_solns[i].transpose()<<endl;
    }
    Vectorq7x1 q_approx;
    Vectorq7x1 q_7dof_precise;
    cout<<"result of new fnc improve_7dof_soln:"<<endl;    
    for (int i=0;i<nsolns;i++) {
        q_approx = q_solns[i];
        valid = baxter_IK_solver.improve_7dof_soln(Affine_flange_wrt_arm_mount, q_approx, q_7dof_precise); 
        cout<<q_7dof_precise.transpose()<<endl;        
    }    
    //q_precise = q_solns[0]; // pick one and improve on it;
    // need to do this for each soln, e.g. 4 solns per q_s0;
    //double w_err_norm= baxter_IK_solver.precise_soln_q123(Affine_flange_wrt_arm_mount,q_solns[0], q_precise);
    //cout<<"q123 soln after Jacobian iterations: "<<endl;
    //cout<<q_precise.transpose()<<endl;
    //correspondingly, do this for each of the above improved q123 solns   
    //baxter_IK_solver.update_spherical_wrist(q_precise,R_flange_wrt_right_arm_mount, q_soln_w_wrist_precise);
    //cout<<"soln after update wrist: "<<endl;
    //cout<<q_soln_w_wrist_precise.transpose()<<endl;
    
    //valid = baxter_IK_solver.improve_7dof_soln(Affine_flange_wrt_arm_mount, q_approx, q_7dof_precise); 
    //cout<<"result of new fnc improve_7dof_soln:"<<endl;
    //cout<<q_7dof_precise.transpose()<<endl;
    //baxter_IK_solver.solve_spherical_wrist(q_precise,R_flange_wrt_right_arm_mount, q_soln_w_wrist_precise); 
    //cout<<"solns after Jacobian iterations: "<<endl;
    //for (int i=0;i<q_solns_w_wrist_precise.size();i++) {
    //    cout<<q_solns_w_wrist_precise[i].transpose()<<endl;
    //}    
    
    
    
    while (ros::ok()) 
    {
        cout<<"enter 1 to initiate: "; //pause here to allow user to move joint angles to desired test pose
        cin>>ans;
        for (int i=0;i<10;i++) { // spin to get current joint angles
            ros::spinOnce();
            ros::Duration(0.1).sleep(); //sleep for 2 seconds
        }
        q_snapshot = q_vec_right_arm;
        cout<<"qvec right arm: "<<endl;
        cout<< q_snapshot.transpose() <<endl;
        // from this test pose, establish a viable hand frame:
        A_fwd_DH = baxter_fwd_solver.fwd_kin_flange_wrt_r_arm_mount_solve(q_snapshot); //fwd_kin_solve

        cout<<"TRYING NEW FNC ik_solve_approx"<<endl;
        nsolns = baxter_IK_solver.ik_solve_approx(A_fwd_DH,q_solns);
        cout<<"num solns: "<<nsolns<<endl;
        cout<<"commanding these solutions..."<<endl;

 
       for (int isoln=0; isoln<nsolns; isoln++) {
               q_vec_display= q_solns[isoln];
               for (int j=0;j<7;j++) {
                    right_cmd.command[j] = q_vec_display[j];    
                }

            pub_right.publish(right_cmd); //publish jnt cmds to right arm
            cout<<"soln: "<<q_vec_display.transpose()<<endl;
            ros::Duration(2).sleep(); //sleep for 2 seconds
            ros::spinOnce();            
        }
    
    ros::Duration(2).sleep(); //sleep for 2 seconds
    ros::spinOnce();

    }
    return 0;
}