Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
B
bachelor thesis
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Christoph Schröter
bachelor thesis
Commits
8d83766b
Commit
8d83766b
authored
3 years ago
by
cs-99
Browse files
Options
Downloads
Patches
Plain Diff
No commit message
No commit message
parent
3935e573
No related branches found
No related tags found
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
main.cpp
+102
-33
102 additions, 33 deletions
main.cpp
with
102 additions
and
33 deletions
main.cpp
+
102
−
33
View file @
8d83766b
...
@@ -5,7 +5,21 @@
...
@@ -5,7 +5,21 @@
#include
<netinet/in.h>
#include
<netinet/in.h>
#include
<arpa/inet.h>
#include
<arpa/inet.h>
typedef
unsigned
char
byte
;
typedef
uint8_t
byte
;
// consts for TRON ----------------------------------------------------------
const
byte
GET_ERROR_MSG
=
127
;
const
byte
DECL_CHAN_INPUT
=
1
;
const
byte
DECL_CHAN_OUTPUT
=
2
;
const
byte
ADD_VAR_TO_INPUT
=
3
;
const
byte
ADD_VAR_TO_OUTPUT
=
4
;
const
byte
SET_TIME_UNIT
=
5
;
const
byte
SET_TIMEOUT
=
6
;
const
byte
REQUEST_START
=
64
;
const
byte
ANSWER_START
=
0
;
const
int32_t
ACK_SINGLE
=
-
2147483648
;
// 32 Bit int with most significant bit set to 1
// function declarations --------------------------------------------------------
// function declarations --------------------------------------------------------
// gets count bytes from socket file descriptor
// gets count bytes from socket file descriptor
...
@@ -14,25 +28,25 @@ std::unique_ptr<byte[]> get_bytes_socket(int fd, int count);
...
@@ -14,25 +28,25 @@ std::unique_ptr<byte[]> get_bytes_socket(int fd, int count);
// log bytes sent/received
// log bytes sent/received
void
byte_info
(
const
byte
*
msg
,
int
msg_length
,
bool
send
=
true
);
void
byte_info
(
const
byte
*
msg
,
int
msg_length
,
bool
send
=
true
);
// wrapping get_bytes_socket for converting to integer
// wrapping get_bytes_socket for converting to
32 bit
integer
int
get_int_socket
(
int
fd
);
int
32_t
get_int_socket
(
int
fd
);
// retrieves error message and prints it, then throws
// retrieves error message and prints it, then throws
void
get_error_msg
(
int
fd
,
int
errorcode
);
// needs fix see implementation
void
get_error_msg
(
int
fd
,
int
32_t
errorcode
);
// needs fix see implementation
// converts num to network order and adds it to msg starting from index
// converts num to network order and adds it to msg starting from index
void
add_int32_in_network_order
(
int
num
,
byte
*
msg
,
int
index
);
void
add_int32_in_network_order
(
int
32_t
num
,
byte
*
msg
,
int
index
);
// wraps write() for printing and throwing on errors
// wraps write() for printing and throwing on errors
void
send_bytes
(
int
fd
,
const
byte
*
bytes
,
int
length
);
void
send_bytes
(
int
fd
,
const
byte
*
bytes
,
int
length
);
void
set_time_unit_and_timeout
(
int
fd
,
u
nsigned
long
in
t
microseconds
,
int
timeout
);
void
set_time_unit_and_timeout
(
int
fd
,
u
int64_
t
microseconds
,
int
32_t
timeout
);
// attaches UPPAAL variable called var to channel
// attaches UPPAAL variable called var to channel
void
add_var_to_channel
(
int
fd
,
std
::
string
channel
,
bool
is_input
,
std
::
string
var
);
void
add_var_to_channel
(
int
fd
,
std
::
string
channel
,
bool
is_input
,
std
::
string
var
);
// reports to var_count variables to channel named chan_name
// reports to var_count variables to channel named chan_name
void
report_now
(
int
fd
,
std
::
string
chan_name
,
unsigned
short
var_count
,
int
*
vars
);
void
report_now
(
int
fd
,
std
::
string
chan_name
,
unsigned
short
var_count
,
int
32_t
*
vars
);
// throws if not answered with byte 0
// throws if not answered with byte 0
void
request_start
(
int
fd
);
void
request_start
(
int
fd
);
...
@@ -40,10 +54,10 @@ void request_start(int fd);
...
@@ -40,10 +54,10 @@ void request_start(int fd);
const
double
SECONDS_BEFORE_TIMEOUT
=
30
;
const
double
SECONDS_BEFORE_TIMEOUT
=
30
;
struct
Channel
{
struct
Channel
{
int
identifier
;
int
32_t
identifier
;
bool
is_input
;
bool
is_input
;
std
::
vector
<
std
::
string
>
vars
;
// associated variables in Uppaal
std
::
vector
<
std
::
string
>
vars
;
// associated variables in Uppaal
Channel
(
int
id
,
bool
is_input
)
:
identifier
(
id
),
is_input
(
is_input
)
,
vars
()
{};
Channel
(
int
32_t
id
,
bool
is_input
)
:
identifier
(
id
),
is_input
(
is_input
){};
Channel
()
=
default
;
// default constructor needed for std::map
Channel
()
=
default
;
// default constructor needed for std::map
};
};
std
::
map
<
std
::
string
,
Channel
>
channels
;
std
::
map
<
std
::
string
,
Channel
>
channels
;
...
@@ -67,14 +81,22 @@ std::unique_ptr<byte[]> get_bytes_socket(int fd, int count){
...
@@ -67,14 +81,22 @@ std::unique_ptr<byte[]> get_bytes_socket(int fd, int count){
return
arr
;
// no explicit move needed since return value is rvalue
return
arr
;
// no explicit move needed since return value is rvalue
};
};
int
get_int_socket
(
int
fd
)
{
int32_t
bytes_to_int_32
(
byte
*
ptr
){
uint32_t
h
=
ntohl
(
*
reinterpret_cast
<
uint32_t
*>
(
ptr
));
return
*
reinterpret_cast
<
int32_t
*>
(
&
h
);
}
uint16_t
bytes_to_uint_16
(
byte
*
ptr
)
{
return
ntohs
(
*
reinterpret_cast
<
uint16_t
*>
(
ptr
));
}
int32_t
get_int_socket
(
int
fd
)
{
auto
ack
=
get_bytes_socket
(
fd
,
4
);
auto
ack
=
get_bytes_socket
(
fd
,
4
);
unsigned
int
h
=
ntohl
(
*
reinterpret_cast
<
unsigned
int
*>
(
ack
.
get
()));
return
bytes_to_int_32
(
ack
.
get
());
return
*
reinterpret_cast
<
int
*>
(
&
h
);
// reinterpret unsigned int as int
}
}
void
add_int32_in_network_order
(
int
num
,
byte
*
msg
,
int
index
){
void
add_int32_in_network_order
(
int
32_t
num
,
byte
*
msg
,
int
index
){
u
nsigned
in
t
n
=
htonl
(
*
reinterpret_cast
<
u
nsigned
in
t
*>
(
&
num
));
u
int32_
t
n
=
htonl
(
*
reinterpret_cast
<
u
int32_
t
*>
(
&
num
));
byte
*
bytes
=
reinterpret_cast
<
byte
*>
(
&
n
);
byte
*
bytes
=
reinterpret_cast
<
byte
*>
(
&
n
);
msg
[
index
]
=
bytes
[
0
];
msg
[
index
]
=
bytes
[
0
];
msg
[
++
index
]
=
bytes
[
1
];
msg
[
++
index
]
=
bytes
[
1
];
...
@@ -95,10 +117,10 @@ void send_bytes(int fd, const byte* bytes, int length){
...
@@ -95,10 +117,10 @@ void send_bytes(int fd, const byte* bytes, int length){
if
(
ret
<
0
)
throw
"writing failed"
;
if
(
ret
<
0
)
throw
"writing failed"
;
}
}
void
get_error_msg
(
int
fd
,
int
errorcode
)
{
void
get_error_msg
(
int
fd
,
int
32_t
errorcode
)
{
ROS_WARN
(
"got error, trying to get corresponding message"
);
ROS_WARN
(
"got error, trying to get corresponding message"
);
std
::
unique_ptr
<
byte
[]
>
get_err_msg_msg
=
std
::
make_unique
<
byte
[]
>
(
5
);
std
::
unique_ptr
<
byte
[]
>
get_err_msg_msg
=
std
::
make_unique
<
byte
[]
>
(
5
);
get_err_msg_msg
[
0
]
=
127
;
// get error msg code
get_err_msg_msg
[
0
]
=
GET_ERROR_MSG
;
// get error msg code
add_int32_in_network_order
(
errorcode
,
get_err_msg_msg
.
get
(),
1
);
add_int32_in_network_order
(
errorcode
,
get_err_msg_msg
.
get
(),
1
);
send_bytes
(
fd
,
get_err_msg_msg
.
get
(),
5
);
// connection is closed after this write?
send_bytes
(
fd
,
get_err_msg_msg
.
get
(),
5
);
// connection is closed after this write?
byte
err_msg_length
=
get_bytes_socket
(
fd
,
1
)[
0
];
byte
err_msg_length
=
get_bytes_socket
(
fd
,
1
)[
0
];
...
@@ -111,14 +133,14 @@ void get_error_msg(int fd, int errorcode) {
...
@@ -111,14 +133,14 @@ void get_error_msg(int fd, int errorcode) {
void
add_var_to_channel
(
int
fd
,
std
::
string
channel
,
bool
is_input
,
std
::
string
var
)
{
void
add_var_to_channel
(
int
fd
,
std
::
string
channel
,
bool
is_input
,
std
::
string
var
)
{
std
::
unique_ptr
<
byte
[]
>
msg
=
std
::
make_unique
<
byte
[]
>
(
6
+
var
.
length
());
std
::
unique_ptr
<
byte
[]
>
msg
=
std
::
make_unique
<
byte
[]
>
(
6
+
var
.
length
());
if
(
channels
.
find
(
channel
)
==
channels
.
end
())
throw
"channel not declared"
;
if
(
channels
.
find
(
channel
)
==
channels
.
end
())
throw
"channel not declared"
;
Channel
chan
=
channels
.
at
(
channel
);
Channel
&
chan
=
channels
.
at
(
channel
);
msg
[
0
]
=
is_input
?
3
:
4
;
msg
[
0
]
=
is_input
?
ADD_VAR_TO_INPUT
:
ADD_VAR_TO_OUTPUT
;
add_int32_in_network_order
(
chan
.
identifier
,
msg
.
get
(),
1
);
add_int32_in_network_order
(
chan
.
identifier
,
msg
.
get
(),
1
);
msg
[
5
]
=
(
byte
)
var
.
length
();
msg
[
5
]
=
(
byte
)
var
.
length
();
for
(
int
i
=
0
;
i
<
var
.
length
();
i
++
)
msg
[
6
+
i
]
=
var
.
at
(
i
);
for
(
int
i
=
0
;
i
<
var
.
length
();
i
++
)
msg
[
6
+
i
]
=
var
.
at
(
i
);
ROS_INFO
(
"attaching variable %s to channel %s"
,
var
.
c_str
(),
channel
.
c_str
());
ROS_INFO
(
"attaching variable %s to channel %s"
,
var
.
c_str
(),
channel
.
c_str
());
send_bytes
(
fd
,
msg
.
get
(),
6
+
var
.
length
());
send_bytes
(
fd
,
msg
.
get
(),
6
+
var
.
length
());
int
ack
=
get_int_socket
(
fd
);
int
32_t
ack
=
get_int_socket
(
fd
);
if
(
ack
<
0
)
get_error_msg
(
fd
,
ack
);
if
(
ack
<
0
)
get_error_msg
(
fd
,
ack
);
ROS_INFO
(
"success: attached variable"
);
ROS_INFO
(
"success: attached variable"
);
chan
.
vars
.
push_back
(
var
);
chan
.
vars
.
push_back
(
var
);
...
@@ -128,7 +150,7 @@ void send_channel_decl_msg(int fd, bool is_input, std::string name) {
...
@@ -128,7 +150,7 @@ void send_channel_decl_msg(int fd, bool is_input, std::string name) {
// prepare packet
// prepare packet
size_t
msg_length
=
2
+
name
.
length
();
size_t
msg_length
=
2
+
name
.
length
();
std
::
unique_ptr
<
byte
[]
>
msg
=
std
::
make_unique
<
byte
[]
>
(
msg_length
);
std
::
unique_ptr
<
byte
[]
>
msg
=
std
::
make_unique
<
byte
[]
>
(
msg_length
);
msg
[
0
]
=
is_input
?
1
:
2
;
msg
[
0
]
=
is_input
?
DECL_CHAN_INPUT
:
DECL_CHAN_OUTPUT
;
msg
[
1
]
=
name
.
length
();
msg
[
1
]
=
name
.
length
();
for
(
int
i
=
2
,
c
=
0
;
i
<
msg_length
;
i
++
,
c
++
)
msg
[
i
]
=
name
[
c
];
for
(
int
i
=
2
,
c
=
0
;
i
<
msg_length
;
i
++
,
c
++
)
msg
[
i
]
=
name
[
c
];
...
@@ -138,7 +160,7 @@ void send_channel_decl_msg(int fd, bool is_input, std::string name) {
...
@@ -138,7 +160,7 @@ void send_channel_decl_msg(int fd, bool is_input, std::string name) {
write
(
fd
,
(
void
*
)
msg
.
get
(),
msg_length
);
write
(
fd
,
(
void
*
)
msg
.
get
(),
msg_length
);
// get answer from TRON
// get answer from TRON
int
channel_identifier
=
get_int_socket
(
fd
);
int
32_t
channel_identifier
=
get_int_socket
(
fd
);
if
(
channel_identifier
<
0
)
{
// error handling
if
(
channel_identifier
<
0
)
{
// error handling
get_error_msg
(
fd
,
channel_identifier
);
get_error_msg
(
fd
,
channel_identifier
);
}
}
...
@@ -148,9 +170,9 @@ void send_channel_decl_msg(int fd, bool is_input, std::string name) {
...
@@ -148,9 +170,9 @@ void send_channel_decl_msg(int fd, bool is_input, std::string name) {
channels
[
name
]
=
Channel
(
channel_identifier
,
is_input
);
channels
[
name
]
=
Channel
(
channel_identifier
,
is_input
);
}
}
void
set_time_unit_and_timeout
(
int
fd
,
unsigned
long
int
microseconds
,
int
timeout
){
void
set_time_unit_and_timeout
(
int
fd
,
unsigned
long
long
microseconds
,
int
32_t
timeout
){
std
::
unique_ptr
<
byte
[]
>
msg
=
std
::
make_unique
<
byte
[]
>
(
9
);
std
::
unique_ptr
<
byte
[]
>
msg
=
std
::
make_unique
<
byte
[]
>
(
9
);
msg
[
0
]
=
5
;
msg
[
0
]
=
SET_TIME_UNIT
;
byte
*
microseconds_bytes
=
reinterpret_cast
<
byte
*>
(
&
microseconds
);
byte
*
microseconds_bytes
=
reinterpret_cast
<
byte
*>
(
&
microseconds
);
// htonl does not exist for long int
// htonl does not exist for long int
...
@@ -162,12 +184,12 @@ void set_time_unit_and_timeout(int fd, unsigned long int microseconds, int timeo
...
@@ -162,12 +184,12 @@ void set_time_unit_and_timeout(int fd, unsigned long int microseconds, int timeo
}
}
ROS_INFO
(
"setting time unit: %i microseconds"
,
microseconds
);
ROS_INFO
(
"setting time unit: %i microseconds"
,
microseconds
);
send_bytes
(
fd
,
msg
.
get
(),
9
);
send_bytes
(
fd
,
msg
.
get
(),
9
);
int
ack
=
get_int_socket
(
fd
);
int
32_t
ack
=
get_int_socket
(
fd
);
if
(
ack
!=
0
)
get_error_msg
(
fd
,
ack
);
if
(
ack
!=
0
)
get_error_msg
(
fd
,
ack
);
ROS_INFO
(
"success: set time unit"
);
ROS_INFO
(
"success: set time unit"
);
msg
.
reset
(
new
byte
[
5
]);
msg
.
reset
(
new
byte
[
5
]);
msg
[
0
]
=
6
;
msg
[
0
]
=
SET_TIMEOUT
;
add_int32_in_network_order
(
timeout
,
msg
.
get
(),
1
);
add_int32_in_network_order
(
timeout
,
msg
.
get
(),
1
);
ROS_INFO
(
"setting timeout to %i units"
,
timeout
);
ROS_INFO
(
"setting timeout to %i units"
,
timeout
);
send_bytes
(
fd
,
msg
.
get
(),
5
);
send_bytes
(
fd
,
msg
.
get
(),
5
);
...
@@ -178,15 +200,15 @@ void set_time_unit_and_timeout(int fd, unsigned long int microseconds, int timeo
...
@@ -178,15 +200,15 @@ void set_time_unit_and_timeout(int fd, unsigned long int microseconds, int timeo
void
request_start
(
int
fd
)
{
void
request_start
(
int
fd
)
{
ROS_INFO
(
"requesting start"
);
ROS_INFO
(
"requesting start"
);
byte
start
=
64
;
byte
start
=
REQUEST_START
;
send_bytes
(
fd
,
&
start
,
1
);
send_bytes
(
fd
,
&
start
,
1
);
byte
answer
=
get_bytes_socket
(
fd
,
1
)[
0
];
byte
answer
=
get_bytes_socket
(
fd
,
1
)[
0
];
if
(
answer
!=
0
)
throw
"starting failed"
;
if
(
answer
!=
ANSWER_START
)
throw
"starting failed"
;
ROS_INFO
(
"success: starting test phase"
);
ROS_INFO
(
"success: starting test phase"
);
}
}
// nach input verarbeitung weiter machen
// nach input verarbeitung weiter machen
void
report_now
(
int
fd
,
std
::
string
chan_name
,
u
nsigned
shor
t
var_count
,
int
*
vars
){
void
report_now
(
int
fd
,
std
::
string
chan_name
,
u
int16_
t
var_count
,
int
32_t
*
vars
){
std
::
unique_ptr
<
byte
[]
>
msg
=
std
::
make_unique
<
byte
[]
>
(
6
+
4
*
var_count
);
std
::
unique_ptr
<
byte
[]
>
msg
=
std
::
make_unique
<
byte
[]
>
(
6
+
4
*
var_count
);
if
(
channels
.
find
(
chan_name
)
==
channels
.
end
())
throw
"channel not declared"
;
if
(
channels
.
find
(
chan_name
)
==
channels
.
end
())
throw
"channel not declared"
;
Channel
chan
=
channels
.
at
(
chan_name
);
Channel
chan
=
channels
.
at
(
chan_name
);
...
@@ -237,13 +259,13 @@ int main(int argc, char**argv){
...
@@ -237,13 +259,13 @@ int main(int argc, char**argv){
ROS_INFO
(
"successfully connected to TRON"
);
ROS_INFO
(
"successfully connected to TRON"
);
try
{
try
{
send_channel_decl_msg
(
socketfd
,
true
,
"ausloesen"
);
send_channel_decl_msg
(
socketfd
,
true
,
"ausloesen"
);
//
add_var_to_channel(socketfd, "ausloesen", true, "
globa
l");
add_var_to_channel
(
socketfd
,
"ausloesen"
,
true
,
"
zah
l"
);
send_channel_decl_msg
(
socketfd
,
false
,
"position"
);
send_channel_decl_msg
(
socketfd
,
false
,
"position"
);
add_var_to_channel
(
socketfd
,
"position"
,
false
,
"zahl"
);
add_var_to_channel
(
socketfd
,
"position"
,
false
,
"zahl"
);
// nicht in dokumentation: lokale variablen nicht möglich
// nicht in dokumentation: lokale variablen nicht möglich
//add_var_to_channel(socketfd, "ausloesen", "lokal");
//add_var_to_channel(socketfd, "ausloesen", "lokal");
unsigned
long
int
microseconds
=
1000000
;
// one second
unsigned
long
long
microseconds
=
1000000
;
// one second
// Dokumentation arbeitet mit 2 unsigned ints, äußerst mystisch
// Dokumentation arbeitet mit 2 unsigned ints, äußerst mystisch
set_time_unit_and_timeout
(
socketfd
,
microseconds
,
10
);
set_time_unit_and_timeout
(
socketfd
,
microseconds
,
10
);
...
@@ -252,13 +274,60 @@ int main(int argc, char**argv){
...
@@ -252,13 +274,60 @@ int main(int argc, char**argv){
// 127 ist gerErrorMessage
// 127 ist gerErrorMessage
request_start
(
socketfd
);
// communication not synchronous anymore after start
request_start
(
socketfd
);
// communication not synchronous anymore after start
// listen to topics
int
acks_needed
=
0
;
ros
::
Rate
rate
(
1
);
while
(
ros
::
ok
())
{
while
(
true
){
// checking for messages arrived
// get 4 bytes at a time
std
::
unique_ptr
<
byte
[]
>
bytes
=
std
::
make_unique
<
byte
[]
>
(
4
);
int
bytes_recv
=
recv
(
socketfd
,
bytes
.
get
(),
4
,
MSG_DONTWAIT
);
if
(
bytes_recv
==
-
1
)
break
;
// nothing more to read
if
(
bytes_recv
==
0
)
throw
"connection was closed"
;
if
(
bytes_recv
!=
4
)
throw
"could not read full ack or chanID"
;
byte_info
(
bytes
.
get
(),
4
,
false
);
int32_t
next
=
bytes_to_int_32
(
bytes
.
get
());
// if those 4 bytes are acknowledgement decrement amount of acks needed;
if
(
next
==
ACK_SINGLE
)
{
if
(
--
acks_needed
<
0
)
throw
"too many acknowledgements"
;
ROS_INFO
(
"got acknowledgement for output"
);
continue
;
}
std
::
string
chan_name
;
for
(
std
::
pair
<
const
std
::
string
,
Channel
>&
pair
:
channels
)
{
if
(
pair
.
second
.
identifier
==
next
)
chan_name
=
pair
.
first
;
}
if
(
chan_name
.
empty
())
throw
"channel could not be identified"
;
ROS_INFO
(
"got channel identifier (%s) for input"
,
chan_name
.
c_str
());
// channel identified, assuming following bytes are correct
bytes
=
std
::
make_unique
<
byte
[]
>
(
2
);
recv
(
socketfd
,
bytes
.
get
(),
2
,
MSG_DONTWAIT
);
byte_info
(
bytes
.
get
(),
2
,
false
);
uint16_t
var_count
=
bytes_to_uint_16
(
bytes
.
get
());
ROS_INFO
(
"got variable count %i"
,
var_count
);
for
(
uint16_t
i
=
0
;
i
<
var_count
;
i
++
)
{
bytes
=
std
::
make_unique
<
byte
[]
>
(
4
);
recv
(
socketfd
,
bytes
.
get
(),
4
,
MSG_DONTWAIT
);
next
=
bytes_to_int_32
(
bytes
.
get
());
Channel
&
c
=
channels
.
at
(
chan_name
);
std
::
string
var
=
channels
.
at
(
chan_name
).
vars
[
i
];
ROS_INFO
(
"got variable number %i: value of %s is %i"
,
i
+
1
,
channels
.
at
(
chan_name
).
vars
[
i
].
c_str
(),
next
);
// TODO transfer message to topic
}
bytes
=
std
::
make_unique
<
byte
[]
>
(
4
);
add_int32_in_network_order
(
ACK_SINGLE
,
bytes
.
get
(),
0
);
ROS_INFO
(
"sending acknowledgement"
);
send_bytes
(
socketfd
,
bytes
.
get
(),
4
);
}
ros
::
spinOnce
();
rate
.
sleep
();
}
// erst nach ausloesen input wäre akzeptierbar
// erst nach ausloesen input wäre akzeptierbar
int
zahl
=
4
;
int
32_t
zahl
=
4
;
//report_now(socketfd, "position", 1, &zahl);
//report_now(socketfd, "position", 1, &zahl);
}
catch
(
const
char
*
err
){
}
catch
(
const
char
*
err
){
ROS_FATAL
(
"shutting down: %s"
,
err
);
ROS_FATAL
(
"shutting down: %s"
,
err
);
ros
::
shutdown
();
ros
::
shutdown
();
}
}
ros
::
Duration
(
100
).
sleep
();
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment