У меня есть два приложения, которые работают как клиент / сервер TCP.
Первое приложение - это клиент, который использует OpenCV для обнаружения и отправки команд через TCP на сервер, который управляет мобильным роботом.
Мои приложения работают хорошо, если я нахожусь на своем развивающемся компьютере, но когда я тестирую его в реальном мире с моим роботом, я понимаю, что у меня есть некоторые задержки с обменом данными между клиентом и сервером.Это происходит потому, что компьютер, на котором я тестирую приложения, немного медленнее, чем мой развивающийся компьютер, который работает быстрее и не доставляет проблем.В реальном случае сервер не получает пакеты от клиента в режиме реального времени, поэтому он выполняет операции с задержкой.
Итак, проблема в том, что клиент теряет обнаружение и отправляет команды на сервер в порядкечтобы остановить это.Сервер получает пакеты с задержкой, поэтому, когда клиенты отправляют стоп-сервер (заголовок = 0, расстояние = 0, узловое соединение), сервер не получает команду сразу, потому что он получает пакеты предыдущих команд, и поэтому он останавливается только через несколько метров.
Я бы хотел найти решение, чтобы немедленно остановить сервер и отбросить все пакеты с движущейся информацией, потому что они бесполезны, если робот должен остановиться.Чтобы остановить робота, я отправляю пакет с запросом узла, который, к сожалению, не поступает в режиме реального времени, поэтому робот продолжает двигаться некоторое время.(Я делаю этот тест на той же машине, поэтому я подключаюсь к localhost)
В данный момент клиент использует этот код:
while (key_mode!='q')
{
//wait and error processing
context.WaitAnyUpdateAll();
// obtain al the metadata image,depthmap and scene
Mat frame = getImageFromKinect();
// do detection and tracking
switch(mode)
{
..
case ROBOT_CONTROL:
{
// Connect to the server
using boost::asio::ip::tcp;
boost::asio::io_service io_service;
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), server, boost::lexical_cast<string>(porta));
tcp::resolver::iterator iterator = resolver.resolve(query);
tcp::socket s(io_service);
try
{
s.connect(*iterator);
}
catch (boost::system::system_error const& e)
{
std::cout << "Warning: could not connect to the server\n" << e.what() << "\nPossible Solution: try to check is Server is UP\n" << std::endl;
}
..
..
float delta = heading - last_heading;
if (!is_equal(delta, 0.0)){
// heading_data = send_heading + token + boost::lexical_cast<std::string>(delta);
// heading_length = strlen(heading_data.c_str());
try
{
// boost::asio::write(s, boost::asio::buffer(heading_data, heading_length));
}
catch (boost::system::system_error const& e)
{
std::cout << "Warning: could not send commands : " << e.what() << std::endl;
}
}
last_heading = heading; // store current for next subtraction
#endif
#if 1
heading_scalato = heading / 3.0;
heading_data = send_heading + token + boost::lexical_cast<std::string>(heading_scalato);
heading_length = strlen(heading_data.c_str());
try
{
boost::asio::write(s, boost::asio::buffer(heading_data, heading_length));
}
catch (boost::system::system_error const& e)
{
std::cout << "Warning: could not send commands : " << e.what() << std::endl;
}
#endif
distance_data = send_distance + token + boost::lexical_cast<std::string>(distance);
distance_length = strlen(distance_data.c_str());
try
{
boost::asio::write(s, boost::asio::buffer(distance_data, distance_length));
}
catch (boost::system::system_error const& e)
{
std::cout << "Warning: could not connect : " << e.what() << std::endl;
}
..
..
// if it has to stop:
else
{
// stop rover
//control.setHeading(0.0);
//control.setDistance(0.0);
float heading = 0.0;
float distance = 0.0;
heading_data = send_heading + token + boost::lexical_cast<std::string>(heading);
distance_data = send_distance + token + boost::lexical_cast<std::string>(distance);
heading_length = heading_data.size();//strlen(heading_data.c_str());
distance_length = strlen(distance_data.c_str());
try
{
boost::asio::write(s, boost::asio::buffer(heading_data, heading_length));
boost::asio::write(s, boost::asio::buffer(distance_data, distance_length));
}
catch (boost::system::system_error const& e)
{
std::cout << "Warning: could not send commands : " << e.what() << std::endl;
}
// write info on image
char text[100];
sprintf(text,"ROBOT CONTROL: No detection");
putText(hogResultFrame,text,Point(4,89),FONT_HERSHEY_PLAIN,1,Scalar(0,0,0));
putText(hogResultFrame,text,Point(5,90),FONT_HERSHEY_PLAIN,1,Scalar(100,100,255));
nodetection_length = nodetection.size();
try
{
boost::asio::write(s, boost::asio::buffer(nodetection, nodetection_length));
}
catch (boost::system::system_error const& e)
{
std::cout << "Warning: could not send commands : " << e.what() << std::endl;
}
На сервере я использую:
void* runThread(void*)
{
while(Aria::getRunning())
{
if(start_routine){
if(temp_heading < 0.0){
printf("\n\nStarting Discovering routine, then sleeping 3 seconds.\a\n\n");
robot.setRotVel(5.0);
ArUtil::sleep(3000);
temp_heading = -1;
}
else if(temp_heading >= 0.0) {
printf("\n\nStarting Clockwise Discovering routine, then sleeping 3 seconds.\a\n\n");
robot.setRotVel(-5.0);
ArUtil::sleep(3000);
temp_heading = 1;
}
}
if( !flag_heading && !flag_distance)
{
myMutex.lock();
temp_heading=m_heading;
temp_distance=m_distance;
myMutex.unlock();
if (is_equal(temp_heading, 0.0)){
robot.setRotVel(0.0);
}
else robot.setRotVel(-ArMath::radToDeg(temp_heading));
if(temp_distance <= distanza_minima || is_equal(temp_distance, 0.0))
robot.setVel(0.0);
else
robot.setVel(float(temp_distance/20));
printf("runThread:: heading= %f distance = %f rob_vel = %f rob_rot_vel = %f\n",ArMath::radToDeg(temp_heading),temp_distance, robot.getVel(),robot.getRotVel());
flag_heading = true;
flag_distance = true;
start_routine = false;
}
ArUtil::sleep(100);
}
}
DataLine GetValueFromLine(const std::string& sData) {
std::string sName, sInteger;
std::stringstream ss;
DataLine Result;
size_t sz = sData.find('@');
sName = sData.substr(0,sz); // Just in case you need it later
Result.sName = sName;
sInteger = sData.substr(sz + 1,sData.length() - sz);
ss.str(sInteger);
ss >> Result.nNumber;
if (ss.fail()) {
// something went wrong, probably not an integer
}
return Result;
}
void session(socket_ptr sock)
{
try
{
for (;;)
{
char data[max_length];
boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), error);
data[length] = 0;
if (error == boost::asio::error::eof)
break; // Connection closed cleanly by peer.
else if (error)
throw boost::system::system_error(error); // Some other error.
output = GetValueFromLine(data);
std::cout << "*******************\n";
comando = output.sName;
valore = output.nNumber;
if (output.sName == "nodetection"){
start_routine = true;
std::cout << "\nSto ricevendo: " << output.sName;
}
else if (output.sName == "heading"){
start_routine = false;
control.setHeading(output.nNumber);
std::cout << "\nSto ricevendo: " << output.sName << "e heading: " << output.nNumber;
}
else if (output.sName == "distance"){
start_routine = false;
control.setDistance(output.nNumber);
std::cout << "\nSto ricevendo: " << output.sName << "e distance: " << output.nNumber;
}
// boost::asio::write(*sock, boost::asio::buffer(data, length));
}
}
catch (std::exception& e)
{
std::cerr << "Exception in thread: " << e.what() << "\n";
}
}
void server(boost::asio::io_service& io_service, short port)
{
tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
for (;;)
{
socket_ptr sock(new tcp::socket(io_service));
a.accept(*sock);
boost::thread t(boost::bind(session, sock));
}
}
int main(int argc, char **argv)
{
// control server initialitation..
....
boost::asio::io_service io_service;
server(io_service, porta);
return 0;
}
Я думал заставить клиента закрыть TCP-соединение, когда оно достигает условия отсутствия обнаружения, чтобы заставить сервер отклонять ожидающие пакеты, но как я могу это сделать?Как уничтожить указатель s в boost?
Есть ли другие решения?Если я закрываю соединение, сервер отклоняет ожидающие пакеты?