Skip to content

Commit c303525

Browse files
committed
Merge pull request #6 from tumbili/simulator_udp
implemented bidirectional udp communication with simulator
2 parents ad1865e + 9119687 commit c303525

File tree

2 files changed

+158
-54
lines changed

2 files changed

+158
-54
lines changed

src/modules/simulator/simulator.cpp

Lines changed: 109 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,18 @@
4545
#include <string.h>
4646
#include <sys/types.h>
4747
#include <drivers/drv_led.h>
48-
#ifndef __PX4_QURT
49-
#include <sys/socket.h>
50-
#include <netinet/in.h>
51-
#endif
48+
5249
#include "simulator.h"
53-
#include <drivers/drv_hrt.h>
5450

5551
using namespace simulator;
5652

5753
static px4_task_t g_sim_task = -1;
5854

5955
Simulator *Simulator::_instance = NULL;
6056

57+
static const uint8_t mavlink_message_lengths[256] = MAVLINK_MESSAGE_LENGTHS;
58+
static const uint8_t mavlink_message_crcs[256] = MAVLINK_MESSAGE_CRCS;
59+
6160
Simulator *Simulator::getInstance()
6261
{
6362
return _instance;
@@ -100,6 +99,83 @@ int Simulator::start(int argc, char *argv[])
10099
return ret;
101100
}
102101

102+
void Simulator::poll_topics() {
103+
// copy new data if available
104+
bool updated;
105+
orb_check(_actuator_outputs_sub, &updated);
106+
if(updated) {
107+
orb_copy(ORB_ID(actuator_outputs), _actuator_outputs_sub, &_actuators);
108+
}
109+
110+
orb_check(_vehicle_attitude_sub, &updated);
111+
if(updated) {
112+
orb_copy(ORB_ID(vehicle_attitude), _vehicle_attitude_sub, &_attitude);
113+
}
114+
}
115+
116+
void Simulator::send_data() {
117+
// check if it's time to send new data
118+
hrt_abstime time_now = hrt_absolute_time();
119+
if (time_now - _time_last >= (hrt_abstime)(_interval * 1000)) {
120+
_time_last = time_now;
121+
mavlink_message_t msg;
122+
pack_actuator_message(&msg);
123+
send_mavlink_message(MAVLINK_MSG_ID_SERVO_OUTPUT_RAW, &msg, 200);
124+
// can add more messages here, can also setup different timings
125+
}
126+
}
127+
128+
void Simulator::pack_actuator_message(mavlink_message_t *msg) {
129+
// pack message and send
130+
mavlink_servo_output_raw_t actuator_msg;
131+
132+
actuator_msg.time_usec = hrt_absolute_time();
133+
actuator_msg.port = 8; // hardcoded for now
134+
actuator_msg.servo1_raw = _actuators.output[0];
135+
actuator_msg.servo2_raw = _actuators.output[1];
136+
actuator_msg.servo3_raw = _actuators.output[2];
137+
actuator_msg.servo4_raw = _actuators.output[3];
138+
actuator_msg.servo5_raw = _actuators.output[4];
139+
actuator_msg.servo6_raw = _actuators.output[5];
140+
actuator_msg.servo7_raw = _actuators.output[6];
141+
actuator_msg.servo8_raw = _actuators.output[7];
142+
143+
// encode the message
144+
mavlink_msg_servo_output_raw_encode(1, 100, msg, &actuator_msg);
145+
}
146+
147+
void Simulator::send_mavlink_message(const uint8_t msgid, const void *msg, uint8_t component_ID) {
148+
uint8_t payload_len = mavlink_message_lengths[msgid];
149+
150+
uint8_t buf[MAVLINK_MAX_PACKET_LEN];
151+
152+
/* header */
153+
buf[0] = MAVLINK_STX;
154+
buf[1] = payload_len;
155+
/* no idea which numbers should be here*/
156+
buf[2] = 100;
157+
buf[3] = 1;
158+
buf[4] = component_ID;
159+
buf[5] = msgid;
160+
161+
/* payload */
162+
memcpy(&buf[MAVLINK_NUM_HEADER_BYTES],&msg, payload_len);
163+
164+
/* checksum */
165+
uint16_t checksum;
166+
crc_init(&checksum);
167+
crc_accumulate_buffer(&checksum, (const char *) &buf[1], MAVLINK_CORE_HEADER_LEN + payload_len);
168+
crc_accumulate(mavlink_message_crcs[msgid], &checksum);
169+
170+
buf[MAVLINK_NUM_HEADER_BYTES + payload_len] = (uint8_t)(checksum & 0xFF);
171+
buf[MAVLINK_NUM_HEADER_BYTES + payload_len + 1] = (uint8_t)(checksum >> 8);
172+
173+
ssize_t len = sendto(_fd, buf, sizeof(buf), 0, (struct sockaddr *)&_srcaddr, _addrlen);
174+
if (len <= 0) {
175+
PX4_WARN("Failed sending mavlink message");
176+
}
177+
}
178+
103179
void Simulator::fill_sensors_from_imu_msg(struct sensor_combined_s *sensor, mavlink_highres_imu_t *imu) {
104180
hrt_abstime timestamp = hrt_absolute_time();
105181
sensor->timestamp = timestamp;
@@ -221,7 +297,6 @@ void Simulator::publishSensorsCombined() {
221297
// advertise
222298
_sensor_combined_pub = orb_advertise(ORB_ID(sensor_combined), &sensors);
223299

224-
225300
hrt_abstime time_last = hrt_absolute_time();
226301
uint64_t delta;
227302
for(;;) {
@@ -270,46 +345,52 @@ void Simulator::updateSamples()
270345
// mag report
271346
struct mag_report mag;
272347
memset(&mag, 0 ,sizeof(mag));
348+
273349
// init publishers
274350
_baro_pub = orb_advertise(ORB_ID(sensor_baro), &baro);
275351
_accel_pub = orb_advertise(ORB_ID(sensor_accel), &accel);
276352
_gyro_pub = orb_advertise(ORB_ID(sensor_gyro), &gyro);
277353
_mag_pub = orb_advertise(ORB_ID(sensor_mag), &mag);
278354

279-
// get samples from external provider
280-
struct sockaddr_in myaddr;
281-
struct sockaddr_in srcaddr;
282-
socklen_t addrlen = sizeof(srcaddr);
283-
int len, fd;
284-
const int buflen = 200;
285-
const int port = 14550;
286-
unsigned char buf[buflen];
355+
// subscribe to topics
356+
_actuator_outputs_sub = orb_subscribe(ORB_ID(actuator_outputs));
357+
_vehicle_attitude_sub = orb_subscribe(ORB_ID(vehicle_attitude));
358+
359+
// try to setup udp socket for communcation with simulator
360+
memset((char *)&_myaddr, 0, sizeof(_myaddr));
361+
_myaddr.sin_family = AF_INET;
362+
_myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
363+
_myaddr.sin_port = htons(_port);
287364

288-
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
365+
if ((_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
289366
PX4_WARN("create socket failed\n");
290367
return;
291368
}
292369

293-
memset((char *)&myaddr, 0, sizeof(myaddr));
294-
myaddr.sin_family = AF_INET;
295-
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
296-
myaddr.sin_port = htons(port);
297-
298-
if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
370+
if (bind(_fd, (struct sockaddr *)&_myaddr, sizeof(_myaddr)) < 0) {
299371
PX4_WARN("bind failed\n");
300372
return;
301373
}
302374

375+
// this is used to time message sending
376+
_time_last = hrt_absolute_time();
377+
378+
// make socket non-blocking
379+
int flags = fcntl(_fd,F_GETFL);
380+
flags |= O_NONBLOCK;
381+
fcntl(_fd, F_SETFL, flags);
382+
383+
int len = 0;
303384
// wait for new mavlink messages to arrive
304385
for (;;) {
305-
len = 0;
306-
len = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&srcaddr, &addrlen);
386+
// see if we can receive data from simulator
387+
len = recvfrom(_fd, _buf, _buflen, 0, (struct sockaddr *)&_srcaddr, &_addrlen);
307388
if (len > 0) {
308389
mavlink_message_t msg;
309390
mavlink_status_t status;
310391
for (int i = 0; i < len; ++i)
311392
{
312-
if (mavlink_parse_char(MAVLINK_COMM_0, buf[i], &msg, &status))
393+
if (mavlink_parse_char(MAVLINK_COMM_0, _buf[i], &msg, &status))
313394
{
314395
// have a message, handle it
315396
handle_message(&msg);
@@ -324,35 +405,16 @@ void Simulator::updateSamples()
324405
gyro.timestamp = time_last;
325406
mag.timestamp = time_last;
326407
// publish the sensor values
327-
//printf("Publishing SensorsCombined\n");
328408
orb_publish(ORB_ID(sensor_baro), _baro_pub, &baro);
329409
orb_publish(ORB_ID(sensor_accel), _accel_pub, &baro);
330410
orb_publish(ORB_ID(sensor_gyro), _gyro_pub, &baro);
331411
orb_publish(ORB_ID(sensor_mag), _mag_pub, &mag);
332-
}
333412

334-
/*
335-
for (;;) {
336-
len = recvfrom(fd, buf, buflen, 0, (struct sockaddr *)&srcaddr, &addrlen);
337-
if (len > 0) {
338-
if (len == sizeof(RawMPUData)) {
339-
PX4_DBG("received: MPU data\n");
340-
_mpu.writeData(buf);
341-
}
342-
else if (len == sizeof(RawAccelData)) {
343-
PX4_DBG("received: accel data\n");
344-
_accel.writeData(buf);
345-
}
346-
else if (len == sizeof(RawBaroData)) {
347-
PX4_DBG("received: accel data\n");
348-
_baro.writeData(buf);
349-
}
350-
else {
351-
PX4_DBG("bad packet: len = %d\n", len);
352-
}
353-
}
413+
// see if there is new data to send to simulator
414+
poll_topics();
415+
send_data();
416+
usleep(10000);
354417
}
355-
*/
356418
}
357419
#endif
358420

src/modules/simulator/simulator.h

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,20 @@
4141
#include <semaphore.h>
4242
#include <uORB/topics/sensor_combined.h>
4343
#include <uORB/topics/manual_control_setpoint.h>
44+
#include <uORB/topics/actuator_outputs.h>
45+
#include <uORB/topics/vehicle_attitude.h>
4446
#include <drivers/drv_accel.h>
4547
#include <drivers/drv_gyro.h>
4648
#include <drivers/drv_baro.h>
4749
#include <drivers/drv_mag.h>
50+
#include <drivers/drv_hrt.h>
4851
#include <uORB/uORB.h>
4952
#include <v1.0/mavlink_types.h>
5053
#include <v1.0/common/mavlink.h>
54+
#include <sys/socket.h>
55+
#ifndef __PX4_QURT
56+
#include <netinet/in.h>
57+
#endif
5158

5259
namespace simulator {
5360

@@ -160,33 +167,68 @@ class Simulator {
160167
_baro(1),
161168
_sensor_combined_pub(-1),
162169
_manual_control_sp_pub(-1),
170+
_actuator_outputs_sub(-1),
171+
_vehicle_attitude_sub(-1),
163172
_sensor{},
164-
_manual_control_sp{}
165-
{}
173+
_manual_control_sp{},
174+
_actuators{},
175+
_attitude{},
176+
_interval(1000)
177+
{
178+
_buf = new unsigned char [_buflen];
179+
}
166180
~Simulator() { _instance=NULL; }
167181

168182
#ifndef __PX4_QURT
169183
void updateSamples();
170184
#endif
171-
void publishSensorsCombined();
172-
void fill_sensors_from_imu_msg(struct sensor_combined_s *sensor, mavlink_highres_imu_t *imu);
173-
void fill_manual_control_sp_msg(struct manual_control_setpoint_s *manual, mavlink_manual_control_t *man_msg);
174-
void handle_message(mavlink_message_t *msg);
175185

176186
static Simulator *_instance;
177187

188+
// simulated sensor instances
178189
simulator::Report<simulator::RawAccelData> _accel;
179190
simulator::Report<simulator::RawMPUData> _mpu;
180191
simulator::Report<simulator::RawBaroData> _baro;
181192

193+
// uORB publisher handlers
182194
orb_advert_t _accel_pub;
183195
orb_advert_t _baro_pub;
184196
orb_advert_t _gyro_pub;
185197
orb_advert_t _mag_pub;
186198
orb_advert_t _sensor_combined_pub;
187199
orb_advert_t _manual_control_sp_pub;
188200

201+
// uORB subscription handlers
202+
int _actuator_outputs_sub;
203+
int _vehicle_attitude_sub;
204+
205+
// uORB data containers
189206
struct sensor_combined_s _sensor;
190207
struct manual_control_setpoint_s _manual_control_sp;
208+
struct actuator_outputs_s _actuators;
209+
struct vehicle_attitude_s _attitude;
210+
211+
// udp socket data
212+
struct sockaddr_in _myaddr;
213+
struct sockaddr_in _srcaddr;
214+
socklen_t _addrlen = sizeof(_srcaddr);
215+
int _fd;
216+
const int _buflen = 200;
217+
const int _port = 14550;
218+
unsigned char *_buf;
219+
220+
hrt_abstime _time_last;
221+
int _interval;
222+
223+
// class methods
224+
int setup_udp_socket();
225+
void do_subscriptions();
226+
void poll_topics();
227+
void publishSensorsCombined();
228+
void fill_sensors_from_imu_msg(struct sensor_combined_s *sensor, mavlink_highres_imu_t *imu);
229+
void fill_manual_control_sp_msg(struct manual_control_setpoint_s *manual, mavlink_manual_control_t *man_msg);
230+
void handle_message(mavlink_message_t *msg);
231+
void send_data();
232+
void send_mavlink_message(const uint8_t msgid, const void *msg, uint8_t component_ID);
233+
void pack_actuator_message(mavlink_message_t *msg);
191234
};
192-

0 commit comments

Comments
 (0)