Skip to content

Comments

Provide estimated power, duration, distance and coverage on mission planning#2123

Merged
ArturoManzoli merged 3 commits intobluerobotics:masterfrom
ArturoManzoli:1235b-provide-power-duration-distance-on-mission-planning
Oct 2, 2025
Merged

Provide estimated power, duration, distance and coverage on mission planning#2123
ArturoManzoli merged 3 commits intobluerobotics:masterfrom
ArturoManzoli:1235b-provide-power-duration-distance-on-mission-planning

Conversation

@ArturoManzoli
Copy link
Contributor

@ArturoManzoli ArturoManzoli commented Sep 11, 2025

  • This feature is BlueBoat specific and will only be available if the vehicle type is MAV_TYPE_SURFACE_BOAT;
  • Calculated power consumption based on the BlueBoat data sheet is very close to the real results, although not considering wind and stream. Those parameters can be integrated on a further implementation;
  • Time estimates are quite accurate, based on BBoat default MAVLink parameters. On a further implementation, the integration with vehicle's turning rate, acceleration and braking parameters will provide even more accurate estimates;
  • Users can configure extra payload, extra battery capacity and different battery chemistry (1);
  • Added a measuring tag on the mission planning wp insertion cursor (2);
  • Latest estimates compared with real vehicle mission's logs (3) (4) (5) (6) on a moderate wind condition;
  • There is a disclaimer about the estimates (7);
  • Survey coverage area is displayed on its center after creation;
  • Total survey coverage area is calculated and displayed on the statistics board (8);
  • MAVLink wp commands like DO_CHANGE_SPEED also affect time and energy consumption estimates;

(1)

Screenshare.-.2025-09-11.9_38_36.AM.mp4

(2)
image

(3)
mission_planned

(4)
wind

(5)
current

(6)
power_consumption_log

(7)
disclaimer

(8)
coverage_2

Closes #1235
Closes #1459

@ArturoManzoli ArturoManzoli changed the title Provide estimated power, duration and distances on mission planning Provide estimated power, duration and distance and coverage on mission planning Sep 11, 2025
@ArturoManzoli ArturoManzoli changed the title Provide estimated power, duration and distance and coverage on mission planning Provide estimated power, duration, distance and coverage on mission planning Sep 11, 2025
@rafaellehmkuhl
Copy link
Member

Amazing work.

@ArturoManzoli ArturoManzoli marked this pull request as draft September 11, 2025 18:04
@ArturoManzoli ArturoManzoli force-pushed the 1235b-provide-power-duration-distance-on-mission-planning branch 2 times, most recently from 686b2c7 to 495a476 Compare September 12, 2025 19:52
@ArturoManzoli ArturoManzoli marked this pull request as ready for review September 12, 2025 19:52
@ArturoManzoli
Copy link
Contributor Author

@rafaellehmkuhl modifications done! ready for review

Copy link
Member

@rafaellehmkuhl rafaellehmkuhl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice addition!

I've made some small considerations around the codebase.

Functionality-wise some bugs were added in the survey creation (comments in the audio):

Kapture.2025-09-17.at.10.15.44.mp4

Comment on lines 46 to 58
const setSurveyAreaM2 = (id: string, areaM2: number): void => {
surveyAreaM2ById.value = { ...surveyAreaM2ById.value, [id]: areaM2 }
}

const removeSurveyAreaM2 = (id: string): void => {
const next = { ...surveyAreaM2ById.value }
delete next[id]
surveyAreaM2ById.value = next
}

const clearAllSurveyAreas = (): void => {
surveyAreaM2ById.value = {}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those methods are only used in the useMissionStatistics composable. It's better to keep them there, as this data is not shared across any other components.

Also, can we rename them to setSurveyAreaSquareMeters and removeSurveyAreaSquareMeters?

Comment on lines 174 to 227
const turnPenaltySeconds = computed(() => {
const wps = missionStore.currentPlanningWaypoints || []
let secs = 0
if (wps.length >= 2) secs += 1 // adds deceleration time
for (let i = 1; i < wps.length - 1; i++) {
const prev = wps[i - 1].coordinates as LatLng
const cur = wps[i].coordinates as LatLng
const next = wps[i + 1].coordinates as LatLng
const diff = deltaBearing(bearingBetween(prev, cur), bearingBetween(cur, next))
if (diff > 45) secs += 1 + 1 + Math.ceil(diff / 15)
}
return secs
})

// Vehicle parameter input
const speedMps = computed<number>(() => {
const speed = Number((missionStore as any).defaultCruiseSpeed)
return speed > 0 ? speed : 1
})

// Extra payload in kg
const payloadKg = computed<number>(() => {
const payload = Number(vehicleStore.vehiclePayloadParameters?.extraPayloadKg)
return Number.isFinite(payload) && payload >= 0 ? payload : 0
})

// Battery mass & capacity from count
const batteryMassKg = computed<number>(() => {
const battCapacity = Number(vehicleStore.vehiclePayloadParameters?.batteryCapacity) || 2 * 266.4 // default battery pack capacity
const chem = (vehicleStore.vehiclePayloadParameters?.batteryChemistry ?? 'li-ion') as BatteryChemistry
const kgPerWh = kgPerWhByChem[chem] ?? kgPerWhByChem['li-ion']
return battCapacity * kgPerWh
})

// Power estimate
const powerW = computed(() => {
const originalBatteryMassKg = 1.152 * 2 // default battery pack mass
const totalExtraMass = payloadKg.value + (batteryMassKg.value - originalBatteryMassKg)
const pAt1 = Math.max(5, basePowerAtOneMs + massSlopeWPerKg1Mps * totalExtraMass)
const speed = Math.max(0.1, speedMps.value)
return pAt1 * Math.pow(speed / 1.0, speedExponent)
})

// Estimate mission time with added penalties
const missionETASeconds = computed(() => {
if (speedMps.value <= 0) return NaN
return missionLengthMeters.value / speedMps.value + turnPenaltySeconds.value
})

// Energy consumption estimate (Wh)
const missionEnergyWh = computed(() => {
if (!isFinite(missionETASeconds.value)) return NaN
return (powerW.value * missionETASeconds.value) / 3600
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move those methods that are estimations based on vehicle parameters to a dedicated .ts file? This way it is much easier for someone extending this functionality in the future (e.g.: for aerial drones) without messing with UI-related code (as this composable).

Copy link
Contributor Author

@ArturoManzoli ArturoManzoli Sep 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops. Indeed it could to be moved

@ArturoManzoli
Copy link
Contributor Author

ArturoManzoli commented Sep 17, 2025

Nice addition!

I've made some small considerations around the codebase.

Functionality-wise some bugs were added in the survey creation (comments in the audio):

I think this behavior is the same that we had before this feature was implemented. Check out the video below, where I start creating a survey the same way you did, and it goes like on blind-mode, until the third vertex is added to the polygon. From that point on, every extra click adds an extra vertex, as it is on master:

Maybe what is happening is that we are now providing an extra reference to the polygon creation and we naturally expect the creation process to have more extra references than that.
We can anyway, improve the survey polygon creation on a secondary PR, for sure

And about the waypoints not being created bug: Its not a bug, what you saw was caused by the size of the polygon you drew. It was a square with less than 10 meter each side, so with the distance between survey lines being set to 10 meters, barely no line would be created.

survey.creation.mp4

@rafaellehmkuhl
Copy link
Member

Nice addition!
I've made some small considerations around the codebase.
Functionality-wise some bugs were added in the survey creation (comments in the audio):

I think this behavior is the same that we had before this feature was implemented. Check out the video below, where I start creating a survey the same way you did, and it goes like on blind-mode, until the third vertex is added to the polygon. From that point on, every extra click adds an extra vertex, as it is on master:

Maybe what is happening is that we are now providing an extra reference to the polygon creation and we naturally expect the creation process to have more extra references than that. We can anyway, improve the survey polygon creation on a secondary PR, for sure

And about the waypoints not being created bug: Its not a bug, what you saw was caused by the size of the polygon you drew. It was a square with less than 10 meter each side, so with the distance between survey lines being set to 10 meters, barely no line would be created.

survey.creation.mp4

It makes sense! Tested again and the problem was indeed the size of the survey.

@ArturoManzoli ArturoManzoli force-pushed the 1235b-provide-power-duration-distance-on-mission-planning branch from 495a476 to d5f85f1 Compare September 18, 2025 10:35
@ArturoManzoli
Copy link
Contributor Author

I've made some small considerations around the codebase.

All considerations addressed!

@rafaellehmkuhl
Copy link
Member

I've made some small considerations around the codebase.

All considerations addressed!

Did you take a look at these ones? It seems like they are as before.

@ArturoManzoli ArturoManzoli force-pushed the 1235b-provide-power-duration-distance-on-mission-planning branch 2 times, most recently from 24a24f2 to 53ba4be Compare September 22, 2025 17:26
@ArturoManzoli
Copy link
Contributor Author

ArturoManzoli commented Sep 22, 2025

I've made some small considerations around the codebase.

All considerations addressed!

Did you take a look at these ones? It seems like they are as before.

Thanks for the remind.

It's indeed way better to have those vehicle specific methods separated from the rest.

Ready for review!

@ArturoManzoli
Copy link
Contributor Author

ArturoManzoli commented Sep 24, 2025

Added on Latest patch:

  • Added energy consumption data modeled from tests with real vehicle with and w/o Ping1D sensor (adds considerable drag);
  • MAVLink commands like DO_CHANGE_SPEED now affect energy consumption and time estimates.

Copy link
Member

@rafaellehmkuhl rafaellehmkuhl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From an architectural point of view, the blueboat-estimates.ts should not be a Vue file, specially a composable, as it makes extending it to other vehicles a difficult and messy task. It is today accessing data from all over the codebase, so it's opening a new star of dependencies. Vue files should only be implementing UI logic, not business logic.

Ideally there should be a vehicle-estimates interface that specifies what is passed to the estimator and what is returned, and the blueboat-estimates.ts file would simply export an implementation of this interface (an object with the necessary methods, their parameters and returns), and the MissionStatistic.vue would simply be calling those methods (e.g.: timeToCompleteMission and totalEnergy) with the necessary parameters. This would also make so we do not export unneeded data from this, as missionEnergyWh and missionETASeconds . Something like the following:

interface VehicleMissionEstimate = {
  timeToCompleteMission: (waypoints: Waypoints, missionConfig: any) => number,
  totalEnergy: (waypoints: Waypoints, missionConfig: any) => number
}

export const blueBoatMissionEstimate: VehicleMissionEstimate = {
  timeToCompleteMission: (waypoints: Waypoints, missionConfig: any): number => {
    ...
  },
  totalEnergy: (waypoints: Waypoints, missionConfig: any): number => {
    ...
  }
}

// This one is just an example on how easy it gets to implement new ones if we implement a good interface
export const otherGenericVehicleMissionEstimate: VehicleMissionEstimate = {
  timeToCompleteMission: (waypoints: Waypoints, missionConfig: any): number => {
    ...
  },
  totalEnergy: (waypoints: Waypoints, missionConfig: any): number => {
    ...
  }
}

let timeToCompleteMission: number | undefined = undefined
let totalEnergy: number | undefined = undefined

if (vehicle == 'blue-boat') {
  timeToCompleteMission = blueBoatMissionEstimate.timeToCompleteMission(...)
  totalEnergy = blueBoatMissionEstimate.totalEnergy(...)
} else if (vehicle == 'generic-vehicle-with-estimates') {
  timeToCompleteMission = otherGenericVehicleMissionEstimate.timeToCompleteMission(...)
  totalEnergy = otherGenericVehicleMissionEstimate.totalEnergy(...)
} else {
  throw Error(`Estimates for vehicle ${vehicle} were not implemented`)
}

Do you think it would be possible to change it to something like that? I think it can be done quickly and really helps us in the future.

One small UI problem I noticed is this blinking panel:

Kapture.2025-09-26.at.16.29.09.mp4

Comment on lines 208 to 209
</select>
<p class="m-1 overflow-visible mt-2 text-sm text-slate-200">Default cruise speed (m/s)</p>
<input v-model="defaultCruiseSpeed" class="px-2 py-1 mt-1 mb-2 mx-5 rounded-sm bg-[#FFFFFF22]" />
<v-divider class="my-2" />
<button
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what I'm seeing this was removed because this speed value was not being used anywhere, right? Can we remove the rest of the references to it? Besides legacy implementations (like in the loadMissionFromFile method), you're also using this value in your energy estimates.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I did remove it but i'm putting it back. Its too early to take that option off. Users might look for a way to set a different speed and MAVLink commands could be a little advanced for some.

So I have updated the uploadMissionToVehicle function to check if the defaultCruiseSpeed is different than 1 and inject that change_speed into the first wp.

Copy link
Member

@rafaellehmkuhl rafaellehmkuhl Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!
Can you separate this change into a dedicated commit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't ready to review yet, so the change wasn't implemented.
Check again

Copy link
Contributor Author

@ArturoManzoli ArturoManzoli Oct 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change is a single modification on the mission upload function:
I added:

if (defaultCruiseSpeed.value !== 1) {
    missionItemsToUpload[0].commands = [
      ...missionItemsToUpload[0].commands.filter((cmd) => cmd.command !== MavCmd.MAV_CMD_DO_CHANGE_SPEED),
      {
        type: MissionCommandType.MAVLINK_NAV_COMMAND,
        command: MavCmd.MAV_CMD_DO_CHANGE_SPEED,
        param1: 0,
        param2: defaultCruiseSpeed.value,
        param3: -1,
        param4: 0,
      },
    ]
  }

Is it okay or you think a separate commit is still needed?

// Includes speed changes present on mission legs (from wp to wp+1)
const missionLegsWithSpeed = computed<Array<{ from: number; to: number; distanceMeters: number; speedMps: number }>>(
() => {
const anyStore = missionStore as any
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This anyStore name here (and in other places) does not make sense, but I assume it will go away when you remove the references to the defaultCruiseSpeed variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed

@ArturoManzoli ArturoManzoli force-pushed the 1235b-provide-power-duration-distance-on-mission-planning branch from 7d2991d to 188f568 Compare September 30, 2025 19:58
* @param {number} deg Angle in degrees.
* @returns {number} Angle in radians.
*/
export const toRad = (deg: number): number => (deg * Math.PI) / 180
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have the radians() method in this file.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

@ArturoManzoli ArturoManzoli force-pushed the 1235b-provide-power-duration-distance-on-mission-planning branch from 188f568 to 11f9a30 Compare October 1, 2025 14:08
@ArturoManzoli
Copy link
Contributor Author

From an architectural point of view, the blueboat-estimates.ts should not be a Vue file, specially a composable, as it makes extending it to other vehicles a difficult and messy task. It is today accessing data from all over the codebase, so it's opening a new star of dependencies. Vue files should only be implementing UI logic, not business logic.

Ideally there should be a vehicle-estimates interface that specifies what is passed to the estimator and what is returned, and the blueboat-estimates.ts file would simply export an implementation of this interface (an object with the necessary methods, their parameters and returns), and the MissionStatistic.vue would simply be calling those methods (e.g.: timeToCompleteMission and totalEnergy) with the necessary parameters. This would also make so we do not export unneeded data from this, as missionEnergyWh and missionETASeconds . Something like the following:

Agreed!
Your suggested architecture was implemented and now there is an easy way to expand the estimates to different vehicles

@ArturoManzoli ArturoManzoli force-pushed the 1235b-provide-power-duration-distance-on-mission-planning branch from 11f9a30 to 06d1827 Compare October 1, 2025 14:19
Copy link
Member

@rafaellehmkuhl rafaellehmkuhl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two functional things:

  1. Changing the battery type or capacity is not changing the estimates
  2. Changing the vehicle payload is also not changing the estimates

The blinking bug mentioned in the last review is still there, although it should not hold this PR if you don't find what's going on.

@rafaellehmkuhl
Copy link
Member

BTW the new architecture got much much better. Nice work.

@ArturoManzoli
Copy link
Contributor Author

Two functional things:

  1. Changing the battery type or capacity is not changing the estimates
  2. Changing the vehicle payload is also not changing the estimates

The blinking bug mentioned in the last review is still there, although it should not hold this PR if you don't find what's going on.

Hmm.. I'll check what happened

@ArturoManzoli
Copy link
Contributor Author

Two functional things:

  1. Changing the battery type or capacity is not changing the estimates
  2. Changing the vehicle payload is also not changing the estimates

The blinking bug mentioned in the last review is still there, although it should not hold this PR if you don't find what's going on.

  • About the blinking panel, I couldn't reproduce it here, but checking the css proprieties, it shouldn't behave like that. Maybe its a mac issue? Ill keep an eye on it, but I think we shouldn't hold the feature.

  • About the battery, payload and submerged probes affecting the estimates:
    This variables will only affect energy consumption, since speed is GPS controlled and mission time will be affected only by path and speed.
    To see the energy consumption field on the panel, your vehicle should be a "surface_boat". With that field on the panel, the changes made on the settings modal will affect the power consumption estimates (1)

Maybe for a UX point of view we should only enable the cog icon to known vehicle types that have power consumption already modeled?

(1)

estimates_changing.mp4

@rafaellehmkuhl
Copy link
Member

rafaellehmkuhl commented Oct 1, 2025

  • About the blinking panel, I couldn't reproduce it here, but checking the css proprieties, it shouldn't behave like that. Maybe its a mac issue? Ill keep an eye on it, but I think we shouldn't hold the feature.

Maybe it's macOS specific indeed. And agree, no need to hold it because of that.

  • About the battery, payload and submerged probes affecting the estimates:
    This variables will only affect energy consumption, since speed is GPS controlled and mission time will be affected only by path and speed.
    To see the energy consumption field on the panel, your vehicle should be a "surface_boat". With that field on the panel, the changes made on the settings modal will affect the power consumption estimates (1)

I was running a Surface Boat, but from SITL. It should still show up, right?
I'm doing some tests for eliot's PR and will them test it again here to see if the vehicle is being recognized wrongly somehow, but what I remember is that it was showing the BlueBoat icon correctly.

Maybe for a UX point of view we should only enable the cog icon to known vehicle types that have power consumption already modeled?

Definitely!

@ArturoManzoli ArturoManzoli force-pushed the 1235b-provide-power-duration-distance-on-mission-planning branch from 06d1827 to 172bd7b Compare October 1, 2025 17:50
@ArturoManzoli
Copy link
Contributor Author

  • About the blinking panel, I couldn't reproduce it here, but checking the css proprieties, it shouldn't behave like that. Maybe its a mac issue? Ill keep an eye on it, but I think we shouldn't hold the feature.

Maybe it's macOS specific indeed. And agree, no need to hold it because of that.

  • About the battery, payload and submerged probes affecting the estimates:
    This variables will only affect energy consumption, since speed is GPS controlled and mission time will be affected only by path and speed.
    To see the energy consumption field on the panel, your vehicle should be a "surface_boat". With that field on the panel, the changes made on the settings modal will affect the power consumption estimates (1)

I was running a Surface Boat, but from SITL. It should still show up, right? I'm doing some tests for eliot's PR and will them test it again here to see if the vehicle is being recognized wrongly somehow, but what I remember is that it was showing the BlueBoat icon correctly.

Check if the vehicleType on vehicleStore is === MavType.MAV_TYPE_SURFACE_BOAT

  • On last patch: Disabled the cog icon to unknown vehicles or types that don't have power consumption already modeled

Copy link
Member

@rafaellehmkuhl rafaellehmkuhl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed externally, everything is working, is just that the energy estimates for the payload and battery are inaccurate. As this can easily be improved later, I've opened an issue about that and we can go with this PR as it is.

I just marked two code changes that do not belong to this PR that need to be removed before we merge it.

currentWaypointAltitude: waypoints[0]?.altitude || 0,
currentWaypointAltitudeRefType: waypoints[0]?.altitudeReferenceType || AltitudeReferenceType.RELATIVE_TO_HOME,
defaultCruiseSpeed: 0,
defaultCruiseSpeed: 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove from this PR.

Comment on lines 551 to 564
if (defaultCruiseSpeed.value !== 1) {
missionItemsToUpload[0].commands = [
...missionItemsToUpload[0].commands.filter((cmd) => cmd.command !== MavCmd.MAV_CMD_DO_CHANGE_SPEED),
{
type: MissionCommandType.MAVLINK_NAV_COMMAND,
command: MavCmd.MAV_CMD_DO_CHANGE_SPEED,
param1: 0,
param2: defaultCruiseSpeed.value,
param3: -1,
param4: 0,
},
]
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To remove from this PR.

@ArturoManzoli ArturoManzoli force-pushed the 1235b-provide-power-duration-distance-on-mission-planning branch from 172bd7b to b6fa525 Compare October 2, 2025 11:12
@ArturoManzoli
Copy link
Contributor Author

As discussed externally, everything is working, is just that the energy estimates for the payload and battery are inaccurate. As this can easily be improved later, I've opened an issue about that and we can go with this PR as it is.

I just marked two code changes that do not belong to this PR that need to be removed before we merge it.

Both problems (panel blinking and energy estimates not changing on different payload and battery capacities) have been addressed.

Also removed the code snippets relative to the default cruise speed PR.

Copy link
Member

@rafaellehmkuhl rafaellehmkuhl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's working perfectly now!

@ArturoManzoli ArturoManzoli merged commit 6b55fc7 into bluerobotics:master Oct 2, 2025
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants