mirror of
https://github.com/EECS-467-W20-RRRobot-Project/RRRobot.git
synced 2025-08-28 02:12:45 +00:00
Added motor control to the simulation, and a test program to verify that it is working as expected
This commit is contained in:
@@ -900,5 +900,6 @@
|
|||||||
<allow_auto_disable>0</allow_auto_disable>
|
<allow_auto_disable>0</allow_auto_disable>
|
||||||
|
|
||||||
<plugin name="joint_angles" filename="libarm_angles.so"/>
|
<plugin name="joint_angles" filename="libarm_angles.so"/>
|
||||||
|
<plugin name="arm_control" filename="libarm_motors.so"/>
|
||||||
</model>
|
</model>
|
||||||
</sdf>
|
</sdf>
|
||||||
|
@@ -52,6 +52,7 @@ find_package(gazebo REQUIRED)
|
|||||||
add_message_files(
|
add_message_files(
|
||||||
FILES
|
FILES
|
||||||
arm_angles.msg
|
arm_angles.msg
|
||||||
|
arm_command.msg
|
||||||
)
|
)
|
||||||
|
|
||||||
## Generate services in the 'srv' folder
|
## Generate services in the 'srv' folder
|
||||||
@@ -129,6 +130,10 @@ add_library(arm_angles SHARED
|
|||||||
src/arm_angle_sensor_plugin.cpp
|
src/arm_angle_sensor_plugin.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_library(arm_motors SHARED
|
||||||
|
src/arm_motors.cpp
|
||||||
|
)
|
||||||
|
|
||||||
## Add cmake target dependencies of the library
|
## Add cmake target dependencies of the library
|
||||||
## as an example, code may need to be generated before libraries
|
## as an example, code may need to be generated before libraries
|
||||||
## either from message generation or dynamic reconfigure
|
## either from message generation or dynamic reconfigure
|
||||||
@@ -137,7 +142,7 @@ add_library(arm_angles SHARED
|
|||||||
## Declare a C++ executable
|
## Declare a C++ executable
|
||||||
## With catkin_make all packages are built within a single CMake context
|
## With catkin_make all packages are built within a single CMake context
|
||||||
## The recommended prefix ensures that target names across packages don't collide
|
## The recommended prefix ensures that target names across packages don't collide
|
||||||
# add_executable(${PROJECT_NAME}_node src/simulation_env_node.cpp)
|
add_executable(test_move_arm test/move_arm.cpp)
|
||||||
|
|
||||||
## Rename C++ executable without prefix
|
## Rename C++ executable without prefix
|
||||||
## The above recommended prefix causes long target names, the following renames the
|
## The above recommended prefix causes long target names, the following renames the
|
||||||
@@ -147,7 +152,7 @@ add_library(arm_angles SHARED
|
|||||||
|
|
||||||
## Add cmake target dependencies of the executable
|
## Add cmake target dependencies of the executable
|
||||||
## same as for the library above
|
## same as for the library above
|
||||||
# add_dependencies(${PROJECT_NAME}_node ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})
|
add_dependencies(test_move_arm arm_angles arm_motors)
|
||||||
|
|
||||||
## Specify libraries to link a library or executable target against
|
## Specify libraries to link a library or executable target against
|
||||||
target_link_libraries(arm_angles
|
target_link_libraries(arm_angles
|
||||||
@@ -155,6 +160,15 @@ target_link_libraries(arm_angles
|
|||||||
${GAZEBO_LIBRARIES}
|
${GAZEBO_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_link_libraries(arm_motors
|
||||||
|
${catkin_LIBRARIES}
|
||||||
|
${GAZEBO_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(test_move_arm
|
||||||
|
${catkin_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
#############
|
#############
|
||||||
## Install ##
|
## Install ##
|
||||||
#############
|
#############
|
||||||
|
@@ -0,0 +1,6 @@
|
|||||||
|
float32 shoulder_pivot_force
|
||||||
|
float32 shoulder_joint_force
|
||||||
|
float32 elbow_joint_force
|
||||||
|
float32 wrist_pivot_force
|
||||||
|
float32 wrist_joint_force
|
||||||
|
float32 end_effector_pivot_force
|
@@ -11,51 +11,51 @@ using std::endl;
|
|||||||
|
|
||||||
namespace gazebo
|
namespace gazebo
|
||||||
{
|
{
|
||||||
class JointAngle : public ModelPlugin
|
class JointAngle : public ModelPlugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
|
void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
|
||||||
{
|
{
|
||||||
cout << "Loading JointAngle sensor plugin for arm" << endl;
|
cout << "Loading JointAngle sensor plugin for arm" << endl;
|
||||||
|
|
||||||
model = _parent;
|
model = _parent;
|
||||||
|
|
||||||
updateConnection = event::Events::ConnectWorldUpdateBegin(std::bind(&JointAngle::onUpdate, this));
|
updateConnection = event::Events::ConnectWorldUpdateBegin(std::bind(&JointAngle::onUpdate, this));
|
||||||
if(!ros::isInitialized())
|
if (!ros::isInitialized())
|
||||||
{
|
{
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
char **argv = NULL;
|
char **argv = NULL;
|
||||||
ros::init(argc, argv, "arm");
|
ros::init(argc, argv, "arm");
|
||||||
}
|
}
|
||||||
|
|
||||||
nh.reset(new ros::NodeHandle("arm_node"));
|
nh.reset(new ros::NodeHandle("arm_node"));
|
||||||
publisher = nh->advertise<simulation_env::arm_angles>("arm_positions", 1);
|
publisher = nh->advertise<simulation_env::arm_angles>("arm_positions", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onUpdate()
|
void onUpdate()
|
||||||
{
|
{
|
||||||
simulation_env::arm_angles msg;
|
simulation_env::arm_angles msg;
|
||||||
|
|
||||||
// read in the joint angle for each joint in the arm
|
// read in the joint angle for each joint in the arm
|
||||||
msg.shoulder_pivot_angle = dynamic_cast<gazebo::physics::Joint*>(model->GetChild("shoulder_pivot").get())->Position();
|
msg.shoulder_pivot_angle = model->GetJoint("shoulder_pivot")->Position();
|
||||||
msg.shoulder_joint_angle = dynamic_cast<gazebo::physics::Joint*>(model->GetChild("shoulder_joint").get())->Position();
|
msg.shoulder_joint_angle = model->GetJoint("shoulder_joint")->Position();
|
||||||
msg.elbow_joint_angle = dynamic_cast<gazebo::physics::Joint*>(model->GetChild("elbow_joint").get())->Position();
|
msg.elbow_joint_angle = model->GetJoint("elbow_joint")->Position();
|
||||||
msg.wrist_pivot_angle = dynamic_cast<gazebo::physics::Joint*>(model->GetChild("wrist_pivot").get())->Position();
|
msg.wrist_pivot_angle = model->GetJoint("wrist_pivot")->Position();
|
||||||
msg.wrist_joint_angle = dynamic_cast<gazebo::physics::Joint*>(model->GetChild("wrist_joint").get())->Position();
|
msg.wrist_joint_angle = model->GetJoint("wrist_joint")->Position();
|
||||||
msg.end_effector_pivot_angle = dynamic_cast<gazebo::physics::Joint*>(model->GetChild("end_effector_pivot").get())->Position();
|
msg.end_effector_pivot_angle = model->GetJoint("end_effector_pivot")->Position();
|
||||||
|
|
||||||
// publish the updated sensor measurements
|
|
||||||
publisher.publish(msg);
|
|
||||||
|
|
||||||
// make sure the message gets published
|
// publish the updated sensor measurements
|
||||||
ros::spinOnce();
|
publisher.publish(msg);
|
||||||
|
|
||||||
|
// make sure the message gets published
|
||||||
|
ros::spinOnce();
|
||||||
}
|
}
|
||||||
|
|
||||||
physics::ModelPtr model;
|
physics::ModelPtr model;
|
||||||
event::ConnectionPtr updateConnection;
|
event::ConnectionPtr updateConnection;
|
||||||
std::unique_ptr<ros::NodeHandle> nh;
|
std::unique_ptr<ros::NodeHandle> nh;
|
||||||
ros::Publisher publisher;
|
ros::Publisher publisher;
|
||||||
};
|
};
|
||||||
GZ_REGISTER_MODEL_PLUGIN(JointAngle)
|
GZ_REGISTER_MODEL_PLUGIN(JointAngle)
|
||||||
}
|
} // namespace gazebo
|
||||||
|
@@ -0,0 +1,53 @@
|
|||||||
|
#include <gazebo/gazebo.hh>
|
||||||
|
#include <gazebo/physics/physics.hh>
|
||||||
|
#include <memory>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "ros/ros.h"
|
||||||
|
#include "simulation_env/arm_command.h"
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
|
namespace gazebo
|
||||||
|
{
|
||||||
|
class ArmControl : public ModelPlugin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void arm_command_callback(const simulation_env::arm_command &cmd)
|
||||||
|
{
|
||||||
|
// update the torque applied to each joint when a message is received
|
||||||
|
model->GetJoint("shoulder_pivot")->SetForce(0, cmd.shoulder_pivot_force);
|
||||||
|
model->GetJoint("shoulder_joint")->SetForce(0, cmd.shoulder_joint_force);
|
||||||
|
model->GetJoint("elbow_joint")->SetForce(0, cmd.elbow_joint_force);
|
||||||
|
model->GetJoint("wrist_pivot")->SetForce(0, cmd.wrist_pivot_force);
|
||||||
|
model->GetJoint("wrist_joint")->SetForce(0, cmd.wrist_joint_force);
|
||||||
|
model->GetJoint("end_effector_pivot")->SetForce(0, cmd.end_effector_pivot_force);
|
||||||
|
|
||||||
|
ros::spinOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Load(physics::ModelPtr _parent, sdf::ElementPtr _sdf)
|
||||||
|
{
|
||||||
|
cout << "Loading motor control plugin for arm" << endl;
|
||||||
|
|
||||||
|
model = _parent;
|
||||||
|
|
||||||
|
if (!ros::isInitialized())
|
||||||
|
{
|
||||||
|
int argc = 0;
|
||||||
|
char **argv = NULL;
|
||||||
|
ros::init(argc, argv, "arm");
|
||||||
|
}
|
||||||
|
|
||||||
|
nh.reset(new ros::NodeHandle("arm_node"));
|
||||||
|
subscriber = nh->subscribe("arm_commands", 1000, &ArmControl::arm_command_callback, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
physics::ModelPtr model;
|
||||||
|
std::unique_ptr<ros::NodeHandle> nh;
|
||||||
|
ros::Subscriber subscriber;
|
||||||
|
};
|
||||||
|
GZ_REGISTER_MODEL_PLUGIN(ArmControl)
|
||||||
|
} // namespace gazebo
|
@@ -0,0 +1,70 @@
|
|||||||
|
#include "ros/ros.h"
|
||||||
|
#include "simulation_env/arm_command.h"
|
||||||
|
#include "simulation_env/arm_angles.h"
|
||||||
|
|
||||||
|
class PID_Control
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PID_Control(float Kp_in, float Ki_in, float Kd_in)
|
||||||
|
: Kp(Kp_in), Ki(Ki_in), Kd(Kd_in)
|
||||||
|
{}
|
||||||
|
|
||||||
|
float update(float error)
|
||||||
|
{
|
||||||
|
if(error > 0 and prev_error < 0
|
||||||
|
|| error < 0 and prev_error > 0)
|
||||||
|
{
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
sum_error += error;
|
||||||
|
float to_ret = Kp * error + Ki * sum_error + Kd * (error - prev_error);
|
||||||
|
|
||||||
|
prev_error = error;
|
||||||
|
return to_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
sum_error = 0;
|
||||||
|
prev_error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const float Kp;
|
||||||
|
const float Ki;
|
||||||
|
const float Kd;
|
||||||
|
|
||||||
|
double sum_error;
|
||||||
|
double prev_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PID_Control pid_controller(1000, 1, 0);
|
||||||
|
ros::Publisher publisher;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void angle_callback(const simulation_env::arm_angles &msg)
|
||||||
|
{
|
||||||
|
// just control the shoulder joint to go to 0 (should be roughly straight up)
|
||||||
|
float output = pid_controller.update(0 - msg.shoulder_joint_angle);
|
||||||
|
|
||||||
|
simulation_env::arm_command cmd;
|
||||||
|
cmd.shoulder_joint_force = output;
|
||||||
|
|
||||||
|
publisher.publish(cmd);
|
||||||
|
ros::spinOnce();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
ros::init(argc, argv, "arm_control_test");
|
||||||
|
|
||||||
|
ros::NodeHandle nh;
|
||||||
|
publisher = nh.advertise<simulation_env::arm_command>("/arm_node/arm_commands", 1000);
|
||||||
|
ros::Subscriber sub = nh.subscribe("/arm_node/arm_positions", 1000, angle_callback);
|
||||||
|
|
||||||
|
ros::spin();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user