/** * raven_homing() * * This function is called 1000 times per second during INIT mode * * \param device0 Which (top level) device to home (usually only one device per system) * \param currParams Current parameters (for Run Level) * \param begin_homing Flag to start the homing process * \ingroup Control * * \brief Move to hard stops in controled way, "zero" the joint value, and then move to "home" position * * This function operates in two phases: * -# Discover joint position by running to hard stop. Using PD control (I term zero'd) we move the joint at a smooth rate until * current increases which indicates hitting hard mechanical stop. * -# Move joints to "home" position. In this phase the robot moves from the joint limits to a designated pose in the center of the workspace. * \todo Homing limits should be Amps not DAC units (see homing() ). * \todo Eliminate or comment out Enders Game code!! */ int raven_homing(struct device *device0, struct param_pass *currParams, int begin_homing) { static int homing_inited = 0; static unsigned long int delay, delay2; struct DOF *_joint = NULL; struct mechanism* _mech = NULL; int i=0,j=0; // Only run in init mode if ( ! (currParams->runlevel == RL_INIT && currParams->sublevel == SL_AUTO_INIT )) { homing_inited = 0; delay = gTime; return 0; // return if we are in the WRONG run level (PLC state) } // Wait a short time for amps to turn on if (gTime - delay < 1000) { return 0; } // Initialize the homing sequence. if (begin_homing || !homing_inited) // only do this the first time through { // Zero out joint torques, and control inputs. Set joint.state=not_ready. _mech = NULL; _joint = NULL; while (loop_over_joints(device0, _mech, _joint, i,j) ) // foreach (joint) { _joint->tau_d = 0; _joint->mpos_d = _joint->mpos; _joint->jpos_d = _joint->jpos; _joint->jvel_d = 0; _joint->state = jstate_not_ready; if (is_toolDOF(_joint)) jvel_PI_control(_joint, 1); // reset PI control integral term homing_inited = 1; } log_msg("Homing sequence initialized"); } // Specify motion commands _mech = NULL; _joint = NULL; while ( loop_over_joints(device0, _mech, _joint, i,j) ) { // Initialize tools first. if ( is_toolDOF(_joint) || tools_ready( &(device0->mech[i]) ) ) { homing(_joint); } } //Inverse Cable Coupling invCableCoupling(device0, currParams->runlevel); // Do PD control on all joints _mech = NULL; _joint = NULL; while ( loop_over_joints(device0, _mech, _joint, i,j) ) { mpos_PD_control( _joint ); } // Calculate output DAC values TorqueToDAC(device0); // Check homing conditions and set joint angles appropriately. _mech = NULL; _joint = NULL; while ( loop_over_joints(device0, _mech, _joint, i,j) ) { struct DOF * _joint = &(_mech->joint[j]); ///\todo is this line necessary? // Check to see if we've reached the joint limit. if( check_homing_condition(_joint) ) { log_msg("Found limit on joint %d cmd: %d \t", _joint->type, _joint->current_cmd, DOF_types[_joint->type].DAC_max); _joint->state = jstate_hard_stop; _joint->current_cmd = 0; stop_trajectory(_joint); log_msg("joint %d checked ",j); } // For each mechanism, check to see if the mech is finished homing. if ( j == (MAX_DOF_PER_MECH-1) ) { /// if we're homing tools, wait for tools to be finished if (( !tools_ready(_mech) && _mech->joint[TOOL_ROT].state==jstate_hard_stop && _mech->joint[WRIST ].state==jstate_hard_stop && _mech->joint[GRASP1 ].state==jstate_hard_stop ) || ( tools_ready( _mech ) && _mech->joint[SHOULDER].state==jstate_hard_stop && _mech->joint[ELBOW ].state==jstate_hard_stop && _mech->joint[Z_INS ].state==jstate_hard_stop )) { if (delay2==0) delay2=gTime; if (gTime > delay2 + 200) // wait 200 ticks for cables to settle down { set_joints_known_pos(_mech, !tools_ready(_mech) ); // perform second phase delay2 = 0; } } } } return 0; }
/** * \brief This function runs pi_control on joint velocity * \param device0 is robot_device struct defined in DS0.h * \param currParams is param_pass struct defined in DS1.h * \return 0 * * This function: * 1. if pedal is down or RL_INIT and SL_AUTO_INIT, it Loops over all the joints and all the mechanisim to initialize * velocity trajectory by calling start_trajectory() which is in trajectory.cpp * 2. calls update_linear_sinusoid_velocity_trajectory() to get the desired joint velocities * 3. calls jvel_PI_control() to run PI control, which is in pid_control.cpp * 4. calls TorqueToDac() to apply torque on DAC * It sets all the joint torques to zero if pedal is not down or not (RL_INIT and SL_AUTO_INIT) * */ int raven_joint_velocity_control(struct device *device0, struct param_pass *currParams) { static int controlStart; static unsigned long int delay=0; // Run velocity control if ( currParams->runlevel == RL_PEDAL_DN || ( currParams->runlevel == RL_INIT && currParams->sublevel == SL_AUTO_INIT )) { // delay the start of control for 300ms b/c the amps have to turn on. if (gTime - delay < 800) return 0; for (int i=0; i < NUM_MECH; i++) { for (int j = 0; j < MAX_DOF_PER_MECH; j++) { struct DOF * _joint = &(device0->mech[i].joint[j]); if (device0->mech[i].type == GOLD_ARM) { // initialize velocity trajectory if (!controlStart) start_trajectory(_joint); // Get the desired joint velocities update_linear_sinusoid_velocity_trajectory(_joint); // Run PI control jvel_PI_control(_joint, !controlStart); } else { _joint->tau_d = 0; } } } if (!controlStart) controlStart = 1; // Convert joint torque to DAC value. TorqueToDAC(device0); } else { delay=gTime; controlStart = 0; for (int i=0; i < NUM_MECH; i++) for (int j = 0; j < MAX_DOF_PER_MECH; j++) { device0->mech[i].joint[j].tau_d=0; } TorqueToDAC(device0); } return 0; }