36 #include <sensor_msgs/JointState.h> 37 #include <sensor_msgs/Imu.h> 38 #include <geometry_msgs/Twist.h> 39 #include <std_msgs/Float64.h> 41 #include <nav_msgs/Odometry.h> 42 #include <robotnik_msgs/set_mode.h> 43 #include <robotnik_msgs/get_mode.h> 44 #include <robotnik_msgs/set_odometry.h> 45 #include <robotnik_msgs/ptz.h> 47 #include "ackermann_msgs/AckermannDriveStamped.h" 49 #include "diagnostic_msgs/DiagnosticStatus.h" 54 #include <std_srvs/Empty.h> 57 #define PI 3.1415926535 58 #define AGVS_MIN_COMMAND_REC_FREQ 5.0 59 #define AGVS_MAX_COMMAND_REC_FREQ 150.0 61 #define AGVS_WHEEL_DIAMETER 0.2195 // Default wheel diameter 62 #define DEFAULT_DIST_CENTER_TO_WHEEL 0.479 // Default distance center to motorwheel 64 #define MAX_ELEVATOR_POSITION 0.05 // meters 191 node_handle_(h), private_node_handle_(
"~"),
192 desired_freq_(100.0),
193 freq_diag_(
diagnostic_updater::FrequencyStatusParam(&desired_freq_, &desired_freq_, 0.05) ),
197 ROS_INFO(
"agvs_robot_control_node - Init ");
199 ros::NodeHandle agvs_robot_control_node_handle(node_handle_,
"agvs_robot_control");
202 if (!private_node_handle_.
getParam(
"model", robot_model_)) {
206 else ROS_INFO(
"Robot Model : %s", robot_model_.c_str());
209 private_node_handle_.
param<std::string>(
"fwd_vel_topic", fwd_vel_topic_,
"/agvs/joint_front_wheel_controller/command");
210 private_node_handle_.
param<std::string>(
"bwd_vel_topic", bwd_vel_topic_,
"/agvs/joint_back_wheel_controller/command");
211 private_node_handle_.
param<std::string>(
"fwd_pos_topic", fwd_pos_topic_,
"/agvs/joint_front_motor_wheel_controller/command");
212 private_node_handle_.
param<std::string>(
"bwd_pos_topic", bwd_pos_topic_,
"/agvs/joint_back_motor_wheel_controller/command");
213 private_node_handle_.
param<std::string>(
"elevator_pos_topic", elevator_pos_topic_,
"/agvs/joint_elevator_controller/command");
214 private_node_handle_.
param<std::string>(
"imu_topic", imu_topic_,
"/agvs/imu_data");
217 private_node_handle_.
param<std::string>(
"joint_front_wheel", joint_front_wheel,
"joint_front_wheel");
218 private_node_handle_.
param<std::string>(
"joint_back_wheel", joint_back_wheel,
"joint_back_wheel");
219 private_node_handle_.
param<std::string>(
"joint_front_motor_wheel", joint_front_motor_wheel,
"joint_front_motor_wheel");
220 private_node_handle_.
param<std::string>(
"joint_back_motor_wheel", joint_back_motor_wheel,
"joint_back_motor_wheel");
223 if (!private_node_handle_.
getParam(
"agvs_wheel_diameter", agvs_wheel_diameter_))
225 if (!private_node_handle_.
getParam(
"agvs_dist_to_center", agvs_dist_to_center_))
230 private_node_handle_.
param(
"publish_odom_tf", publish_odom_tf_,
true);
231 if (publish_odom_tf_)
ROS_INFO(
"PUBLISHING odom->base_footprint tf");
232 else ROS_INFO(
"NOT PUBLISHING odom->base_footprint tf");
235 linearSpeedXMps_ = 0.0;
236 linearSpeedYMps_ = 0.0;
237 angularSpeedRads_ = 0.0;
240 robot_pose_px_ = 0.0;
241 robot_pose_py_ = 0.0;
242 robot_pose_pa_ = 0.0;
243 robot_pose_vx_ = 0.0;
244 robot_pose_vy_ = 0.0;
251 ang_vel_x_ = 0.0; ang_vel_y_ = 0.0; ang_vel_z_ = 0.0;
252 lin_acc_x_ = 0.0; lin_acc_y_ = 0.0; lin_acc_z_ = 0.0;
253 orientation_diff_x_ = 0.0; orientation_diff_y_ = 0.0; orientation_diff_z_ = 0.0; orientation_diff_w_ = 1.0;
271 ref_vel_fwd_ = private_node_handle_.
advertise<std_msgs::Float64>( fwd_vel_topic_, 50);
272 ref_vel_bwd_ = private_node_handle_.
advertise<std_msgs::Float64>( bwd_vel_topic_, 50);
273 ref_pos_fwd_ = private_node_handle_.
advertise<std_msgs::Float64>( fwd_pos_topic_, 50);
274 ref_pos_bwd_ = private_node_handle_.
advertise<std_msgs::Float64>( bwd_pos_topic_, 50);
275 ref_pos_elevator_ = private_node_handle_.
advertise<std_msgs::Float64>( elevator_pos_topic_, 50);
282 odom_pub_ = private_node_handle_.
advertise<nav_msgs::Odometry>(
"odom", 1000);
285 diagnostic_.
setHardwareID(
"agvs_robot_control - simulation");
286 diagnostic_.
add( freq_diag_ );
287 diagnostic_.
add( command_freq_ );
295 subs_command_freq->
addTask(&command_freq_);
308 ROS_INFO(
"AGVSControllerClass::starting");
316 vector<string> joint_names = joint_state_.name;
317 fwd_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_front_wheel)) - joint_names.begin();
318 bwd_vel_ = find (joint_names.begin(),joint_names.end(), string(joint_back_wheel)) - joint_names.begin();
319 fwd_pos_ = find (joint_names.begin(),joint_names.end(), string(joint_front_motor_wheel)) - joint_names.begin();
320 bwd_pos_ = find (joint_names.begin(),joint_names.end(), string(joint_back_motor_wheel)) - joint_names.begin();
342 double fBetaRads = 0.0;
346 double fSamplePeriod = 1.0 / desired_freq_;
350 v_fwd = joint_state_.velocity[fwd_vel_] * (agvs_wheel_diameter_ / 2.0);
351 v_bwd = joint_state_.velocity[bwd_vel_] * (agvs_wheel_diameter_ / 2.0);
353 v_mps = -(v_fwd + v_bwd) / 2.0;
357 a_fwd = radnorm2( joint_state_.position[fwd_pos_] );
358 a_bwd = radnorm2( joint_state_.position[bwd_pos_] );
362 if(fabs(v_mps) < 0.00001) v_mps = 0.0;
365 double w = (v_mps / agvs_dist_to_center_) * sin(fBetaRads);
366 robot_pose_pa_ += w * fSamplePeriod;
369 radnorm(&robot_pose_pa_);
372 robot_pose_vx_ = v_mps * cos(fBetaRads) * cos(robot_pose_pa_);
373 robot_pose_vy_ = v_mps * cos(fBetaRads) * sin(robot_pose_pa_);
376 robot_pose_px_ += robot_pose_vx_ * fSamplePeriod;
377 robot_pose_py_ += robot_pose_vy_ * fSamplePeriod;
386 geometry_msgs::TransformStamped odom_trans;
387 odom_trans.header.stamp = current_time;
388 odom_trans.header.frame_id =
"odom";
389 odom_trans.child_frame_id =
"base_footprint";
391 odom_trans.transform.translation.x = robot_pose_px_;
392 odom_trans.transform.translation.y = robot_pose_py_;
393 odom_trans.transform.translation.z = 0.0;
396 double theta = robot_pose_pa_;
398 odom_trans.transform.rotation.x = quat.x;
399 odom_trans.transform.rotation.y = quat.y;
400 odom_trans.transform.rotation.z = quat.z;
401 odom_trans.transform.rotation.w = quat.w;
407 if (publish_odom_tf_) odom_broadcaster.
sendTransform(odom_trans);
410 nav_msgs::Odometry odom;
411 odom.header.stamp = current_time;
412 odom.header.frame_id =
"odom";
416 odom.pose.pose.position.x = robot_pose_px_;
417 odom.pose.pose.position.y = robot_pose_py_;
418 odom.pose.pose.position.z = 0.0;
420 odom.pose.pose.orientation.x = orientation_diff_x_;
421 odom.pose.pose.orientation.y = orientation_diff_y_;
422 odom.pose.pose.orientation.z = orientation_diff_z_;
423 odom.pose.pose.orientation.w = orientation_diff_w_;
426 for(
int i = 0; i < 6; i++)
427 odom.pose.covariance[i*6+i] = 0.1;
430 odom.child_frame_id =
"base_footprint";
432 odom.twist.twist.linear.x = robot_pose_vx_;
433 odom.twist.twist.linear.y = robot_pose_vy_;
434 odom.twist.twist.linear.z = 0.0;
436 odom.twist.twist.angular.x = ang_vel_x_;
437 odom.twist.twist.angular.y = ang_vel_y_;
438 odom.twist.twist.angular.z = ang_vel_z_;
440 for(
int i = 0; i < 6; i++)
441 odom.twist.covariance[6*i+i] = 0.1;
450 std_msgs::Float64 vel_ref_msg;
451 std_msgs::Float64 pos_ref_msg;
452 static double ev_ant = 0.0;
470 vel_ref_msg.data = -v_ref_ * Kp;
472 pos_ref_msg.data = a_ref_;
475 ref_vel_fwd_.
publish( vel_ref_msg );
476 ref_vel_bwd_.
publish( vel_ref_msg );
478 ref_pos_fwd_.
publish( pos_ref_msg );
479 pos_ref_msg.data = -a_ref_;
480 ref_pos_bwd_.
publish( pos_ref_msg );
486 std_msgs::Float64 ref_msg;
490 ref_pos_elevator_.
publish( ref_msg );
505 double diff = (current_time - last_command_time_).toSec();
508 stat.
summary(diagnostic_msgs::DiagnosticStatus::WARN,
"Topic is not receiving commands");
512 stat.
summary(diagnostic_msgs::DiagnosticStatus::OK,
"Topic receiving commands");
520 robot_pose_px_ = request.x;
521 robot_pose_py_ = request.y;
522 robot_pose_pa_ = request.orientation;
540 SetElevatorPosition(0.0);
558 subs_command_freq->
tick();
560 double speed_limit = 2.0;
561 double angle_limit =
PI;
562 v_ref_ = saturation(msg->drive.speed, -speed_limit, speed_limit);
563 a_ref_ = saturation(msg->drive.steering_angle, -angle_limit, angle_limit);
569 orientation_diff_x_ = imu_msg.orientation.x;
570 orientation_diff_y_ = imu_msg.orientation.y;
571 orientation_diff_z_ = imu_msg.orientation.z;
572 orientation_diff_w_ = imu_msg.orientation.w;
574 ang_vel_x_ = imu_msg.angular_velocity.x;
575 ang_vel_y_ = imu_msg.angular_velocity.y;
576 ang_vel_z_ = imu_msg.angular_velocity.z;
578 lin_acc_x_ = imu_msg.linear_acceleration.x;
579 lin_acc_y_ = imu_msg.linear_acceleration.y;
580 lin_acc_z_ = imu_msg.linear_acceleration.z;
595 while (*radians >= (
PI)) {
596 *radians -= 2.0 *
PI;
598 while (*radians <= (-
PI)) {
599 *radians += 2.0 *
PI;
605 while (value > 2.0*
PI) value -= 2.0*
PI;
606 while (value < -2.0*
PI) value += 2.0*
PI;
612 ROS_INFO(
"agvs_robot_control::spin()");
636 ROS_INFO(
"agvs_robot_control::spin() - end");
642 int main(
int argc,
char** argv)
644 ros::init(argc, argv,
"agvs_robot_control");
void UpdateOdometry()
Updates the values of the odometry Ackerman's odometry calculation (using motor speed and position of...
diagnostic_updater::Updater diagnostic_
void publish(const boost::shared_ptr< M > &message) const
ros::ServiceServer srv_RaiseElevator_
std::string fwd_vel_topic_
std::string bwd_pos_topic_
void stopping()
Controller stopping.
double saturation(double u, double min, double max)
void summary(unsigned char lvl, const std::string s)
Subscriber subscribe(const std::string &topic, uint32_t queue_size, void(T::*fp)(M), T *obj, const TransportHints &transport_hints=TransportHints())
ros::ServiceServer srv_LowerElevator_
void imuCallback(const sensor_msgs::Imu &imu_msg)
double orientation_diff_y_
void setHardwareID(const std::string &hwid)
double orientation_diff_x_
ros::Publisher ref_pos_elevator_
std::string joint_front_motor_wheel
#define AGVS_WHEEL_DIAMETER
void commandCallback(const ackermann_msgs::AckermannDriveStamped::ConstPtr &msg)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void add(const std::string &name, TaskFunction f)
ros::ServiceServer srv_SetMode_
void check_command_subscriber(diagnostic_updater::DiagnosticStatusWrapper &stat)
bool srvCallback_SetOdometry(robotnik_msgs::set_odometry::Request &request, robotnik_msgs::set_odometry::Response &response)
std::string elevator_pos_topic_
#define MAX_ELEVATOR_POSITION
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
AGVSControllerClass(ros::NodeHandle h)
Public constructor.
ros::Time last_command_time_
sensor_msgs::JointState joint_state_
diagnostic_updater::FrequencyStatus freq_diag_
void SetElevatorPosition(double val)
double agvs_wheel_diameter_
ros::ServiceServer srv_GetMode_
ros::Publisher ref_pos_fwd_
ros::Publisher ref_vel_fwd_
tf::TransformBroadcaster odom_broadcaster
diagnostic_updater::FunctionDiagnosticTask command_freq_
bool srvCallback_RaiseElevator(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
ros::Publisher ref_vel_bwd_
std::string joint_back_wheel
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
#define AGVS_MIN_COMMAND_REC_FREQ
ros::NodeHandle private_node_handle_
bool srvCallback_LowerElevator(std_srvs::Empty::Request &request, std_srvs::Empty::Response &response)
ros::NodeHandle node_handle_
std::string fwd_pos_topic_
ROSCPP_DECL bool isShuttingDown()
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
#define DEFAULT_DIST_CENTER_TO_WHEEL
std::string bwd_vel_topic_
double orientation_diff_w_
diagnostic_updater::HeaderlessTopicDiagnostic * subs_command_freq
double orientation_diff_z_
ros::Subscriber joint_state_sub_
TFSIMD_FORCE_INLINE const tfScalar & w() const
#define AGVS_MAX_COMMAND_REC_FREQ
std::string joint_back_motor_wheel
int starting()
Controller startup in realtime.
void jointStateCallback(const sensor_msgs::JointStateConstPtr &msg)
static double radnorm2(double value)
std::string joint_front_wheel
static geometry_msgs::Quaternion createQuaternionMsgFromYaw(double yaw)
bool getParam(const std::string &key, std::string &s) const
ackermann_msgs::AckermannDriveStamped base_vel_msg_
static void radnorm(double *radians)
Normalize in rad.
ros::ServiceServer srv_SetOdometry_
ROSCPP_DECL void spinOnce()
int main(int argc, char **argv)
ros::Publisher ref_pos_bwd_
double agvs_dist_to_center_
void addTask(DiagnosticTask *t)