Go to the documentation of this file.00001
00037
00038
00039
00040
00041 #include <ros/ros.h>
00042 #include <std_msgs/Float64.h>
00043
00044 namespace plant_sim
00045 {
00046
00047 static double control_effort = 0.0;
00048 static bool reverse_acting = false;
00049 }
00050 using namespace plant_sim;
00051
00052
00053 void ControlEffortCallback(const std_msgs::Float64& control_effort_input)
00054 {
00055
00056 if (reverse_acting)
00057 {
00058 control_effort = -control_effort_input.data;
00059 }
00060 else
00061 {
00062 control_effort = control_effort_input.data;
00063 }
00064 }
00065
00066 int main(int argc, char **argv)
00067 {
00068 int plant_order = 1;
00069 double temp = 4.7;
00070 double displacement = 3.3;
00071
00072 ros::init(argc, argv, "plant");
00073 ros::NodeHandle sim_node;
00074
00075 while (ros::Time(0) == ros::Time::now())
00076 {
00077 ROS_INFO("Plant_sim spinning waiting for time to become non-zero");
00078 sleep(1);
00079 }
00080
00081 ros::NodeHandle node_priv("~");
00082 node_priv.param<int>("plant_order", plant_order, 1);
00083 node_priv.param<bool>("reverse_acting", reverse_acting, false);
00084
00085 if (plant_order == 1)
00086 {
00087 ROS_INFO("Starting simulation of a first-order plant.");
00088 }
00089 else if (plant_order == 2)
00090 {
00091 ROS_INFO("Starting simulation of a second-order plant.");
00092 }
00093 else
00094 {
00095 ROS_ERROR("Error: Invalid plant type parameter, must be 1 or 2: %s", argv[1]);
00096 return -1;
00097 }
00098
00099
00100 std_msgs::Float64 plant_state;
00101 ros::Publisher servo_state_pub = sim_node.advertise<std_msgs::Float64>("state", 1);
00102
00103
00104 ros::Subscriber sub = sim_node.subscribe("control_effort", 1, ControlEffortCallback );
00105
00106 int loop_counter = 0;
00107 double delta_t = 0.01;
00108 ros::Rate loop_rate(1/delta_t);
00109
00110
00111 double temp_rate = 0;
00112
00113
00114 double speed = 0;
00115 double acceleration = 0;
00116 double mass = 0.1;
00117 double friction = 1.0;
00118 double stiction = 1;
00119 double Kv = 1;
00120 double Kbackemf = 0;
00121 double decel_force;
00122
00123 while (ros::ok())
00124 {
00125 ros::spinOnce();
00126
00127 switch (plant_order)
00128 {
00129 case 1:
00130 temp_rate = (0.1 * temp) + control_effort;
00131 temp = temp + temp_rate * delta_t;
00132
00133 plant_state.data = temp;
00134 break;
00135
00136 case 2:
00137 if (fabs(speed) < 0.001)
00138 {
00139
00140 speed = 0;
00141 if (fabs(control_effort) < stiction)
00142 {
00143 control_effort = 0;
00144 }
00145 }
00146
00147
00148
00149
00150
00151
00152 decel_force = -(speed * friction);
00153 acceleration = ((Kv * (control_effort - (Kbackemf * speed)) + decel_force) / mass);
00154 speed = speed + (acceleration * delta_t);
00155 displacement = displacement + speed * delta_t;
00156
00157 plant_state.data = displacement;
00158 break;
00159
00160 default:
00161 ROS_ERROR("Invalid plant_order: %d", plant_order);
00162 return(-1);
00163 }
00164
00165 servo_state_pub.publish(plant_state);
00166 loop_rate.sleep();
00167 }
00168
00169 return 0;
00170 }
00171