%% American Solar Challenge: an uphill battle across the Midwest
% In today's post, Sam Reinsel joins us to talk about the American Solar Challenge. Over to you, Sam..
%
%
% With electric vehicles coming to the forefront of the industry, innovations and new approaches in energy efficiency are likely to become the next big battleground in production vehicles. You don’t need to look far to find vehicles pushing the limits today. Vehicles like the Lightyear One are pushing the limits of efficiency and technology in their use of solar panels directly on the vehicle.
% The team at Lightyear didn’t start completely from scratch: they started their solar journey as students participating in solar car races. One of these races is the American solar challenge: ASC 2021 just wrapped up, and after seeing a reddit post detailing this year’s route from Kansas City to Santa Fe, I wanted to investigate just how much extra work the solar cars would need to do to make their way up the edge of the Rockies.
%
%
%
% If you aren’t familiar with solar car racing, it’s a fascinating engineering challenge. Teams must build their vehicles to strict rules that limit the area of solar panels available to them (which also limits how much energy they can capture as a result). The vehicles race across real-world roads on a 1000+ mile cross-country rally over a few days, only being allowed to use energy they capture from the sun to sustain them. The analysis I show below is just the tip of the iceberg in terms of strategy and planning for these races, in addition to all the engineering work.
%
%% Charting a course
% First off, keep in mind that the route posted on reddit (https://www.reddit.com/r/solarracing/comments/oij0sc/asc_2021_route_map/) is NOT the official route (that ends up changing based on any construction or other issues), but it’s a fantastic place to start to take a look at what the teams will be up against. There were a few issues that had already been identified with it when I pulled down the .kml file, so it’s not flawless. When estimating total mileage, however, I ended up within ~0.1 miles on each leg compared to the official route book, so for my purposes this is good enough.
% Before we do anything fancy, we should probably start with grabbing the route from Google maps. I downloaded it as a .kml file, which I read into MATLAB using a file exchange submission that’s been around about as long as I’ve been using MATLAB: kml2struct https://www.mathworks.com/matlabcentral/fileexchange/35642-kml2struct
% With this function we can bring our data in and start analyzing the route, which is broken into 9 segments (3 being optional loops) and plot it on a basic street map:

ascFile = kml2struct('ASC 2021.kml');
lineSegs = ascFile(strcmp({ascFile.Geometry},'Line'));
 
figure
gx = geoaxes;
hold on
for ind = 1: numel(lineSegs)
    geoplot(gx,lineSegs(ind).Lat,lineSegs(ind).Lon,'LineWidth',5)
end
geobasemap(gx,'streets')

%
%
% This gives us a good overview of the route, but it’s not much more than we get on google maps. To start getting a better look at the energy demands of the climb, we’ll need to get a digital elevation map of the area.
%
%% Finding the right map
% To simplify the workflow (and avoid downloading files to all the PCs I work on) I’m using a webmap imported with the Mapping toolbox. First things first: I need to search for any webmap servers that have elevation data in the area. I’m also going to filter my search to make sure I am actually going to get elevation data:

layerSearch = wmsfind('elevation','SearchFields','layername','Latlim',[30,45],'Lonlim',[-110,90]);
serverList = layerSearch.servers;
thisServer = WebMapServer(serverList{5});
capabilities = getCapabilities(thisServer);
layers = capabilities.Layer(11);
request = WMSMapRequest(layers,thisServer);

%
% Once I have the list of servers and layers that match the search criteria, I can start looking for a webmap that has what I need. There’s a bit of trial and error here as I make sure I’m satisfied with the maps I’m pulling, but ultimately I settled on one from https://elevation.nationalmap.gov/I’d like to find one with a bit more granularity in the elevation data, but for now this one has what I need. Now I just need to build my request for data. I need to specify the layers of the map I want (in this case, I only need the one), the latitude and longitude limits of my request, and the resolution of the data I’ll get back. I settled on a 3000x3000 image, mostly for performance reasons on the weaker of my machines.

thisServer = WebMapServer(serverList{4});
capabilities = getCapabilities(thisServer);
layers = capabilities.Layer(11);
request = WMSMapRequest(layers,thisServer);

request.Latlim = [35 40];
request.Lonlim = [-106 -94];
request.ImageHeight = 3000;
request.ImageWidth = 3000;
request.ImageFormat = 'image/jpeg';
A = getMap(thisServer,request.RequestURL);
R = request.RasterReference;

%
% Now that I have the elevation data, I can create a new version of the map. For this particular webmap the data is being passed back as an image rather than elevation data itself, so I need to convert it from the grayscale image (with values ranging 0 to 255) to actual elevation data. I often find myself writing remaps like this, so I have another file off the file exchange that I use to avoid re-writing this code everytime I need it. https://www.mathworks.com/matlabcentral/fileexchange/61213-mapfun-value-fromlow-fromhigh-tolow-tohigh
% I like to keep utility files like this around to avoid re-writing common functions and avoid typos or messing up my formula. Below I’ve written out the code, but Once that’s done we can plot out our course with elevation data instead:

figure
wm = worldmap(A,R);

% an example using the mapfun File exchange post
% mapElevation = mapfun(double(A(:,:, 1)),0, 255, -60.3041, 3922.47);

% and the hand-coded version:
mapElevation = (double(A(:,:,1)) - 0) .* (3922.47 - -60.3041) ./ (255 - 0) + -60.3041;
geoshow(mapElevation,R,'DisplayType','texturemap')
colormap turbo
c = colorbar;
c.Label.String = "Elevation, m";
hold on
for ind = 1: numel(lineSegs)
    geoshow(lineSegs(ind).Lat,lineSegs(ind).Lon,'LineWidth',3,'Color',rand(1,3))
end
hold off

%
%
% This makes it clear that the solar cars have quite a big vertical climb ahead of them, and that takes a lot of energy to overcome. Unlike your daily commute, where an electric vehicle could make up some of that extra uphill grunt with regenerative braking on the way back down the hill, the solar cars don’t get a return trip to even things out. The most drastic elevation change in any of the segments happens on segment E, where the vehicles will need to climb nearly a kilometer. If we zoom in on that section of the elevation map we can see the areas that will involve the most elevation change in a bit more detail:
%
%
%
% Looking at the elevation change over the entire route, this part of the climb is easily the most taxing (although even here, the average road grade is not that severe, just more consistent).
%
%
%%
%% Impact on energy consumption
% Ultimately, my curiosity here was how much more energy it’s going to take to overcome the terrain a nice flat road, which requires not just mapping the elevation but running it through a vehicle model.  I don’t have a great approximation of any individual solar cars, so instead I’m using a common electric vehicle as the basis of my comparison. It won’t be correct in terms of total energy consumed (we’re talking a few thousand pounds of extra weight in my model) but should give us a decent comparison of how much the elevation change impacts the energy needed.
% Because I'm just looking for a baseline, rather than use a fully-fledged vehicle model, I set up a a configurable power-loss model of a few common Electric vehicles. We've discussed this kind of model in our vehicle modeling series, so if you’re interested you should check those videos out here: https://www.mathworks.com/videos/matlab-and-simulink-racing-lounge-vehicle-modeling-part-1-simulink-1502466996305.html
% To make sure the model was accurate enough, I compared it to published EPA energy consumption data on the main city and highway drive cycles. These numbers aren’t quite the same as the label fuel economy you see on window stickers at dealerships: that label takes multiple drive cycles and some correction factors to determine more real-world results. The EPA data I am using is raw, unadjusted data over individual cycles, which is much better for comparing to as the energy consumption of our model will also be unadjusted. My powerloss model isn't perfect: for some EVs I could only get within ~15% or so, others were within 2-3% on most of the drive cycles. Those last few % would bother me if I was building a more complicated, high-fidelity model: but for my quick analysis I feel satisfied getting that close.
% So how much more power does it take to climb up the foothills of the Rockies? I ran 2 simulations: one with grade considered and one without. The resulting power difference is relatively mild: usually only a few kW difference. On Section E, with its significantly higher average grade we peak at nearly 35kW of additional power
%
%
%
% So how much of an impact does this actually have on energy consumption? With my simulations, I saw a total increase in energy used of about 7 kWh, right around 5% or so more than the run without grade. While its not a huge increase, in the context of solar racing 5% more energy (which all has to come from the sun!) is significant.
% One limitation to my model is that I'm re-using the US HWFET certification cycle as my velocity profile as I haven't found an easy source for speed limits. I considered using the GPS route to estimate road curvature to adjust target vehicle speeds as an alternative way to generate a speed trace but decided to focus on improving the power loss model with the time I had instead. Even with speed limits, the Solar cars themselves are very streamlined vehicles with a strict limit on their power, so they cannot accelerate or maintain high speeds the same way a passenger vehicle can.
% There are many other factors teams must consider along the route: cloud coverage, how the route positions them against the sun, wind speed, and many more. Each of those play into the strategy each team takes to complete the event: but hopefully you can see from the exploration I've presented here how you can start considering these aspects in relatively simple ways, with surprisingly little data needed to start drawing conclusions about what we need to consider for high-level strategy decisions.