#include "pdControlPlugin.h" #include "../../SharedMemoryPublic.h" #include "../b3PluginContext.h" #include #include "LinearMath/btScalar.h" #include "LinearMath/btAlignedObjectArray.h" #include "../../b3RobotSimulatorClientAPI_NoDirect.h" #include "../../b3RobotSimulatorClientAPI_InternalData.h" struct MyPDControl { int m_objectUniqueId; int m_linkIndex; btScalar m_desiredPosition; btScalar m_desiredVelocity; btScalar m_kd; btScalar m_kp; btScalar m_maxForce; }; struct MyPDControlContainer { int m_testData; btAlignedObjectArray m_controllers; b3RobotSimulatorClientAPI_NoDirect m_api; MyPDControlContainer() : m_testData(42) { } virtual ~MyPDControlContainer() { } }; B3_SHARED_API int initPlugin_pdControlPlugin(struct b3PluginContext* context) { MyPDControlContainer* obj = new MyPDControlContainer(); b3RobotSimulatorClientAPI_InternalData data; data.m_physicsClientHandle = context->m_physClient; data.m_guiHelper = 0; obj->m_api.setInternalData(&data); context->m_userPointer = obj; return SHARED_MEMORY_MAGIC_NUMBER; } B3_SHARED_API int preTickPluginCallback_pdControlPlugin(struct b3PluginContext* context) { //apply pd control here, apply forces using the PD gains MyPDControlContainer* obj = (MyPDControlContainer*)context->m_userPointer; for (int i = 0; i < obj->m_controllers.size(); i++) { const MyPDControl& pdControl = obj->m_controllers[i]; int dof1 = 0; b3JointSensorState actualState; if (obj->m_api.getJointState(pdControl.m_objectUniqueId, pdControl.m_linkIndex, &actualState)) { if (pdControl.m_maxForce > 0) { //compute torque btScalar qActual = actualState.m_jointPosition; btScalar qdActual = actualState.m_jointVelocity; btScalar positionError = (pdControl.m_desiredPosition - qActual); double desiredVelocity = 0; btScalar velocityError = (pdControl.m_desiredVelocity - qdActual); btScalar force = pdControl.m_kp * positionError + pdControl.m_kd * velocityError; btClamp(force, -pdControl.m_maxForce, pdControl.m_maxForce); //apply torque b3RobotSimulatorJointMotorArgs args(CONTROL_MODE_TORQUE); args.m_maxTorqueValue = force; obj->m_api.setJointMotorControl(pdControl.m_objectUniqueId, pdControl.m_linkIndex, args); } } } return 0; } B3_SHARED_API int executePluginCommand_pdControlPlugin(struct b3PluginContext* context, const struct b3PluginArguments* arguments) { MyPDControlContainer* obj = (MyPDControlContainer*)context->m_userPointer; if (arguments->m_numInts == 0) { obj->m_api.syncBodies(); return -1; } int numObj = obj->m_api.getNumBodies(); //printf("numObj = %d\n", numObj); //protocol: //first int is the type of command //second int is body unique id //third int is link index if (arguments->m_numInts != 3) return -1; switch (arguments->m_ints[0]) { case eSetPDControl: { if (arguments->m_numFloats < 5) return -1; MyPDControl controller; controller.m_desiredPosition = arguments->m_floats[0]; controller.m_desiredVelocity = arguments->m_floats[1]; controller.m_kd = arguments->m_floats[2]; controller.m_kp = arguments->m_floats[3]; controller.m_maxForce = arguments->m_floats[4]; controller.m_objectUniqueId = arguments->m_ints[1]; controller.m_linkIndex = arguments->m_ints[2]; int foundIndex = -1; for (int i = 0; i < obj->m_controllers.size(); i++) { if (obj->m_controllers[i].m_objectUniqueId == controller.m_objectUniqueId && obj->m_controllers[i].m_linkIndex == controller.m_linkIndex) { obj->m_controllers[i] = controller; foundIndex = i; } } if (foundIndex < 0) { obj->m_controllers.push_back(controller); } break; } case eRemovePDControl: { MyPDControl controller; controller.m_objectUniqueId = arguments->m_ints[1]; controller.m_linkIndex = arguments->m_ints[2]; for (int i = 0; i < obj->m_controllers.size(); i++) { if (obj->m_controllers[i].m_objectUniqueId == controller.m_objectUniqueId && obj->m_controllers[i].m_linkIndex == controller.m_linkIndex) { obj->m_controllers.removeAtIndex(i); break; } } break; } default: { return -1; } } int result = 42; return result; } B3_SHARED_API void exitPlugin_pdControlPlugin(struct b3PluginContext* context) { MyPDControlContainer* obj = (MyPDControlContainer*)context->m_userPointer; delete obj; context->m_userPointer = 0; }