24 #include <protobuf_comm/peer.h> 26 #include <llsf_msgs/BeaconSignal.pb.h> 27 #include <llsf_msgs/VersionInfo.pb.h> 28 #include <llsf_msgs/GameState.pb.h> 29 #include <llsf_msgs/MachineInfo.pb.h> 30 #include <llsf_msgs/RobotInfo.pb.h> 31 #include <llsf_msgs/ExplorationInfo.pb.h> 32 #include <llsf_msgs/MachineReport.pb.h> 33 #include <llsf_msgs/OrderInfo.pb.h> 34 #include <llsf_msgs/RingInfo.pb.h> 35 #include <llsf_msgs/MachineInstructions.pb.h> 37 #include <rcll_ros_msgs/BeaconSignal.h> 38 #include <rcll_ros_msgs/GameState.h> 39 #include <rcll_ros_msgs/Team.h> 40 #include <rcll_ros_msgs/MachineInfo.h> 41 #include <rcll_ros_msgs/ExplorationInfo.h> 42 #include <rcll_ros_msgs/MachineReportInfo.h> 43 #include <rcll_ros_msgs/OrderInfo.h> 44 #include <rcll_ros_msgs/RingInfo.h> 46 #include <rcll_ros_msgs/SendBeaconSignal.h> 47 #include <rcll_ros_msgs/SendMachineReport.h> 48 #include <rcll_ros_msgs/SendPrepareMachine.h> 54 #include <condition_variable> 57 #define GET_PRIV_PARAM(P) \ 59 if (! ros::param::get("~" #P, cfg_ ## P ## _)) { \ 60 ROS_ERROR("Failed to retrieve parameter " #P ", aborting"); \ 112 ROS_WARN(
"Receive error from %s:%u: %s",
113 endpoint.address().to_string().c_str(), endpoint.port(), msg.c_str());
119 ROS_ERROR(
"Send error: %s", msg.c_str());
126 if (team_color == llsf_msgs::CYAN)
127 return (
int)rcll_ros_msgs::Team::CYAN;
129 return (
int)rcll_ros_msgs::Team::MAGENTA;
135 if (team_color == rcll_ros_msgs::Team::CYAN)
136 return llsf_msgs::CYAN;
138 return llsf_msgs::MAGENTA;
143 uint16_t component_id, uint16_t msg_type,
144 std::shared_ptr<google::protobuf::Message> msg)
149 static bool version_info_printed =
false;
150 std::shared_ptr<VersionInfo> v;
151 if (! version_info_printed && (v = std::dynamic_pointer_cast<VersionInfo>(msg))) {
152 ROS_INFO(
"Referee Box %s detected", v->version_string().c_str());
153 version_info_printed =
true;
158 std::shared_ptr<BeaconSignal> b;
159 if ((b = std::dynamic_pointer_cast<BeaconSignal>(msg))) {
162 rcll_ros_msgs::BeaconSignal rb;
163 rb.header.seq = b->seq();
164 rb.header.stamp =
ros::Time(b->time().sec(), b->time().nsec());
165 rb.number = b->number();
166 rb.team_name = b->team_name();
167 rb.peer_name = b->peer_name();
170 rb.pose.header.frame_id =
"/map";
171 rb.pose.header.stamp =
ros::Time(b->pose().timestamp().sec(), b->pose().timestamp().nsec());
172 rb.pose.pose.position.x = b->pose().x();
173 rb.pose.pose.position.y = b->pose().y();
174 rb.pose.pose.position.z = 0.;
176 q.
setRPY(0., 0., b->pose().ori());
177 rb.pose.pose.orientation.x = q.x();
178 rb.pose.pose.orientation.y = q.y();
179 rb.pose.pose.orientation.z = q.z();
180 rb.pose.pose.orientation.w = q.w();
187 std::shared_ptr<GameState> gs;
188 if ((gs = std::dynamic_pointer_cast<GameState>(msg))) {
189 rcll_ros_msgs::GameState rgs;
190 rgs.game_time.sec = gs->game_time().sec();
191 rgs.game_time.nsec = gs->game_time().nsec();
192 rgs.state = (int)gs->state();
193 rgs.phase = (int)gs->phase();
194 if (gs->has_points_cyan()) rgs.points_cyan = gs->points_cyan();
195 if (gs->has_points_magenta()) rgs.points_magenta = gs->points_magenta();
197 if (gs->has_team_cyan()) {
202 rgs.team_cyan = gs->team_cyan();
204 if (gs->has_team_magenta()) {
209 rgs.team_magenta = gs->team_magenta();
217 std::shared_ptr<MachineInfo> mi;
218 if ((mi = std::dynamic_pointer_cast<MachineInfo>(msg))) {
219 rcll_ros_msgs::MachineInfo rmi;
220 for (
int i = 0; i < mi->machines_size(); ++i) {
221 const llsf_msgs::Machine &m = mi->machines(i);
222 rcll_ros_msgs::Machine rm;
224 if (m.has_type()) rm.type = m.type();
225 if (m.has_state()) rm.state = m.state();
227 if (m.has_zone()) rm.zone = (
int)m.zone();
228 for (
int j = 0; j < m.ring_colors_size(); ++j) {
229 rm.rs_ring_colors.push_back((
int)m.ring_colors(j));
231 rmi.machines.push_back(rm);
233 pub_machine_info_.
publish(rmi);
244 std::shared_ptr<ExplorationInfo> ei;
245 if ((ei = std::dynamic_pointer_cast<ExplorationInfo>(msg))) {
246 rcll_ros_msgs::ExplorationInfo rei;
247 for (
int i = 0; i < ei->signals_size(); ++i) {
248 const llsf_msgs::ExplorationSignal &es = ei->signals(i);
249 rcll_ros_msgs::ExplorationSignal res;
250 res.type = es.type();
251 for (
int j = 0; j < es.lights_size(); ++j) {
252 const llsf_msgs::LightSpec &l = es.lights(j);
253 rcll_ros_msgs::LightSpec rl;
255 rl.light_color = (int)l.color();
256 rl.light_state = (int)l.state();
257 res.lights.push_back(rl);
259 rei.signals.push_back(res);
261 for (
int i = 0; i < ei->zones_size(); ++i) {
262 const llsf_msgs::ExplorationZone &ez = ei->zones(i);
263 rcll_ros_msgs::ExplorationZone rez;
264 rez.zone = (int)ez.zone();
266 rei.zones.push_back(rez);
268 pub_exploration_info_.
publish(rei);
273 std::shared_ptr<MachineReportInfo> mri;
274 if ((mri = std::dynamic_pointer_cast<MachineReportInfo>(msg))) {
275 rcll_ros_msgs::MachineReportInfo rmri;
276 for (
int i = 0; i < mri->reported_machines_size(); ++i) {
277 rmri.reported_machines.push_back(mri->reported_machines(i));
280 pub_machine_report_info_.
publish(rmri);
285 std::shared_ptr<OrderInfo> oi;
286 if ((oi = std::dynamic_pointer_cast<OrderInfo>(msg))) {
287 rcll_ros_msgs::OrderInfo roi;
288 for (
int i = 0; i < oi->orders_size(); ++i) {
289 const llsf_msgs::Order &o = oi->orders(i);
290 rcll_ros_msgs::Order ro;
292 ro.complexity = (int)o.complexity();
293 ro.base_color = (int)o.base_color();
294 ro.cap_color = (int)o.cap_color();
295 for (
int j = 0; j < o.ring_colors_size(); ++j) {
296 ro.ring_colors.push_back((
int)o.ring_colors(j));
298 ro.quantity_requested = o.quantity_requested();
299 ro.quantity_delivered_cyan = o.quantity_delivered_cyan();
300 ro.quantity_delivered_magenta = o.quantity_delivered_magenta();
301 ro.delivery_period_begin = o.delivery_period_begin();
302 ro.delivery_period_end = o.delivery_period_end();
303 ro.delivery_gate = o.delivery_gate();
304 roi.orders.push_back(ro);
311 std::shared_ptr<RingInfo> ri;
312 if ((ri = std::dynamic_pointer_cast<RingInfo>(msg))) {
313 rcll_ros_msgs::RingInfo rri;
314 for (
int i = 0; i < ri->rings_size(); ++i) {
315 const llsf_msgs::Ring &r = ri->rings(i);
316 rcll_ros_msgs::Ring rr;
317 rr.ring_color = (int)r.ring_color();
318 rr.raw_material = r.raw_material();
319 rri.rings.push_back(rr);
334 if (team_color == llsf_msgs::CYAN) {
335 ROS_INFO(
"Creating private peer for CYAN");
350 ROS_INFO(
"Creating private peer for MAGENTA");
372 rcll_ros_msgs::SendBeaconSignal::Response &res)
376 res.error_msg =
"Cannot send beacon signal: private peer not setup, team not set in refbox?";
380 llsf_msgs::BeaconSignal b;
381 b.mutable_time()->set_sec(req.header.stamp.sec);
382 b.mutable_time()->set_nsec(req.header.stamp.nsec);
383 b.set_seq(req.header.seq);
388 if (req.pose.pose.position.x != 0. || req.pose.pose.position.y != 0. ||
389 req.pose.pose.orientation.x != 0. || req.pose.pose.orientation.y != 0. ||
390 req.pose.pose.orientation.z != 0. || req.pose.pose.orientation.w != 0.)
392 if (req.pose.pose.position.z != 0.) {
393 ROS_WARN(
"Poses must be 2.5D pose in ground support plane (x,y,ori)");
395 res.error_msg =
"Poses must be 2.5D pose in ground support plane (x,y,ori)";
398 b.mutable_pose()->mutable_timestamp()->set_sec(req.pose.header.stamp.sec);
399 b.mutable_pose()->mutable_timestamp()->set_nsec(req.pose.header.stamp.nsec);
400 b.mutable_pose()->set_x(req.pose.pose.position.x);
401 b.mutable_pose()->set_y(req.pose.pose.position.y);
402 tf2::Quaternion q(req.pose.pose.orientation.x, req.pose.pose.orientation.y,
403 req.pose.pose.orientation.z, req.pose.pose.orientation.w);
409 ROS_DEBUG(
"Sending beacon %s:%s (seq %lu)", b.team_name().c_str(), b.peer_name().c_str(), b.seq());
412 }
catch (std::runtime_error &e) {
414 res.error_msg = e.what();
422 rcll_ros_msgs::SendMachineReport::Response &res)
426 res.error_msg =
"Cannot send machine report: private peer not setup, team not set in refbox?";
430 llsf_msgs::MachineReport mr;
433 std::string machines_sent;
435 for (
size_t i = 0; i < req.machines.size(); ++i) {
436 const rcll_ros_msgs::MachineReportEntry &rmre = req.machines[i];
437 llsf_msgs::MachineReportEntry *mre = mr.add_machines();
438 mre->set_name(rmre.name);
439 mre->set_type(rmre.type);
441 if (! Zone_IsValid(rmre.zone)) {
443 res.error_msg = std::string(
"Invalid zone value for machine") + rmre.name;
447 mre->set_zone((llsf_msgs::Zone)rmre.zone);
449 if (! machines_sent.empty()) machines_sent +=
", ";
450 machines_sent += rmre.name;
454 ROS_DEBUG(
"Sending machine report for machines: %s", machines_sent.c_str());
457 }
catch (std::runtime_error &e) {
459 res.error_msg = e.what();
467 rcll_ros_msgs::SendPrepareMachine::Response &res)
471 res.error_msg =
"private peer not setup, team not set in refbox?";
475 if (req.machine.length() < 4) {
477 res.error_msg =
"Invalid machine name '" + req.machine +
"'";
482 std::string machine_team = req.machine.substr(0, 1);
483 std::string machine_type = req.machine.substr(2, 2);
485 if (machine_team !=
"C" && machine_team !=
"M") {
487 res.error_msg =
"Invalid team prefix '" + machine_team +
"', must be C or M";
490 if (machine_team ==
"C" &&
cfg_team_color_ == (
int)rcll_ros_msgs::Team::MAGENTA) {
492 res.error_msg =
"Invalid team prefix 'C', own team is MAGENTA";
495 if (machine_team ==
"M" &&
cfg_team_color_ == (
int)rcll_ros_msgs::Team::CYAN) {
497 res.error_msg =
"Invalid team prefix 'M', own team is CYAN";
500 if (machine_type !=
"BS" && machine_type !=
"DS" && machine_type !=
"CS" && machine_type !=
"RS") {
502 res.error_msg =
"Invalid machine type '" + machine_type +
"' in name";
506 llsf_msgs::PrepareMachine pm;
508 pm.set_machine(req.machine);
510 if (machine_type ==
"BS") {
511 if (! llsf_msgs::MachineSide_IsValid(req.bs_side)) {
513 res.error_msg =
"Invalid BS machine side";
516 if (! llsf_msgs::BaseColor_IsValid(req.bs_base_color)) {
518 res.error_msg =
"Invalid BS base color";
521 llsf_msgs::PrepareInstructionBS *bsi = pm.mutable_instruction_bs();
522 bsi->set_side((llsf_msgs::MachineSide)req.bs_side);
523 bsi->set_color((llsf_msgs::BaseColor)req.bs_base_color);
524 }
else if (machine_type ==
"DS") {
525 llsf_msgs::PrepareInstructionDS *dsi = pm.mutable_instruction_ds();
526 dsi->set_gate(req.ds_gate);
527 }
else if (machine_type ==
"CS") {
528 if (! llsf_msgs::CsOp_IsValid(req.cs_operation)) {
530 res.error_msg =
"Invalid CS operation";
533 llsf_msgs::PrepareInstructionCS *csi = pm.mutable_instruction_cs();
534 csi->set_operation((llsf_msgs::CsOp)req.cs_operation);
535 }
else if (machine_type ==
"RS") {
536 if (! llsf_msgs::RingColor_IsValid(req.rs_ring_color)) {
538 res.error_msg =
"Invalid RS ring color";
541 llsf_msgs::PrepareInstructionRS *rsi = pm.mutable_instruction_rs();
542 rsi->set_ring_color((llsf_msgs::RingColor)req.rs_ring_color);
548 bool need_to_wait =
false;
551 if (m.name() == req.machine) {
552 if (m.has_state() && m.state() !=
"IDLE") {
553 ROS_INFO(
"Machine '%s' is not in IDLE state, waiting briefly", req.machine.c_str());
562 [&req, &machine_idx]() ->
bool {
564 rcll_ros_msgs::MachineInfo rmi;
567 if (m.name() == req.machine && m.has_state() && m.state() ==
"IDLE") {
576 if (m.state() !=
"IDLE") {
577 ROS_INFO(
"Machine '%s' went into '%s' state, not IDLE", req.machine.c_str(), m.state().c_str());
579 res.error_msg =
"Machine '" + req.machine +
"' went into '" + m.state() +
"' state, not IDLE";
582 ROS_INFO(
"Machine '%s' is now in IDLE state", req.machine.c_str());
588 ROS_DEBUG(
"Sending prepare machine instruction for machine: %s", req.machine.c_str());
591 }
catch (std::runtime_error &e) {
593 res.error_msg = e.what();
597 ROS_INFO(
"Waiting for machine '%s' state != IDLE", req.machine.c_str());
602 [&req, &machine_idx, &pm]() ->
bool {
604 rcll_ros_msgs::MachineInfo rmi;
607 if (m.name() == req.machine && m.has_state() && m.state() !=
"IDLE") {
617 if (m.state() ==
"BROKEN") {
618 ROS_WARN(
"Machine '%s' went into 'BROKEN' state", req.machine.c_str());
620 res.error_msg =
"Machine '" + req.machine +
"' went into '" + m.state() +
"' state";
622 ROS_INFO(
"Machine '%s' went into '%s' state", req.machine.c_str(), m.state().c_str());
633 ros::init(argc, argv,
"rcll_refbox_peer");
660 ROS_ERROR(
"Failed to retrieve parameter cyan_recv_port, aborting");
664 ROS_ERROR(
"Failed to retrieve parameter cyan_send_port, aborting");
670 ROS_ERROR(
"Failed to retrieve parameter cyan_port, aborting");
677 ROS_ERROR(
"Failed to retrieve parameter magenta_recv_port, aborting");
681 ROS_ERROR(
"Failed to retrieve parameter magenta_send_port, aborting");
687 ROS_ERROR(
"Failed to retrieve parameter magenta_port, aborting");
696 pub_beacon_ = n.
advertise<rcll_ros_msgs::BeaconSignal>(
"rcll/beacon", 100);
697 pub_game_state_ = n.
advertise<rcll_ros_msgs::GameState>(
"rcll/game_state", 10);
698 pub_machine_info_ = n.
advertise<rcll_ros_msgs::MachineInfo>(
"rcll/machine_info", 10);
699 pub_exploration_info_ = n.
advertise<rcll_ros_msgs::ExplorationInfo>(
"rcll/exploration_info", 10);
700 pub_machine_report_info_ = n.
advertise<rcll_ros_msgs::MachineReportInfo>(
"rcll/machine_report_info", 10);
701 pub_order_info_ = n.
advertise<rcll_ros_msgs::OrderInfo>(
"rcll/order_info", 10);
702 pub_ring_info_ = n.
advertise<rcll_ros_msgs::RingInfo>(
"rcll/ring_info", 10);
706 ROS_WARN(
"Creating public peer: addr: %s send: %u recv: %u",
712 ROS_WARN(
"Creating public peer: addr: %s port: %u",
717 MessageRegister & message_register =
peer_public_->message_register();
718 message_register.add_message_type<llsf_msgs::VersionInfo>();
719 message_register.add_message_type<llsf_msgs::BeaconSignal>();
720 message_register.add_message_type<llsf_msgs::GameState>();
721 message_register.add_message_type<llsf_msgs::MachineInfo>();
722 message_register.add_message_type<llsf_msgs::ExplorationInfo>();
723 message_register.add_message_type<llsf_msgs::MachineReportInfo>();
724 message_register.add_message_type<llsf_msgs::OrderInfo>();
725 message_register.add_message_type<llsf_msgs::RingInfo>();
726 message_register.add_message_type<llsf_msgs::RobotInfo>();
727 message_register.add_message_type<llsf_msgs::PrepareMachine>();
std::string cfg_team_name_
std::shared_ptr< MachineInfo > msg_machine_info_
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
ProtobufBroadcastPeer * peer_public_
int cfg_peer_magenta_recv_port_
void setup_private_peer(llsf_msgs::Team team_color)
void publish(const boost::shared_ptr< M > &message) const
int cfg_peer_public_recv_port_
std::string cfg_robot_name_
void handle_send_error(std::string msg)
ros::ServiceServer srv_send_machine_report_
int pb_to_ros_team_color(const llsf_msgs::Team &team_color)
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
int cfg_peer_magenta_send_port_
ROSCPP_DECL const std::string & getName()
ros::Publisher pub_order_info_
bool cfg_peer_cyan_local_
int cfg_peer_magenta_port_
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
int cfg_peer_public_port_
ros::Publisher pub_machine_info_
ros::ServiceServer srv_send_prepare_machine_
ros::ServiceServer srv_send_beacon_
ros::Publisher pub_game_state_
int cfg_peer_cyan_recv_port_
bool cfg_peer_magenta_local_
ROSCPP_DECL bool get(const std::string &key, std::string &s)
void handle_recv_error(boost::asio::ip::udp::endpoint &endpoint, std::string msg)
bool srv_cb_send_machine_report(rcll_ros_msgs::SendMachineReport::Request &req, rcll_ros_msgs::SendMachineReport::Response &res)
llsf_msgs::Team ros_to_pb_team_color(int team_color)
ros::Publisher pub_machine_report_info_
std::condition_variable cdv_machine_info_
ROSCPP_DECL bool has(const std::string &key)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
ros::Publisher pub_ring_info_
std::string cfg_peer_address_
double getYaw(const A &a)
int cfg_peer_cyan_send_port_
int cfg_peer_public_send_port_
std::string cfg_crypto_key_
bool cfg_peer_public_local_
bool srv_cb_send_beacon(rcll_ros_msgs::SendBeaconSignal::Request &req, rcll_ros_msgs::SendBeaconSignal::Response &res)
ros::Publisher pub_beacon_
void handle_message(boost::asio::ip::udp::endpoint &sender, uint16_t component_id, uint16_t msg_type, std::shared_ptr< google::protobuf::Message > msg)
bool srv_cb_send_prepare_machine(rcll_ros_msgs::SendPrepareMachine::Request &req, rcll_ros_msgs::SendPrepareMachine::Response &res)
std::string cfg_crypto_cipher_
int main(int argc, char **argv)
ProtobufBroadcastPeer * peer_private_
std::mutex mtx_machine_info_
ros::Publisher pub_exploration_info_
#define GET_PRIV_PARAM(P)