Skip to main content

Plotting your own Data

Max Gallup

Max Gallup

Hardware Lead, Project Administrator

The Web-UI features not only the live feed from the camera, but also has the option to plot scalar values. All of the VU-ASE services have built-in types that the WebUI Recognizes to be able to plot them. But what if you would like to plot your own values? For this, we have two "generic" scalar types that you can use to plot values. The full list of generic messages can be found here, however the only two that can be plotted are GenericFloatScalar and GenericIntScalar.

This is what a data message will look like when plotted, in this case we are just sending a dummy sine data. Notice there is a custom label we can add "some_string". This is only to help you organize which streams are being printed, we recommend to use unique and descriptive names.

Generic Debug Data

The following are example services for each language that only plot sine data as shown in the picture above:

For this to work, make sure you add the testing output to your service.yaml!

src/main.go
package main

import (
"fmt"
"os"
"time"
"math"

pb_outputs "github.com/VU-ASE/rovercom/packages/go/outputs"
roverlib "github.com/VU-ASE/roverlib-go/src"

"github.com/rs/zerolog/log"
)

// The main user space program
// this program has all you need from roverlib: service identity, reading, writing and configuration
func run(service roverlib.Service, configuration *roverlib.ServiceConfiguration) error {
//
// Writing to an output that other services can read (see service.yaml to understand the output name)
//
writeStream := service.GetWriteStream("testing")
if writeStream == nil {
return fmt.Errorf("Failed to create write stream 'testing'")
}

angle := 0.0

for {

sineValue := math.Sin(angle)

// Initialize the message that we want to send to the actuator
output_msg := pb_outputs.SensorOutput{
Timestamp: uint64(time.Now().UnixMilli()), // milliseconds since epoch
Status: 0, // all is well
SensorId: 1,
SensorOutput: &pb_outputs.SensorOutput_GenericFloatScalar{
GenericFloatScalar: &pb_outputs.GenericFloatScalar{
Key: "some_string",
Value: float32(sineValue),
},
},

}

// Send the message to the actuator
err := writeStream.Write(&output_msg)
if err != nil {
log.Warn().Err(err).Msg("Could not write to actuator")
}
angle += 0.1
time.Sleep(100 * time.Millisecond)
}
}

// This function gets called when roverd wants to terminate the service
func onTerminate(sig os.Signal) error {
log.Info().Str("signal", sig.String()).Msg("Terminating service")

return nil
}

// This is just a wrapper to run the user program
// it is not recommended to put any other logic here
func main() {
roverlib.Run(run, onTerminate)
}