Example use of I2CTransaction class. In this example, the master mbed is talking to 3 legs of the SIPPC3B robot.
LegInterface.cpp
- Committer:
- symbiotic
- Date:
- 2014-06-10
- Revision:
- 4:5f7d38d0e22d
- Parent:
- 3:8e7471af3453
- Child:
- 5:86f1cd6657de
File content as of revision 4:5f7d38d0e22d:
/* Interface for communication to the set of legs for the OU SIPPC Robot (version 3B and beyond). Note: this interface is talking to very custom hardware. As a result, it serves more as an example of how to use the I2CTransaction library. Author: Andrew H. Fagg (May, 2014) More documentation to come... */ #include "LegInterface.h" const int LegInterface::LegAddress[] = {I2C_ADDR_WEST, I2C_ADDR_EAST, I2C_ADDR_SOUTH}; /** Constructor: create all of the packets that can be sent + the associated transactions */ LegInterface::LegInterface(Serial *pc) { // ESTOP transactions transactionEstop[LEG_W] = new I2CTransaction(I2C_ADDR_WEST, (char*) &legPacketEstop, 4); transactionEstop[LEG_E] = new I2CTransaction(I2C_ADDR_EAST, (char*) &legPacketEstop, 4); transactionEstop[LEG_S] = new I2CTransaction(I2C_ADDR_SOUTH, (char*) &legPacketEstop, 4); // Query state transactions legPacketQuery.type = nsPacketsLeg::QUERY_STATE; transactionQueryState[LEG_W] = new I2CTransaction(I2C_ADDR_WEST, (char*) &legPacketQuery, 4, (char*) &(legState[LEG_W]), sizeof(LegState_t)); transactionQueryState[LEG_E] = new I2CTransaction(I2C_ADDR_EAST, (char*) &legPacketQuery, 4, (char*) &(legState[LEG_E]), sizeof(LegState_t)); transactionQueryState[LEG_S] = new I2CTransaction(I2C_ADDR_SOUTH, (char*) &legPacketQuery, 4, (char*) &(legState[LEG_S]), sizeof(LegState_t)); // Query leg parameter transactions. Note: shared outgoing packet structure legPacketQueryLiftParams.type = nsPacketsLeg::GET_LIFT_PARAMS; transactionQueryLiftParams[LEG_W] = new I2CTransaction(I2C_ADDR_WEST, (char*) &legPacketQueryLiftParams, 4, (char *) &legLiftParams, sizeof(LegControlParams_t)); transactionQueryLiftParams[LEG_E] = new I2CTransaction(I2C_ADDR_EAST, (char*) &legPacketQueryLiftParams, 4, (char *) &legLiftParams, sizeof(LegControlParams_t)); transactionQueryLiftParams[LEG_S] = new I2CTransaction(I2C_ADDR_SOUTH, (char*) &legPacketQueryLiftParams, 4, (char *) &legLiftParams, sizeof(LegControlParams_t)); legPacketQueryWheelParams.type = nsPacketsLeg::GET_WHEEL_PARAMS; transactionQueryWheelParams[LEG_W] = new I2CTransaction(I2C_ADDR_WEST, (char*) &legPacketQueryWheelParams, 4, (char *) &legWheelParams, sizeof(LegControlParams_t)); transactionQueryWheelParams[LEG_E] = new I2CTransaction(I2C_ADDR_EAST, (char*) &legPacketQueryWheelParams, 4, (char *) &legWheelParams, sizeof(LegControlParams_t)); transactionQueryWheelParams[LEG_S] = new I2CTransaction(I2C_ADDR_SOUTH, (char*) &legPacketQueryWheelParams, 4, (char *) &legWheelParams, sizeof(LegControlParams_t)); // Set leg parameter transactions // Note: shared packet structure across transactions (since we are setting one at a time) legPacketSetLiftParams.type = nsPacketsLeg::SET_LIFT_PARAMS; transactionSetLiftParams[LEG_W] = new I2CTransaction(I2C_ADDR_WEST, (char*) &legPacketSetLiftParams, 4+sizeof(LegControlParams_t)); transactionSetLiftParams[LEG_E] = new I2CTransaction(I2C_ADDR_EAST, (char*) &legPacketSetLiftParams, 4+sizeof(LegControlParams_t)); transactionSetLiftParams[LEG_S] = new I2CTransaction(I2C_ADDR_SOUTH, (char*) &legPacketSetLiftParams, 4+sizeof(LegControlParams_t)); legPacketSetWheelParams.type = nsPacketsLeg::SET_WHEEL_PARAMS; transactionSetWheelParams[LEG_W] = new I2CTransaction(I2C_ADDR_WEST, (char*) &legPacketSetWheelParams, 4+sizeof(LegControlParams_t)); transactionSetWheelParams[LEG_E] = new I2CTransaction(I2C_ADDR_EAST, (char*) &legPacketSetWheelParams, 4+sizeof(LegControlParams_t)); transactionSetWheelParams[LEG_S] = new I2CTransaction(I2C_ADDR_SOUTH, (char*) &legPacketSetWheelParams, 4+sizeof(LegControlParams_t)); // Goal set legPacketSetGoal[LEG_W].type = nsPacketsLeg::SET_GOAL; transactionSetGoal[LEG_W] = new I2CTransaction(I2C_ADDR_WEST, (char*) &(legPacketSetGoal[LEG_W]), 4+sizeof(Goal_t)); legPacketSetGoal[LEG_E].type = nsPacketsLeg::SET_GOAL; transactionSetGoal[LEG_E] = new I2CTransaction(I2C_ADDR_EAST, (char*) &(legPacketSetGoal[LEG_E]), 4+sizeof(Goal_t)); legPacketSetGoal[LEG_S].type = nsPacketsLeg::SET_GOAL; transactionSetGoal[LEG_S] = new I2CTransaction(I2C_ADDR_SOUTH, (char*) &(legPacketSetGoal[LEG_S]), 4+sizeof(Goal_t)); // Other initialziations this->pc = pc; Leg leg = LEG_S; pc->printf("codes: %d %d\n\r", transactionSetLiftParams[leg]->getStatus(0), transactionSetLiftParams[leg]->getStatus(1)); } /** Attempt to send an estop to all legs. @param estop true = stop all motion; false = enable motion @return true = transaction successfully scheduled, false = prior attempt at sending had not completed. */ bool LegInterface::sendEstop(bool estop) { // Has the prior attempt at sending the estop completed? if(!transactionEstop[LEG_W]->completed() || !transactionEstop[LEG_E]->completed() || !transactionEstop[LEG_S]->completed()) { // No: do not attempt return false; } // Yes - configure the packet (all packets are the same in this case) legPacketEstop.type = estop?nsPacketsLeg::ESTOP_ON:nsPacketsLeg::ESTOP_OFF; // Schedule the transactions transactionEstop[LEG_W]->initiateTransaction(); transactionEstop[LEG_E]->initiateTransaction(); transactionEstop[LEG_S]->initiateTransaction(); // Complete return true; } bool LegInterface::queryStateInitiate() { /* transactionQueryState[LEG_W]->checkTransaction(); transactionQueryState[LEG_E]->checkTransaction(); transactionQueryState[LEG_S]->checkTransaction(); */ // Has the prior attempt at sending the estop completed? if(!queryStateCompleted()) { // No: do not attempt return false; } // Query last had completed // Schedule the transactions transactionQueryState[LEG_W]->initiateTransaction(); transactionQueryState[LEG_E]->initiateTransaction(); transactionQueryState[LEG_S]->initiateTransaction(); return true; } bool LegInterface::queryStateWaitForCompletion(int timeout) { for(int i = 0; i < NUM_LEGS; ++i) { if(!transactionQueryState[i]->waitForCompletion(timeout)) { return false; } } return true; } bool LegInterface::queryStateCompleted() { for(int i = 0; i < NUM_LEGS; ++i) { if(!transactionQueryState[i]->completed()) { return false; } } return true; } void LegInterface::queryStateTest(Serial *pc) { for(int i = 0; i < NUM_LEGS; ++i) { pc->printf("Status %d: %d %d\n\r", i, transactionQueryState[i]->getStatus(0), transactionQueryState[i]->getStatus(1)); } } bool LegInterface::queryStateCopy(LegState_t legState[NUM_LEGS]) { // Has the prior attempt at sending the estop completed? if(!queryStateCompleted()) { // No: do not attempt return false; } // Transaction complete: copy the state of the legs legState[LEG_W] = this->legState[LEG_W]; legState[LEG_E] = this->legState[LEG_E]; legState[LEG_S] = this->legState[LEG_S]; return true; } bool LegInterface::queryStateCopy(float liftPosition[NUM_LEGS], float liftVelocity[NUM_LEGS], float wheelPosition[NUM_LEGS], float wheelVelocity[NUM_LEGS]) { // Has the prior attempt at sending the estop completed? if(!queryStateCompleted()) { // No: do not attempt return false; } // Transaction complete: copy the state of the legs for(int i = 0; i < NUM_LEGS; ++i) { liftPosition[i] = this->legState[i].lift.pos / LIFT_TICKS_PER_METER; liftVelocity[i] = this->legState[i].lift.vel / LIFT_TICKS_PER_METER; wheelPosition[i] = this->legState[i].wheel.pos / TICKS_PER_METER; wheelVelocity[i] = this->legState[i].wheel.vel / TICKS_PER_METER; } return true; } void LegInterface::displayLegState(LegState_t *legState) { pc->printf("Cliff = %d, Limit = %d\n\r", legState->cliff, legState->limit); pc->printf("Wheel: pos=%d, vel=%d\n\r", legState->wheel.pos, legState->wheel.vel); pc->printf("Lift: pos=%d, vel=%d\n\r", legState->lift.pos, legState->lift.vel); } bool LegInterface::queryLegParams(Leg leg, LegControlParams_t *liftParams, LegControlParams_t *wheelParams) { /* if(pc != NULL) { pc->printf("completed: %d %d %d %d\n\r", transactionQueryLiftParams[leg]->completed(), transactionQueryWheelParams[leg]->completed(), transactionSetLiftParams[leg]->completed(), transactionSetWheelParams[leg]->completed()); pc->printf("codes: %d %d\n\r", transactionSetLiftParams[leg]->getStatus(0), transactionSetLiftParams[leg]->getStatus(1)); } */ // Has the prior attempt at querying/setting leg parameters completed? if(!transactionQueryLiftParams[leg]->completed() || !transactionQueryWheelParams[leg]->completed() || !transactionSetLiftParams[leg]->completed() || !transactionSetWheelParams[leg]->completed()) { // No: do not attempt return false; } // Yes: initiate the transactions transactionQueryLiftParams[leg]->initiateTransaction(); transactionQueryWheelParams[leg]->initiateTransaction(); //pc->printf("codes: %d %d\n\r", transactionQueryWheelParams[leg]->getStatus(0), transactionQueryWheelParams[leg]->getStatus(1)); if(transactionQueryLiftParams[leg]->waitForCompletion() && transactionQueryWheelParams[leg]->waitForCompletion()) { // Completed *liftParams = this->legLiftParams; *wheelParams = this->legWheelParams; return true; } // A timeout happened (no copy) return false; } void LegInterface::displayParams(LegControlParams_t *params) { pc->printf("Kp = %d\t Kv = %d\t Ki=%d\n\r", params->Kp, params->Kv, params->Ki); pc->printf("deadband = %d\n\r", params->deadband); pc->printf("Control signal range = [%d, %d]\n\r", params->min_val, params->max_val); pc->printf("Max error = %d, max error accum = %d\n\r", params->max_error, params->max_error_accum); pc->printf("Max acceleration = %d\n\r", params->max_accel); } bool LegInterface::setLegParams(Leg leg, LegControlParams_t *liftParams, LegControlParams_t *wheelParams) { // Has the prior attempt at querying/setting leg parameters completed? if(!transactionQueryLiftParams[leg]->completed() || !transactionQueryWheelParams[leg]->completed() || !transactionSetLiftParams[leg]->completed() || !transactionSetWheelParams[leg]->completed()) { // No: do not attempt return false; } // Copy provided parameters into structure to send this->legLiftParams = *liftParams; this->legWheelParams = *wheelParams; // Yes: initiate the transactions transactionSetLiftParams[leg]->initiateTransaction(); transactionSetWheelParams[leg]->initiateTransaction(); if(transactionQueryLiftParams[leg]->waitForCompletion() && transactionQueryWheelParams[leg]->waitForCompletion()) { // Completed return true; } // A timeout happened (no copy) return false; } bool LegInterface::setLegGoal(int32_t liftPos[NUM_LEGS], int32_t wheelVel[NUM_LEGS]) { // Has the previous attempt completed? if(!transactionSetGoal[LEG_W]->completed() || !transactionSetGoal[LEG_E]->completed() || !transactionSetGoal[LEG_S]->completed()) { // No: refuse to send return false; } // Copy goals into structures to send and initiate for(int i = 0; i < LegInterface::NUM_LEGS; ++i) { legPacketSetGoal[i].contents.as_goal.liftPos = liftPos[i]; legPacketSetGoal[i].contents.as_goal.wheelVel = wheelVel[i]; transactionSetGoal[i]->initiateTransaction(); } // Indicate success return true; } bool LegInterface::setLegGoal(float liftPos[NUM_LEGS], float wheelVel[NUM_LEGS]) { int32_t lift[NUM_LEGS]; int32_t wheel[NUM_LEGS]; for(int i = 0; i < NUM_LEGS; ++i) { wheel[i] = (int32_t) (wheelVel[i] * TICKS_PER_METER); lift[i] = (int32_t) (liftPos[i] * LIFT_TICKS_PER_METER); } return setLegGoal(lift, wheel); } void LegInterface::displayStatus() { pc->printf("Transaction status:\n\r"); transactionEstop[LEG_W]->displayStatus(pc, "Estop W:\t"); transactionEstop[LEG_E]->displayStatus(pc, "Estop E:\t"); transactionEstop[LEG_S]->displayStatus(pc, "Estop S:\t"); pc->printf("\n\r"); transactionQueryState[LEG_W]->displayStatus(pc, "Query State W:\t"); transactionQueryState[LEG_E]->displayStatus(pc, "Query State E:\t"); transactionQueryState[LEG_S]->displayStatus(pc, "Query State S:\t"); pc->printf("\n\r"); transactionQueryLiftParams[LEG_W]->displayStatus(pc, "Query Lift Params W"); transactionQueryLiftParams[LEG_E]->displayStatus(pc, "Query Lift Params E"); transactionQueryLiftParams[LEG_S]->displayStatus(pc, "Query Lift Params S"); pc->printf("\n\r"); transactionQueryWheelParams[LEG_W]->displayStatus(pc, "Query Wheel Params W"); transactionQueryWheelParams[LEG_E]->displayStatus(pc, "Query Wheel Params E"); transactionQueryWheelParams[LEG_S]->displayStatus(pc, "Query Wheel Params S"); pc->printf("\n\r"); transactionSetLiftParams[LEG_W]->displayStatus(pc, "Set Lift Params W"); transactionSetLiftParams[LEG_E]->displayStatus(pc, "Set Lift Params E"); transactionSetLiftParams[LEG_S]->displayStatus(pc, "Set Lift Params S"); pc->printf("\n\r"); transactionSetWheelParams[LEG_W]->displayStatus(pc, "Set Wheel Params W"); transactionSetWheelParams[LEG_E]->displayStatus(pc, "Set Wheel Params E"); transactionSetWheelParams[LEG_S]->displayStatus(pc, "Set Wheel Params S"); pc->printf("\n\r"); transactionSetGoal[LEG_W]->displayStatus(pc, "Set Goal W:\t"); transactionSetGoal[LEG_E]->displayStatus(pc, "Set Goal E:\t"); transactionSetGoal[LEG_S]->displayStatus(pc, "Set Goal S:\t"); pc->printf("\n\r"); } void LegInterface::reset() { I2CTransaction::reset(); } void LegInterface::resetBus() { I2CTransaction::resetBus(); } void LegInterface::cycleBus() { I2CTransaction::cycleBus(); }