영상전송을 위한 ROS-> C++ Application(windows)통신 문제 대해 도움을 요청합니다.

870 views
Skip to first unread message

이재민

unread,
Apr 7, 2015, 11:56:12 AM4/7/15
to korea-r...@googlegroups.com

안녕하세요 한국ros사용자 그룹 유저분들께 여쭙고 싶은게 생겨서 글을 올리게 되었습니다.
저는 지금 rosbridge를 이용해 다른 PC에 설치된 ROS와 windows application간의 영상 전송을 위한 간단한 예제 프로그램을 구현하고 있습니다. 
windows쪽 작업환경은 VS2013에 websocket, json을 사용하기 위해 NuGet Package Manager에서 C++REST SDK를 설치하여 사용중입니다.
ROS에서는 usb_cam을 이용하여 usb_cam/Image_raw 메시지를 출력하고 있습니다.
windows app에서는 subscribe요청을 보내고 callback에서 데이터를 파싱하여 OpenCV Mat으로 변환하고자 합니다.

---windows app실행 시 문제점---
 
1. compression없이 전송을 받았을 때는  "data" 태그를 파싱하는 과정에서 abort()에러가 발생합니다. null이 반환되는 것으로 보아 데이터의 크기나 기타의 이유로 파싱이 정상적으로 이루어지지 않는 것 같습니다.
callback에서 받은 websocket을 출력해 보면 {"op" : "subscribe"..."data" : ".........."}와 같은 형태로 정상적으로 보입니다. 
2. compression=png로 전송을 받았을 때는 cv::imdecode에서 아래 그림과 같은 에러가 발생합니다.

callback에서 받은 websocket을 출력해 보면 {"data" : ".........."}와 같은 형태로 json태그의 일부가 출력되지 않습니다. 


topic과 같은 다른 태그는 정상적으로 불러올 수 있는 것으로 보아 데이터의 크기나 Base64파싱에 문제가 있는 것이라 생각되어 우선은 사용하는 websocket, json 라이브러리를 바꾸어볼까 생각하던 중에 의견을 여쭙고 싶어 이렇게 글을 올리게 되었습니다.

구현중인 windows app의 코드는 아래와 같습니다.

#include <cpprest/http_client.h>
#include <cpprest/filestream.h>
#include <cpprest/ws_client.h>
#include <cpprest/json.h>
#include <cpprest/asyncrt_utils.h>

#include <windows.h>
#include <opencv2/opencv.hpp>

using namespace web;                        // Common features like URIs.
using namespace web::websockets::client;
using namespace utility;                    // Common utilities like string conversions
using namespace utility::conversions;
using namespace concurrency::streams;       // Asynchronous streams

int main(int argc, char* argv[])
{
//websocket_client client;
websocket_callback_client client;
client.connect(U("ws://192.168.0.104:9090")).then([](pplx::task<void> t){
try
{
t.get();
}
catch (const websocket_exception& ex)
{
std::cout << ex.what();
}});
Sleep(100);

std::cout << "sending message to rosbridge" << std::endl;
websocket_outgoing_message out_msg;
web::json::value out_obj;

out_obj[U("op")] = json::value::string(U("subscribe"));
out_obj[U("topic")] = json::value::string(U("/usb_cam/image_raw"));
out_obj[U("type")] = json::value::string(U("sensor_msgs/Image"));
/*obj[U("throttle_rate")] = json::value::number(10);
obj[U("queue_length")] = json::value::number(10);
obj[U("fragment_size")] = json::value::number(10);*/
out_obj[U("compression")] = json::value::string(U("png"));

out_msg.set_utf8_message(to_utf8string(out_obj.serialize()));
auto send_task = client.send(out_msg).then([](pplx::task<void> t){
try
{
t.get();
}
catch (const websocket_exception& ex)
{
std::cout << ex.what();
}});
client.send(out_msg).then([](pplx::task<void> t){
try
{
t.get();
}
catch (const websocket_exception& ex)
{
std::cout << ex.what();
}});
send_task.wait();

//////////////////////////////////////////////////////////////////////////
//// WebSocket Message Callback
//////////////////////////////////////////////////////////////////////////
client.set_message_handler([](websocket_incoming_message msg)
{
std::cout << "receiving message to rosbridge" << std::endl;
json::value obj = json::value::parse(conversions::to_string_t(msg.extract_string().get()));
json::value imgValue = obj[U("data")];
json::value  topicValue = obj[U("topic")];

std::vector<unsigned char>imgdata = conversions::from_base64(imgValue.as_string());
cv::Mat buf_obj = cv::Mat(480, 640, CV_8U, imgdata.data());
cv::Mat img = imdecode(buf_obj, CV_LOAD_IMAGE_COLOR);
cv::imshow("png", img);
cv::waitKey(1);
});

while (true)
{
// client.receive().then([](websocket_incoming_message msg) {
// return msg.extract_string();
// }).then([](std::string body) {
// std::cout << body << std::endl;
// });
}

}


web 프로그래밍(?)은 처음이라 여러모로 애를 먹고 있네요... X(

Jihoon Lee

unread,
Apr 8, 2015, 12:31:11 AM4/8/15
to 이재민, korea-r...@googlegroups.com
안녕하세요,

상황이 정확하게 이해가 가지 않아서 정확한 답변을 못드리겠습니다. 현재 문제를 분석하면 다음 부분들에서 문제들이 있을수 있겠네요.

1. subscribe자체의 문제. subscribe시 데이터가 정상적으로 들어오지 않아서 문제가 생김.

-> 동일 데이터를 javascript 라이브러리를 이용한 브라우저에서 받아서 같은 데이터가 들어오는지 확인하면 쉽게 확인 가능

2. subscribe는 되지만 JSON으로 구성된 Topic 데이터(예 : std_msgs/String, geometry_msgs/Twist)파싱이 안되어 문제가 생김. 

-> 파싱문제도 금방 해결하실수 있을듯합니다.

3. 다른 Topic들은 되지만 sensor_msgs/Image 타입의 데이터에서만 문제가 생김.

-> 이게 질문의 요지이신거 같은데 이경우 uint8[] 데이타타입에 대해서 rosbridge가 base64 인코딩을 하는데 그 데이터를 디코딩할때 잘못 되어서 생기는 문제 일수 있겠네요.

cpp로 디코딩을 해본적이 없는지라 어떤 라이브러리를 이용해야되는지 잘모르겠네요. 대신 Java버젼의 rosbridge client 라이브러리가 있으니 코드를 보시면 해결에 참고가 되실껍니다. 


이후에 ROS 메시지 복원에 성공하시면 Using CvBridge To Convert Between ROS Images And OpenCV Images  튜토리얼을 참고하셔서 OpenCV 이미지로 변환하시면 되겠습니다.

ROS Image를 전송하는 또다른 방법으로는 web_video_server 이 있으니 참고하세요.

지훈 드림


-------------------------------------------
Jihoon Lee
Research Engineer
YujinRobot RnD
Tel      : +82-70-4657-7077

--
이 메일은 Google 그룹스 '한국 ROS 사용자' 그룹에 가입한 분들에게 전송되는 메시지입니다.
이 그룹에서 탈퇴하고 더 이상 이메일을 받지 않으려면 korea-ros-use...@googlegroups.com에 이메일을 보내세요.
이 그룹에 게시하려면 korea-r...@googlegroups.com에 이메일을 보내세요.
http://groups.google.com/group/korea-ros-users에서 이 그룹을 방문하세요.
더 많은 옵션을 보려면 https://groups.google.com/d/optout을(를) 방문하세요.

한승원

unread,
Oct 17, 2016, 4:31:10 AM10/17/16
to 한국 ROS 사용자
안녕하세요 혹시 이 문제 어떻게 해결하셨는지 궁금해서 이렇게 연락드립니다.

저도 지금 비슷한 상황에 있고.. pub 하는 중에 JSON 어쩌구 라는 오류가 뜨더라고요.. 해결방안 여쭤봐도될까요?
Reply all
Reply to author
Forward
0 new messages