/* * scout_webots_node.cpp * * Created on: Sep 26, 2019 23:03 * Description: * * Copyright (c) 2019 Ruixiang Du (rdu) */ #include #include #include #include #include #include #include "scout_webots_sim/scout_webots_interface.hpp" using namespace wescore; ros::ServiceClient timeStepClient; webots_ros::set_int timeStepSrv; static int controllerCount; static std::vector controllerList; void quit(int sig) { ROS_INFO("User stopped the 'agilex_scout' node."); timeStepSrv.request.value = 0; timeStepClient.call(timeStepSrv); ros::shutdown(); exit(0); } // catch names of the controllers availables on ROS network void controllerNameCallback(const std_msgs::String::ConstPtr &name) { controllerCount++; controllerList.push_back(name->data); ROS_INFO("Controller #%d: %s.", controllerCount, controllerList.back().c_str()); } int main(int argc, char *argv[]) { ros::init(argc, argv, "scout_webots_node", ros::init_options::AnonymousName); ros::NodeHandle nh, private_node("~"); ScoutROSMessenger messenger(&nh); private_node.param("odom_frame", messenger.odom_frame_, std::string("odom")); private_node.param("base_frame", messenger.base_frame_, std::string("base_link")); private_node.param("sim_control_rate", messenger.sim_control_rate_, 50); private_node.param("simulated_robot", messenger.simulated_robot_, true); messenger.SetupSubscription(); const uint32_t time_step = 1000 / messenger.sim_control_rate_; ScoutWebotsInterface scout_webots(&nh, &messenger, time_step); signal(SIGINT, quit); // subscribe to the topic model_name to get the list of availables controllers std::string controllerName; ros::Subscriber nameSub = nh.subscribe("model_name", 100, controllerNameCallback); while (controllerCount == 0 || controllerCount < nameSub.getNumPublishers()) { ros::spinOnce(); ros::spinOnce(); ros::spinOnce(); } ros::spinOnce(); // if there is more than one controller available, it let the user choose if (controllerCount == 1) controllerName = controllerList[0]; else { int wantedController = 0; std::cout << "Choose the # of the controller you want to use:\n"; std::cin >> wantedController; if (1 <= wantedController && wantedController <= controllerCount) controllerName = controllerList[wantedController - 1]; else { ROS_ERROR("Invalid number for controller choice."); return 1; } } ROS_INFO("Using controller: '%s'", controllerName.c_str()); // leave topic once it is not necessary anymore nameSub.shutdown(); // init robot components scout_webots.InitComponents(controllerName); ROS_INFO("Entering ROS main loop..."); // main loop timeStepClient = nh.serviceClient(controllerName + "/robot/time_step"); timeStepSrv.request.value = time_step; while (ros::ok()) { if (!timeStepClient.call(timeStepSrv) || !timeStepSrv.response.success) { ROS_ERROR("Failed to call service time_step for next step."); break; } scout_webots.UpdateSimState(); ros::spinOnce(); } timeStepSrv.request.value = 0; timeStepClient.call(timeStepSrv); ros::shutdown(); return 0; }