#include "adaptor_module.h"
#include "custom_event.h"
#include "event_data.h"
#include "deebot_status/deebot_status.h"
#include "utils/dbg/dbg.h"
#include "rectangle.h"
#include "lineobj.h"
#include "frame_manager/rule/create_new_rule.h"
#define POSE_COLLECT_COUNT 20
#define CARPET_ID 20
#define RECTANGLE_VERTICES_SIZE 4
AdaptorModule::AdaptorModule() : Module(EventTag::idx_to_tag(EventRosPose) |
EventTag::idx_to_tag(EventRosFurnitureInfo) |
EventTag::idx_to_tag(EventRosCleanState) |
EventTag::idx_to_tag(EventRosDoorSillsInfo) |
EventTag::idx_to_tag(EventRosLineLaserData) |
EventTag::idx_to_tag(EventRosChargeFailed) |
EventTag::idx_to_tag(EventRosVritualWallsInfo) |
EventTag::idx_to_tag(EventRosExternalTakePhoto) |
EventTag::idx_to_tag(EventRosWaveResult))
{
}
void AdaptorModule::on_init()
{
auto timer = std::make_shared<BusTimerInfo>();
timer->second = 5;
timer->cb = [this, timer]()
{
if (current_moving_state_ == MovingState::Moving)
{
auto now = time(nullptr);
auto duration = now - last_move_time_;
if (duration >= 5)
{
current_moving_state_ = MovingState::Stop;
auto items = std::make_shared<FilterItem>();
items->items.emplace_back(FilterItem::Info{"isMoving", Item(std::make_shared<bool>(false)), -1});
call_back(EventAddItem, items);
}
}
call_back(EventSetBusTimer, timer);
};
call_back(EventSetBusTimer, timer);
}
void AdaptorModule::on_event(int EventID, BaseDataType data)
{
switch (EventID)
{
case EventRosPose:
{
auto practicalData = RosDataType<EventRosPose>::Dereference(data);
auto items = std::make_shared<FilterItem>();
auto guard = DeebotStatus::instance().make_guard();
if (!(DeebotStatus::instance().robot_pos.x == practicalData->pose.x && DeebotStatus::instance().robot_pos.y == practicalData->pose.y && DeebotStatus::instance().robot_pos.theta == practicalData->pose.theta))
{
last_move_time_ = time(nullptr);
if (current_moving_state_ != MovingState::Moving)
{
items->items.emplace_back(FilterItem::Info{"isMoving", Item(std::make_shared<bool>(true)), -1});
current_moving_state_ = MovingState::Moving;
}
}
DeebotStatus::instance().robot_pos.x = practicalData->pose.x;
DeebotStatus::instance().robot_pos.y = practicalData->pose.y;
DeebotStatus::instance().robot_pos.theta = practicalData->pose.theta;
auto r = std::make_shared<SelfPose>(SelfPose{DeebotStatus::instance().robot_pos});
items->items.emplace_back(FilterItem::Info{"x", Item(std::make_shared<Numeric>(practicalData->pose.x)), -1});
items->items.emplace_back(FilterItem::Info{"y", Item(std::make_shared<Numeric>(practicalData->pose.y)), -1});
items->items.emplace_back(FilterItem::Info{"theta", Item(std::make_shared<Numeric>(practicalData->pose.theta)), -1});
call_back(EventAddItem, items);
if (++count_ < POSE_COLLECT_COUNT)
{
return;
}
count_ = 0;
call_back(EventMoveLongEnough, r);
break;
}
case EventRosFurnitureInfo:
{
LOG(INFO) << "EventRosFurnitureInfo";
auto practicalData = RosDataType<EventRosFurnitureInfo>::Dereference(data);
for (auto &info : practicalData->furnitureinfos)
{
if (RECTANGLE_VERTICES_SIZE == info.outlines2d.size())
{
auto obj_info = std::make_shared<ObjectInfo>();
obj_info->name = "furniture" + std::to_string(info.type);
auto object = std::make_shared<Rectangle>(info.outlines2d[0].x, info.outlines2d[0].y, info.outlines2d[1].x, info.outlines2d[1].y,
info.outlines2d[2].x, info.outlines2d[2].y, info.outlines2d[3].x, info.outlines2d[3].y);
obj_info->objects.push_back(object);
LOG(INFO) << "name:" << obj_info->name << " pose:" << object->poses[0].x << "," << object->poses[0].y << " " << object->poses[1].x << "," << object->poses[1].y << " " << object->poses[2].x << "," << object->poses[2].y << " " << object->poses[3].x << "," << object->poses[3].y;
call_back(EventAddObjectToMap, obj_info);
}
}
}
break;
case EventRosVritualWallsInfo:
{
auto practicalData = RosDataType<EventRosVritualWallsInfo>::Dereference(data);
for (const auto &wall : practicalData->vwalls)
{
if (wall.type != 0)
{
continue;
}
auto obj_info = std::make_shared<ObjectInfo>();
obj_info->name = "virtualWall";
auto size = wall.dots.size();
if (size != 2)
{
LOG(INFO) << "bad virtual wall size:" << size;
continue;
}
auto object = std::make_shared<LineObj>(wall.dots[0].x, wall.dots[0].y, wall.dots[1].x, wall.dots[1].y);
obj_info->objects.push_back(object);
LOG(INFO) << "name:" << obj_info->name << " pose:" << object->poses.first.x << "," << object->poses.first.y << " " << object->poses.second.x << "," << object->poses.second.y;
call_back(EventAddObjectToMap, obj_info);
}
}
break;
case EventRosDoorSillsInfo:
{
LOG(INFO) << "EventRosDoorSillsInfo";
auto practicalData = RosDataType<EventRosDoorSillsInfo>::Dereference(data);
auto obj_info = std::make_shared<ObjectInfo>();
obj_info->name = "doorsill";
for (auto &sill : practicalData->sills)
{
auto object = std::make_shared<Rectangle>(sill.dotFixed[0].x, sill.dotFixed[0].y, sill.dotFixed[1].x, sill.dotFixed[1].y,
sill.dotFixed[2].x, sill.dotFixed[2].y, sill.dotFixed[3].x, sill.dotFixed[3].y);
obj_info->objects.push_back(object);
LOG(INFO) << "name:" << obj_info->name << " pose:" << object->poses[0].x << "," << object->poses[0].y << " " << object->poses[1].x << "," << object->poses[1].y << " " << object->poses[2].x << "," << object->poses[2].y << " " << object->poses[3].x << "," << object->poses[3].y;
}
call_back(EventAddObjectToMap, obj_info);
}
break;
case EventRosWaveResult:
{
auto practicalData = RosDataType<EventRosWaveResult>::Dereference(data);
for (auto info : practicalData.get()->values)
{
if (onOffInfo::OnOffSensorValue::TYPE_CARPET == info.type && 1 == info.value)
{
auto items = std::make_shared<FilterItem>();
items->items.emplace_back(FilterItem::Info{"WaveFoundCarpet", Item(std::make_shared<bool>(true))});
call_back(EventAddItem, items);
}
}
}
break;
case EventRosCleanState:
{
LOG(INFO) << "EventRosCleanState";
auto practicalData = RosDataType<EventRosCleanState>::Dereference(data);
uint8_t state = practicalData->state;
uint8_t work_type = practicalData->worktype;
auto items = std::make_shared<FilterItem>();
items->items.emplace_back(FilterItem::Info{"workState", Item(std::make_shared<Numeric>(state)), -1});
items->items.emplace_back(FilterItem::Info{"workType", Item(std::make_shared<Numeric>(work_type)), -1});
items->items.emplace_back(FilterItem::Info{"currentCleanStart", Item(std::make_shared<std::string>(std::to_string(time(nullptr)))), -1});
if (WORK_TYPE_IDLE == work_type && (CLEAN_RUNNING == last_clean_state || CLEAN_PAUSED == last_clean_state))
{
LOG(INFO) << "Robot become IDLE";
last_clean_state = CLEAN_IDLE;
items->items.emplace_back(FilterItem::Info{"newClearRound", Item(std::make_shared<bool>(true))});
call_back(EventAddItem, items);
return;
}
if (work_type == WORK_TYPE_IDLE)
{
call_back(EventAddItem, items);
return;
}
if (last_clean_state == state)
{
call_back(EventAddItem, items);
return;
}
if (CLEAN_IDLE == last_clean_state && CLEAN_RUNNING == state)
{
items->items.emplace_back(FilterItem::Info{"newClearRound", Item(std::make_shared<bool>(true))});
}
else if (CLEAN_PAUSED == last_clean_state)
{
if (CLEAN_RUNNING == state)
{
LOG(INFO) << "Resume collect";
}
else if (CLEAN_IDLE == state)
{
items->items.emplace_back(FilterItem::Info{"roundFinished", Item(std::make_shared<bool>(true))});
}
}
else if (CLEAN_RUNNING == last_clean_state)
{
if (CLEAN_IDLE == state)
{
items->items.emplace_back(FilterItem::Info{"roundFinished", Item(std::make_shared<bool>(true))});
}
else if (CLEAN_PAUSED == state)
{
LOG(INFO) << "Collect paused";
}
}
last_clean_state = state;
LOG(INFO) << "New clean state:" << (int)last_clean_state;
call_back(EventAddItem, items);
}
break;
case EventRosChargeFailed:
{
LOG(INFO) << "EventRosChargeFailed";
auto practicalData = RosDataType<EventRosChargeFailed>::Dereference(data);
u_int16_t type = practicalData->type;
u_int32_t code = practicalData->code;
uint8_t reason = practicalData->reason;
LOG(INFO) << "chargeFailedType:" << type;
LOG(INFO) << "chargeFailedCode:" << code;
LOG(INFO) << "chargeFailedReason:" << reason;
auto items = std::make_shared<FilterItem>();
items->items.emplace_back(FilterItem::Info{"chargeFailedType", Item(std::make_shared<Numeric>(type))});
items->items.emplace_back(FilterItem::Info{"chargeFailedCode", Item(std::make_shared<std::string>(std::to_string(code)))});
items->items.emplace_back(FilterItem::Info{"chargeFailedReason", Item(std::make_shared<Numeric>(reason))});
call_back(EventAddItem, items);
}
break;
case EventRosLineLaserData:
{
auto practicalData = RosDataType<EventRosLineLaserData>::Dereference(data);
// 只需要正前方传感器
if (practicalData->idx == 1)
return;
std::vector<float> single_raw_linelsaer_data;
single_raw_linelsaer_data.push_back(practicalData->pose.pose.x);
single_raw_linelsaer_data.push_back(practicalData->pose.pose.y);
single_raw_linelsaer_data.push_back(practicalData->pose.pose.theta);
single_raw_linelsaer_data.push_back((int)practicalData->idx);
for (int i = 0; i < practicalData->points.size(); i++)
{
single_raw_linelsaer_data.push_back(practicalData->points[i].x);
single_raw_linelsaer_data.push_back(practicalData->points[i].y);
single_raw_linelsaer_data.push_back(practicalData->points[i].z);
single_raw_linelsaer_data.push_back(practicalData->grayscales[i]);
}
auto guard = DeebotStatus::instance().make_guard();
DeebotStatus::instance().current_raw_linelsaer_data = std::move(single_raw_linelsaer_data);
}
break;
case EventRosExternalTakePhoto:
{
LOG(INFO) << "EventRosExternalTakePhoto";
static int external_take_photo_id;
auto practicalData = RosDataType<EventRosExternalTakePhoto>::Dereference(data);
LOG(INFO)<<"EventRosExternalTakePhoto METADATA:"<<practicalData->metadata;
if (practicalData->type == 0)
{
auto items = std::make_shared<FilterItem>();
items->items.emplace_back(FilterItem::Info{"externalTakePhoto", Item(std::make_shared<bool>(true))});
try
{
json external_metadata_j = json::parse(practicalData->metadata);
int cnt = 0;
for (nlohmann::json::const_iterator it = external_metadata_j.begin(); it != external_metadata_j.end(); ++it)
{
if (++cnt > 5)
{
// 最大允许5个label
break;
}
if (it.value().is_number())
items->items.emplace_back(FilterItem::Info{it.key(), Item(std::make_shared<Numeric>(it.value().get<float>()))});
if (it.value().is_string())
items->items.emplace_back(FilterItem::Info{it.key(), Item(std::make_shared<std::string>(it.value().get<std::string>()))});
if (it.value().is_boolean())
items->items.emplace_back(FilterItem::Info{it.key(), Item(std::make_shared<bool>(it.value().get<bool>()))});
}
}
catch (...)
{
LOG(INFO) << "bad externalMetaData";
}
call_back(EventAddItem, items);
}
else if (practicalData->type == 1)
{
auto r = std::make_shared<CreateNewRuleChain>();
r->filter_expression = R"("mapObject":{"objType":"externalRequiredOBJ","objValue":#REPLACE_ME,"inView":true})";
std::string placeholder = "#REPLACE_ME";
size_t pos = r->filter_expression.find(placeholder);
if (pos != std::string::npos)
{
r->filter_expression.replace(pos, placeholder.length(), std::to_string(external_take_photo_id));
}
r->mission_info.name = "external_mission" + std::to_string(external_take_photo_id);
r->mission_info.filter_expression = r->filter_expression;
std::string syringe_str = R"([{"tag_name":"externalTakePhoto","time_to_live":"1","element":true}])";
auto syringe_config = json::parse(syringe_str);
json temp;
temp["tag_name"] = "externalMetaData";
temp["time_to_live"] = 1;
temp["element"] = practicalData->metadata;
syringe_config.push_back(temp);
int cnt = 0;
try
{
json external_metadata_j = json::parse(practicalData->metadata);
for (nlohmann::json::const_iterator it = external_metadata_j.begin(); it != external_metadata_j.end(); ++it)
{
if (++cnt > 5)
{
// 最大允许5个label
break;
}
json temp;
temp["tag_name"] = it.key();
temp["time_to_live"] = 1;
temp["element"] = it.value();
syringe_config.push_back(temp);
}
}
catch (...)
{
LOG(INFO) << "bad externalMetaData";
}
r->mission_info.collectors_info.push_back({"syringe", syringe_config});
r->limiter_config.push_back({"privacy", json()});
auto obj_info = std::make_shared<ObjectInfo>();
obj_info->name = "externalRequiredOBJ" + std::to_string(external_take_photo_id);
for (const auto &e : practicalData->points)
{
// 从点到矩形
auto object = std::make_shared<Rectangle>(e.x, e.y, e.x + 1, e.y, e.x, e.y + 1, e.x + 1, e.y + 1);
obj_info->objects.push_back(object);
LOG(INFO) << "name:" << obj_info->name << " pose:" << object->poses[0].x << "," << object->poses[0].y << " " << object->poses[1].x << "," << object->poses[1].y << " " << object->poses[2].x << "," << object->poses[2].y << " " << object->poses[3].x << "," << object->poses[3].y;
}
external_take_photo_id++;
call_back(EventAddObjectToMap, obj_info);
call_back(EventChainAddNewRuleWithJson, r);
}
}
break;
default:
LOG(INFO) << "bad event catch in " << get_module_name();
break;
}
}
std::string AdaptorModule::get_module_name()
{
return "AdaptorModule";
}
详细解释这段代码
最新发布