Basically I'm just making sure i'm going the right way about accessing positioning data from the piksi -- in either single or RTK mode.
If anyone can provide some additional simplified sample code for accessing positioning data, that would be greatly appreciated.
I'm using ubuntu 12.04 and it comes up under /dev/ttyUSB0 and i can cat /dev/ttyUSB0 and i get jibberish, so it must be outputting in SBP.
If I run the console.py and make sure it's all set up right and outputting solutions, is there any script that simply reads /dev/ttyUSB0 and gets the position solutions? I'm assuming SBP probably output some other things, like signal integrity and used satellites and such, but i really only need the positioning data.If anyone could help me with this it would be greately appreciated.
Our university (The University of Western Australia) purchased a pair for some final year student robotics projects.
If you could post those perl scripts you have written we will be extremely grateful.
If you don't have time to clean them up, don't worry. We can work on them and post them back here with your permission. Just having something to give us hints at using the SBP will be extremely helpful.We understand this will be your code and we'll credit you for it in anything that requires it.
--
You received this message because you are subscribed to the Google Groups "swiftnav-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swiftnav-discu...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
b = sbp.BaselineNED(data)
v = sbp.VelNED(data)
print "%.4f,%.4f,%.4f,%.4f,%.4f,%.4f" % \
(b.n * 1e-3, b.e * 1e-3, b.d * 1e-3, v.n * 1e-3, v.e * 1e-3, v.d * 1e-3 )
Also I'm not sure what I am doing wrong but I am getting a "No such file or directory" error when running the above example python script when it tries to open the serial on ttyUSB0. I can connect using the console though.
I have the example python code working no problem now. Did a reboot and it worked straight up so I deleted my previous post. Thanks though!
I think a tutorial on using the c library would be great. I think I am going to need the speed of c.
Thanks for all your hard work!
Anybody had any luck reading and parsing the data in C on linux? I'm stuck as.
--
You received this message because you are subscribed to a topic in the Google Groups "swiftnav-discuss" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/swiftnav-discuss/mfBn9L4UcJY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to swiftnav-discu...@googlegroups.com.
U just need to modify the fifo_read and decompose it every time data comes on ur UART buffer. I don't have access to my codebase, but I can share it on Monday.
#include <stdio.h>
#include <string.h>
#include <sbp.h>
#include <sbp_messages.h>
#include <sbp_messages.h>
#include <sbp_utils.h>
#include <nav_msg.h>
#include <gpstime.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#ifdef MAC
#include <IOKit/serial/ioss.h>
#else
#include <linux/serial.h>
#endif
// Simple per-connection context
typedef struct {
int fd;
char *path;
} context_t;
// State of the SBP message parser.
// Must be statically allocated.
//
sbp_state_t sbp_state;
context_t mycontext;
// Structs that messages from Piksi will feed.
sbp_pos_llh_t pos_llh;
sbp_baseline_ned_t baseline_ned;
sbp_vel_ned_t vel_ned;
sbp_dops_t dops;
sbp_gps_time_t gps_time;
sbp_heartbeat_t heartbeat;
// SBP callback nodes must be statically allocated. Each message ID / callback
// pair must have a unique sbp_msg_callbacks_node_t associated with it.
//
sbp_msg_callbacks_node_t pos_llh_node;
sbp_msg_callbacks_node_t baseline_ned_node;
sbp_msg_callbacks_node_t vel_ned_node;
sbp_msg_callbacks_node_t dops_node;
sbp_msg_callbacks_node_t gps_time_node;
sbp_msg_callbacks_node_t heartbeat_node;
u32 serialread(u8 *buf, u32 n, void* context) {
context_t ctx = *(context_t *)context;
return read(ctx.fd, buf, n);
}
u32 serialwrite(u8 *buf, u32 n, void* context) {
context_t ctx = *(context_t *)context;
u32 orig = n;
while (n) {
ssize_t v = write(ctx.fd, buf, n);
if (v < 0) {
return v;
}
buf += v;
n -= v;
}
return orig;
}
/*
* Callback functions to interpret SBP messages.
* Every message ID has a callback associated with it to
* receive and interpret the message payload.
*/
void sbp_pos_llh_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
pos_llh = *(sbp_pos_llh_t *)msg;
printf("{\"type\":\"absolution position\", \"sender\":%d, \"latitude\":%1.10f, \"longitude\":%1.10f, \"altitude\":%1.10f, \"numsatellites\":%d}\n", sender_id, pos_llh.lat, pos_llh.lon, pos_llh.height, pos_llh.n_sats);
}
void sbp_baseline_ned_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
baseline_ned = *(sbp_baseline_ned_t *)msg;
printf("{\"type\": \"baseline ned mm\", \"sender\": %d, \"north\":%d \"east\":%d, \"down\":%d}\n", sender_id, (int)baseline_ned.n, (int)baseline_ned.e, (int)baseline_ned.d);
}
void sbp_vel_ned_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
vel_ned = *(sbp_vel_ned_t *)msg;
printf("{\"type\":\"velocity ned mm/s\", \"sender\":%d, \"north\":%d, \"east\":%d, \"down\":%d}\n", sender_id, (int)vel_ned.n, (int)vel_ned.e, (int)vel_ned.d);
}
void sbp_dops_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
dops = *(sbp_dops_t *)msg;
printf("{\"type\":\"dilution of precision\", \"sender\":%d, \"gdop\":%1.2f, \"hdop\":%1.2f, \"pdop\":%1.2f, \"tdop\":%1.2f, \"vdop\":%1.2f}\n", sender_id, (float)dops.gdop/100, (float)dops.hdop/100, (float)dops.pdop/100, (float)dops.tdop/100, (float)dops.vdop/100);
}
void sbp_gps_time_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
gps_time = *(sbp_gps_time_t *)msg;
gps_time_t out;
out.tow = (float)gps_time.tow / 1e3;
out.wn = gps_time.wn;
time_t now = gps2time(out);
printf("{\"type\":\"gps time\", \"sender\":%d, \"week\":%d, \"seconds\":%d, \"unix\":%lld}\n", sender_id, (int)gps_time.wn, (int)((float)gps_time.tow / 1e3), (unsigned long long)now);
}
void sbp_heartbeat_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
heartbeat = *(sbp_heartbeat_t *)msg;
printf("{\"type\":\"heartbeat\", \"sender\":%d, \"flags\":%d}\n", sender_id, heartbeat.flags);
}
/*
* Set up SwiftNav Binary Protocol (SBP) nodes; the sbp_process function will
* search through these to find the callback for a particular message ID.
*
* Example: sbp_pos_llh_callback is registered with sbp_state, and is associated
* with both a unique sbp_msg_callbacks_node_t and the message ID SBP_POS_LLH.
* When a valid SBP message with the ID SBP_POS_LLH comes through the UART, written
* to the FIFO, and then parsed by sbp_process, sbp_pos_llh_callback is called
* with the data carried by that message.
*/
void sbp_setup(sbp_state_t *sbp_state, context_t *context) {
// SBP parser state must be initialized before sbp_process is called.
sbp_state_init(sbp_state);
sbp_state_set_io_context(sbp_state, context);
// Register a node and callback, and associate them with a specific message ID.
sbp_register_callback(sbp_state, SBP_HEARTBEAT, &sbp_heartbeat_callback, NULL, &heartbeat_node);
sbp_register_callback(sbp_state, SBP_GPS_TIME, &sbp_gps_time_callback, NULL, &gps_time_node);
sbp_register_callback(sbp_state, SBP_POS_LLH, &sbp_pos_llh_callback, NULL, &pos_llh_node);
sbp_register_callback(sbp_state, SBP_BASELINE_NED, &sbp_baseline_ned_callback, NULL, &baseline_ned_node);
sbp_register_callback(sbp_state, SBP_VEL_NED, &sbp_vel_ned_callback, NULL, &vel_ned_node);
sbp_register_callback(sbp_state, SBP_DOPS, &sbp_dops_callback, NULL, &dops_node);
}
int openSerial(char *path, speed_t baud) {
printf("Opening %s\b\n", path);
int fd = open(path, O_RDONLY | O_NOCTTY);
struct termios toptions;
bzero(&toptions, sizeof(toptions));
if (tcgetattr(fd, &toptions) < 0) {
perror("tcgetattr");
return -1;
}
toptions.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
toptions.c_iflag = IGNPAR;
toptions.c_oflag = 0;
toptions.c_lflag = 0;
#ifndef MAC
struct serial_struct ss;
ioctl(fd, TIOCGSERIAL, &ss);
ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
ss.custom_divisor = ss.baud_base / baud;
ioctl(fd, TIOCSSERIAL, &ss);
#endif
cfsetispeed(&toptions, B38400);
cfsetospeed(&toptions, B38400);
toptions.c_cc[VMIN] = 5; // blocking read until 1 char received
toptions.c_cc[VTIME] = 0; // inter-character timer unused
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW, &toptions) < 0) {
perror("tcsetattr");
return -1;
}
#ifdef MAC
ioctl(fd, IOSSIOSPEED, &baud);
#endif
return fd;
}
int main(int argc, char **argv) {
mycontext.path = argv[1];
mycontext.fd = openSerial(argv[1], 1000000);
sbp_setup(&sbp_state, &mycontext);
while (1) {
sbp_process(&sbp_state, &serialread);
}
}.Couldn't you just register sbp_state as the context instead of the NULL?
sbp_register_callback(sbp_state, SBP_HEARTBEAT, &sbp_heartbeat_callback, NULL, &heartbeat_node);
This is the context passed into the callback, and not the same as io_context
sbp_register_callback(sbp_state, 0x45, &sbp_packed_obs_callback, NULL, &packed_ops_node);
void sbp_packed_obs_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
sbp_state_t *otherunit = sender_id == sbp_state1.sender_id ? &sbp_state2 : &sbp_state1;
sbp_send_message(otherunit, 0x45, sender_id, len, msg, &serialwrite);
}
u32 serialwrite(u8 *buf, u32 n, void* context) {
context_t ctx = *(context_t *)context;
u32 orig = n;
while (n) {
ssize_t v = write(ctx.fd, buf, n);
if (v < 0) {
return v;
}
buf += v;
n -= v;
}
return orig;
}
// Simple example to display SBP messages from Piksi on Linux or Mac,
// and optionally relay observations from one Piksi to another over USB
//
// To relay observations, both Pikis should be plugged in via USB and
// the path to both units should be passed in as arguments, along with
// the baud rate.
//
// To compile on Mac, #define MAC
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sbp.h>
#include <sbp_messages.h>
#include <sbp_utils.h>
#include <nav_msg.h>
#include <gpstime.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#ifdef MAC
#include <IOKit/serial/ioss.h>
#else
#include <linux/serial.h>
#endif
// Simple per-connection context
typedef struct {
int fd;
char *path;
} context_t;
// State of the SBP message parser.
// Must be statically allocated.
//
sbp_state_t sbp_state1, sbp_state2;
context_t context1, context2;
// Structs that messages from Piksi will feed.
sbp_pos_llh_t pos_llh;
sbp_baseline_ned_t baseline_ned;
sbp_vel_ned_t vel_ned;
sbp_dops_t dops;
sbp_gps_time_t gps_time;
sbp_heartbeat_t heartbeat;
// SBP callback nodes must be statically allocated. Each message ID / callback
// pair must have a unique sbp_msg_callbacks_node_t associated with it.
//
sbp_msg_callbacks_node_t pos_llh_node;
sbp_msg_callbacks_node_t baseline_ned_node;
sbp_msg_callbacks_node_t vel_ned_node;
sbp_msg_callbacks_node_t dops_node;
sbp_msg_callbacks_node_t gps_time_node;
sbp_msg_callbacks_node_t heartbeat_node;
sbp_msg_callbacks_node_t packed_ops_node;
u32 serialread(u8 *buf, u32 n, void* context) {
context_t ctx = *(context_t *)context;
return read(ctx.fd, buf, n);
}
u32 serialwrite(u8 *buf, u32 n, void* context) {
context_t ctx = *(context_t *)context;
u32 orig = n;
while (n) {
ssize_t v = write(ctx.fd, buf, n);
if (v < 0) {
return v;
}
buf += v;
n -= v;
}
return orig;
}
/*
* Callback functions to interpret SBP messages.
* Every message ID has a callback associated with it to
* receive and interpret the message payload.
*/
void sbp_pos_llh_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
pos_llh = *(sbp_pos_llh_t *)msg;
printf("{\"type\":\"absolution position\", \"sender\":%d, \"latitude\":%1.10f, \"longitude\":%1.10f, \"altitude\":%1.10f, \"numsatellites\":%d}\n", sender_id, pos_llh.lat, pos_llh.lon, pos_llh.height, pos_llh.n_sats);
}
void sbp_baseline_ned_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
baseline_ned = *(sbp_baseline_ned_t *)msg;
// Note - I'm only really in fixed NED position. Report floating NED to show we're getting signal
if (baseline_ned.flags & 1) {
// Fixed
printf("{\"type\":\"baseline ned mm\", \"sender\":%d, \"north\":%d \"east\":%d, \"down\":%d}\n", sender_id, (int)baseline_ned.n, (int)baseline_ned.e, (int)baseline_ned.d);
} else {
// Floating
printf("{\"type\":\"baseline ned mm\", \"sender\":%d}\n", sender_id);
}
}
void sbp_vel_ned_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
vel_ned = *(sbp_vel_ned_t *)msg;
printf("{\"type\":\"velocity ned mm/s\", \"sender\":%d, \"north\":%d, \"east\":%d, \"down\":%d}\n", sender_id, (int)vel_ned.n, (int)vel_ned.e, (int)vel_ned.d);
}
void sbp_dops_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
dops = *(sbp_dops_t *)msg;
printf("{\"type\":\"dilution of precision\", \"sender\":%d, \"gdop\":%1.2f, \"hdop\":%1.2f, \"pdop\":%1.2f, \"tdop\":%1.2f, \"vdop\":%1.2f}\n", sender_id, (float)dops.gdop/100, (float)dops.hdop/100, (float)dops.pdop/100, (float)dops.tdop/100, (float)dops.vdop/100);
}
void sbp_gps_time_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
gps_time = *(sbp_gps_time_t *)msg;
gps_time_t out;
out.tow = (float)gps_time.tow / 1e3;
out.wn = gps_time.wn;
time_t now = gps2time(out);
printf("{\"type\":\"gps time\", \"sender\":%d, \"week\":%d, \"seconds\":%d, \"unix\":%lld}\n", sender_id, (int)gps_time.wn, (int)((float)gps_time.tow / 1e3), (unsigned long long)now);
}
void sbp_heartbeat_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
heartbeat = *(sbp_heartbeat_t *)msg;
printf("{\"type\":\"heartbeat\", \"sender\":%d, \"flags\":%d}\n", sender_id, heartbeat.flags);
}
void sbp_packed_obs_callback(u16 sender_id, u8 len, u8 msg[], void *context) {
printf("{\"type\":\"packed obs\", \"sender\":%d, \"length\":%d}\n", sender_id, len);
// Relay this message from one unit to another
if (context2.fd) {
sbp_state_t *other = sender_id == sbp_state1.sender_id ? &sbp_state2 : &sbp_state1;
sbp_send_message(other, 0x45, sender_id, len, msg, &serialwrite);
}
}
/*
* Set up SwiftNav Binary Protocol (SBP) nodes; the sbp_process function will
* search through these to find the callback for a particular message ID.
*
* Example: sbp_pos_llh_callback is registered with sbp_state, and is associated
* with both a unique sbp_msg_callbacks_node_t and the message ID SBP_POS_LLH.
* When a valid SBP message with the ID SBP_POS_LLH comes through the UART, written
* to the FIFO, and then parsed by sbp_process, sbp_pos_llh_callback is called
* with the data carried by that message.
*/
void sbp_setup(sbp_state_t *sbp_state, context_t *context) {
// SBP parser state must be initialized before sbp_process is called.
sbp_state_init(sbp_state);
sbp_state_set_io_context(sbp_state, context);
// Register a node and callback, and associate them with a specific message ID.
sbp_register_callback(sbp_state, SBP_HEARTBEAT, &sbp_heartbeat_callback, NULL, &heartbeat_node);
sbp_register_callback(sbp_state, SBP_GPS_TIME, &sbp_gps_time_callback, NULL, &gps_time_node);
sbp_register_callback(sbp_state, SBP_POS_LLH, &sbp_pos_llh_callback, NULL, &pos_llh_node);
sbp_register_callback(sbp_state, SBP_BASELINE_NED, &sbp_baseline_ned_callback, NULL, &baseline_ned_node);
sbp_register_callback(sbp_state, SBP_VEL_NED, &sbp_vel_ned_callback, NULL, &vel_ned_node);
sbp_register_callback(sbp_state, SBP_DOPS, &sbp_dops_callback, NULL, &dops_node);
sbp_register_callback(sbp_state, 0x45, &sbp_packed_obs_callback, NULL, &packed_ops_node);
}
int openSerial(char *path, speed_t baud) {
printf("Opening %s\b\n", path);
int fd = open(path, O_RDWR | O_NOCTTY);
struct termios toptions;
bzero(&toptions, sizeof(toptions));
if (tcgetattr(fd, &toptions) < 0) {
perror("tcgetattr");
return -1;
}
toptions.c_cflag = CRTSCTS | CS8 | CLOCAL | CREAD;
toptions.c_iflag = IGNPAR;
toptions.c_oflag = 0;
toptions.c_lflag = 0;
#ifndef MAC
struct serial_struct ss;
ioctl(fd, TIOCGSERIAL, &ss);
ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST;
ss.custom_divisor = ss.baud_base / baud;
ioctl(fd, TIOCSSERIAL, &ss);
#endif
cfsetispeed(&toptions, B38400);
cfsetospeed(&toptions, B38400);
toptions.c_cc[VMIN] = 5; // blocking read until 5 chars received
toptions.c_cc[VTIME] = 0; // inter-character timer unused
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW, &toptions) < 0) {
perror("tcsetattr");
return -1;
}
#ifdef MAC
ioctl(fd, IOSSIOSPEED, &baud);
#endif
return fd;
}
int main(int argc, char **argv) {
if (argc < 3) {
printf("Usage: test <baudrate> <tty1> [<tty2>]\n");
}
int baud = atoi(argv[1]);
context1.path = argv[2];
context1.fd = openSerial(argv[2], baud);
sbp_setup(&sbp_state1, &context1);
if (argc > 3) {
context2.fd = openSerial(argv[3], baud);
context2.path = argv[3];
sbp_setup(&sbp_state2, &context2);
}
while (1) {
sbp_process(&sbp_state1, &serialread);
if (context2.fd) {
sbp_process(&sbp_state2, &serialread);
}
}
}
--
// Serial setupint serial_setup(char* port, int baud){ fd = open(port, O_RDONLY | O_NOCTTY);
if (fd == -1) { return -1; }
struct termios toptions; bzero(&toptions, sizeof(toptions));
toptions.c_cflag = baud | CS8 | CLOCAL | CREAD; toptions.c_iflag = IGNPAR; toptions.c_oflag = 0; toptions.c_lflag = 0;
cfsetispeed(&toptions, baud); cfsetospeed(&toptions, baud); toptions.c_cc[VMIN] = 5; toptions.c_cc[VTIME] = 0; tcflush(fd, TCIFLUSH);
return 0;}
// Read serialu32 read_serial(u8 *buf, u32 n, void* context){ return read(fd, buf, n);}
// Setup peripheralsrc = serial_setup("/dev/ttyO1", B115200);if (rc == -1) { fprintf(stderr, "Unable to connect to GPS\n"); exit(EXIT_FAILURE);}Hi all.I'm sorry if this question has been already answered somewhere.Basically I'm just making sure i'm going the right way about accessing positioning data from the piksi -- in either single or RTK mode.I saw on the wiki there's a tute for C++ with some basic single board computer, but it seemed a bit complicated.Then i tried the libswiftnav-python, but the documentation didn't make it easy to understand which functions to call to get positioning data.If anyone can provide some additional simplified sample code for accessing positioning data, that would be greatly appreciated.Also, I noticed by running the console.py in the piksi_firmware/script folder, files such as position,baseline,velocity_log...csv are created and seem to have some data...Is this how people are going about extracting positioning data from the piksi (i.e. reading the last line of those files)? Or is this going to be too delayed and these files are just meant to be used as log files.I need to access the data relatively quickly so I can use it with ROS (robot operating system). I think I read a few people are developing a ROS driver for the piksi. Anyone have any updates on that?Thanks in advance if anyone can help me with these questions.
No problem! I'll email it through in a bit.
On Wednesday, 29 October 2014 06:50:03 UTC+10, Colin Beighley wrote:
Hey Joe,I believe Sam Thomas got this working. Sam, would you be interested in sharing your work with Joe?
Colinᐧ
On Tue, Oct 28, 2014 at 1:46 PM, Joe Auchter <joe.a...@gmail.com> wrote:
Hello Colin,I also need to receive SBP messages in C (or C++) on a Linux host, over USB. Have you had a chance to put together the demo you mentioned?Thank you,
Joe
On Friday, August 15, 2014 2:56:14 PM UTC-5, Colin Beighley wrote:
Noted - I'll try to set aside some time to create a demo for receiving SBP messages in C on a Linux host.
On Fri, Aug 15, 2014 at 12:23 PM, Sam Thomas <samthoma...@gmail.com> wrote:
Hey Colin!
I have the example python code working no problem now. Did a reboot and it worked straight up so I deleted my previous post. Thanks though!
I think a tutorial on using the c library would be great. I think I am going to need the speed of c.
Thanks for all your hard work!
--
You received this message because you are subscribed to the Google Groups "swiftnav-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swiftnav-discu...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.