Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions core/frontend/src/components/vehiclesetup/PwmSetup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -426,15 +426,15 @@ export default Vue.extend({
this.motor_writer_interval = setInterval(this.write_motors, 100)
fetchCurrentBoard()

mavlink.setMessageRefreshRate({ messageName: 'SERVO_OUTPUT_RAW', refreshRate: 10 })
mavlink.subscribeMessageRefreshRate({ messageName: 'SERVO_OUTPUT_RAW', refreshRate: 10 })
this.desired_armed_state = this.is_armed
this.installListeners()
this.updateReversionValues()
},
beforeDestroy() {
clearInterval(this.motor_zeroer_interval)
clearInterval(this.motor_writer_interval)
mavlink.setMessageRefreshRate({ messageName: 'SERVO_OUTPUT_RAW', refreshRate: 1 })
mavlink.unsubscribeMessageRefreshRate({ messageName: 'SERVO_OUTPUT_RAW', refreshRate: 10 })
this.uninstallListeners()
},
methods: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,10 @@

<script lang="ts">

import { PropType } from 'vue'
import { markRaw, PropType } from 'vue'

import mavlink2rest from '@/libs/MAVLink2Rest'
import Listener from '@/libs/MAVLink2Rest/Listener'
import autopilot_data from '@/store/autopilot'
import autopilot from '@/store/autopilot_manager'
import { FirmwareVehicleType } from '@/types/autopilot'
Expand Down Expand Up @@ -93,6 +94,7 @@ export default {
manual_lat: this.inputcoordinates?.lat,
manual_lon: this.inputcoordinates?.lon,
original_ekf_src: undefined as number | undefined,
position_listener: undefined as Listener | undefined,
}
},
computed: {
Expand Down Expand Up @@ -136,13 +138,19 @@ export default {
},
mounted() {
this.original_ekf_src = this.current_ekf_src
mavlink2rest.startListening('GLOBAL_POSITION_INT').setCallback((receivedMessage) => {
this.mavlink_lat = receivedMessage.message.lat !== 0 ? receivedMessage.message.lat * 1e-7 : undefined
this.mavlink_lon = receivedMessage.message.lon !== 0 ? receivedMessage.message.lon * 1e-7 : undefined
}).setFrequency(0)
// markRaw: Listener -> Endpoint.latestData must not be deep-observed.
this.position_listener = markRaw(
mavlink2rest.startListening('GLOBAL_POSITION_INT').setCallback((receivedMessage) => {
this.mavlink_lat = receivedMessage.message.lat !== 0 ? receivedMessage.message.lat * 1e-7 : undefined
this.mavlink_lon = receivedMessage.message.lon !== 0 ? receivedMessage.message.lon * 1e-7 : undefined
}).setFrequency(0),
)
mavlink2rest.requestMessageRate('GLOBAL_POSITION_INT', 1, autopilot_data.system_id)
this.getGeoIp()
},
beforeDestroy() {
this.position_listener?.discard()
},
methods: {
async waitFor(func: () => boolean, raise = false): Promise<void> {
const start = new Date()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ const mainAngles = {
315: 'NW',
}

const COMPASS_REFRESH_MESSAGES = ['ATTITUDE', 'RAW_IMU', 'SCALED_IMU2', 'SCALED_IMU3', 'GPS_RAW_INT', 'GPS2_RAW']

export default Vue.extend({
name: 'CompassDisplay',
components: {
Expand All @@ -59,6 +61,7 @@ export default Vue.extend({
renderVariables: {
yawAngleDegrees: [0, 0, 0, 0, 0, 0],
},
render_interval: 0,
}
},
computed: {
Expand Down Expand Up @@ -131,8 +134,15 @@ export default Vue.extend({
this.canvas.height = this.canvasSize
})
this.initializeCanvas()
for (const msg of ['ATTITUDE', 'RAW_IMU', 'SCALED_IMU2', 'SCALED_IMU3', 'GPS_RAW_INT', 'GPS2_RAW']) {
mavlink.setMessageRefreshRate({ messageName: msg, refreshRate: 10 })
for (const msg of COMPASS_REFRESH_MESSAGES) {
mavlink.subscribeMessageRefreshRate({ messageName: msg, refreshRate: 10 })
}
},
beforeDestroy() {
clearInterval(this.render_interval)
gsap.killTweensOf(this.renderVariables.yawAngleDegrees)
for (const msg of COMPASS_REFRESH_MESSAGES) {
mavlink.unsubscribeMessageRefreshRate({ messageName: msg, refreshRate: 10 })
}
},
methods: {
Expand Down Expand Up @@ -289,7 +299,7 @@ export default Vue.extend({
}
},
initializeCanvas() {
setInterval(() => {
this.render_interval = window.setInterval(() => {
for (const [index, _value] of this.renderVariables.yawAngleDegrees.entries()) {
const angle = this.headings[index]
const angleDegrees = this.headings[index]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export default Vue.extend({
data() {
return {
dialog: false,
attitude_subscribed: false,
calibrating: false,
status_type: undefined as string | undefined,
status_text: undefined as string | undefined,
Expand All @@ -121,14 +122,32 @@ export default Vue.extend({
watch: {
dialog(open: boolean) {
if (open) {
mavlink.setMessageRefreshRate({ messageName: 'ATTITUDE', refreshRate: 10 })
this.subscribeAttitude()
} else {
this.unsubscribeAttitude()
this.status_text = undefined
this.status_type = undefined
}
},
},
beforeDestroy() {
this.unsubscribeAttitude()
},
methods: {
subscribeAttitude() {
if (this.attitude_subscribed) {
return
}
mavlink.subscribeMessageRefreshRate({ messageName: 'ATTITUDE', refreshRate: 10 })
this.attitude_subscribed = true
},
unsubscribeAttitude() {
if (!this.attitude_subscribed) {
return
}
mavlink.unsubscribeMessageRefreshRate({ messageName: 'ATTITUDE', refreshRate: 10 })
this.attitude_subscribed = false
},
calibrationFinished() {
this.status_type = 'success'
this.status_text = 'Calibration finished'
Expand Down
11 changes: 9 additions & 2 deletions core/frontend/src/components/vehiclesetup/overview/GyroCalib.vue
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ import mavlink_store_get from '@/utils/mavlink'

import { calibrator, PreflightCalibration } from '../calibration'

const GYRO_REFRESH_MESSAGES = ['RAW_IMU', 'SCALED_IMU2', 'SCALED_IMU3']

interface CalibrationStatus {
param?: Parameter
name: string
Expand Down Expand Up @@ -129,8 +131,13 @@ export default Vue.extend({
},
},
mounted() {
for (const msg of ['RAW_IMU', 'SCALED_IMU2', 'SCALED_IMU3']) {
mavlink.setMessageRefreshRate({ messageName: msg, refreshRate: 10 })
for (const msg of GYRO_REFRESH_MESSAGES) {
mavlink.subscribeMessageRefreshRate({ messageName: msg, refreshRate: 10 })
}
},
beforeDestroy() {
for (const msg of GYRO_REFRESH_MESSAGES) {
mavlink.unsubscribeMessageRefreshRate({ messageName: msg, refreshRate: 10 })
}
},
methods: {
Expand Down
65 changes: 55 additions & 10 deletions core/frontend/src/store/mavlink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@ interface messsageRefreshRate {
refreshRate: number
}

// Per-message requested rates from live consumers; wire rate is max(claims), or 1 Hz when empty.
const message_rate_claims: Dictionary<number[]> = {}
const IDLE_MESSAGE_RATE_HZ = 1

function claimedRefreshRate(messageName: string): number {
const claims = message_rate_claims[messageName]
if (!claims?.length) {
return IDLE_MESSAGE_RATE_HZ
}
return Math.max(...claims)
}

@Module({
dynamic: true,
store,
Expand All @@ -24,31 +36,64 @@ interface messsageRefreshRate {

class MavlinkStore extends VuexModule {
available_messages: Dictionary<MavlinkMessage> = {}

available_identified_messages: Dictionary<Dictionary<MavlinkMessage>> = {}

message_listeners: Dictionary<Listener> = {}

@Action({ commit: 'updateMessage' })
setMessageRefreshRate(rate: messsageRefreshRate): void {
@Action
subscribeMessageRefreshRate(rate: messsageRefreshRate): void {
const { messageName, refreshRate } = rate
if (refreshRate < 0) {
console.warn(`Invalid request rate requested for message ${messageName}@${refreshRate}Hz`)
return
}

mavlink2rest.requestMessageRate(messageName, refreshRate, autopilot_data.system_id)
// Remove any listener that has a lower frequency than requested
if (!message_rate_claims[messageName]) {
message_rate_claims[messageName] = []
}
message_rate_claims[messageName].push(refreshRate)
this.applyMessageRefreshRate(messageName)
}

@Action
unsubscribeMessageRefreshRate(rate: messsageRefreshRate): void {
const { messageName, refreshRate } = rate
const claims = message_rate_claims[messageName]
if (!claims?.length) {
return
}

const index = claims.indexOf(refreshRate)
if (index < 0) {
console.warn(`No ${refreshRate}Hz claim to release for message ${messageName}`)
return
}
claims.splice(index, 1)
this.applyMessageRefreshRate(messageName)
}

/** Lifetime / one-shot claim. Prefer subscribe/unsubscribe when the consumer leaves. */
@Action
setMessageRefreshRate(rate: messsageRefreshRate): void {
this.subscribeMessageRefreshRate(rate)
}

@Action
applyMessageRefreshRate(messageName: string): void {
const refreshRate = claimedRefreshRate(messageName)

// Equal rate: keep existing listener and skip the wire request.
// Any other rate change discards the listener and creates a replacement.
if (messageName in this.message_listeners) {
const currentRate = this.message_listeners[messageName].frequency
if (currentRate > refreshRate) {
console.warn(
`Request with higher rate already registered for message ${messageName}@${currentRate}Hz vs ${refreshRate}Hz`,
)
if (this.message_listeners[messageName].frequency === refreshRate) {
return
}
this.message_listeners[messageName].discard()
}

// Create a new listener
mavlink2rest.requestMessageRate(messageName, refreshRate, autopilot_data.system_id)

this.message_listeners[messageName] = mavlink2rest.startListening(messageName).setCallback((receivedMessage) => {
this.updateMessage({
messageName,
Expand Down
3 changes: 2 additions & 1 deletion core/frontend/src/views/MainView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,12 @@ export default Vue.extend({
mounted() {
window.addEventListener('resize', this.handleResize)
this.handleResize()
mavlink.setMessageRefreshRate({ messageName: 'ATTITUDE', refreshRate: 10 })
mavlink.subscribeMessageRefreshRate({ messageName: 'ATTITUDE', refreshRate: 10 })
this.fetch_streams_task.setAction(video.fetchStreams)
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
mavlink.unsubscribeMessageRefreshRate({ messageName: 'ATTITUDE', refreshRate: 10 })
},
methods: {
handleResize() {
Expand Down