{"id":2624,"date":"2019-03-18T17:32:50","date_gmt":"2019-03-18T16:32:50","guid":{"rendered":"https:\/\/blogs.mathworks.com\/student-lounge\/?p=2624"},"modified":"2020-05-08T20:58:43","modified_gmt":"2020-05-08T18:58:43","slug":"modeling-robotic-boats-in-simulink","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/student-lounge\/2019\/03\/18\/modeling-robotic-boats-in-simulink\/","title":{"rendered":"Modeling Robotic Boats in Simulink"},"content":{"rendered":"<p><a href=\"https:\/\/www.linkedin.com\/in\/connelldsouza\/\">Connell D&#8217;Souza<\/a> our co-blogger has worked with a team that develops robotic boats. The outcome is clearly impressive.<\/p>\n<p>&#8212;<\/p>\n<p>For today\u2019s post, I would like to introduce you to <a href=\"https:\/\/www.linkedin.com\/in\/alejandro-gonzalez-garcia\/\">Alejandro Gonzalez<\/a>. Alex is a member of the RoboBoat team \u2013 <a title=\"https:\/\/www.vanttec.mx\/ (link no longer works)\">VantTec<\/a> of <a href=\"https:\/\/tec.mx\/es\">Tecnol\u00f3gico de Monterrey<\/a> in Monterrey, Mexico. I met Alex at RoboBoat 2018 where I got a chance to see his team\u2019s innovative solution to the tasks at the competition \u2013 an Unmanned Aerial Vehicle (UAV) guiding an Unmanned Surface Vehicle (USV) through the course, and I was glad when Alex offered to write about his team\u2019s work with MATLAB and Simulink for the Racing Lounge Blog! Alex will talk about using the Robotics System Toolbox to develop a path planning algorithm and the Aerospace Blockset to build a dynamic model of their boat to tune controllers. Download the code used in this post from <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/75425-simulink-usv-model\">File Exchange in the Add-Ons tab in MATLAB<\/a>. So, let me hand it off to Alex to take it away \u2013 Alex, the stage is yours!<\/p>\n<p>&#8212;<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/boats.png\"><img decoding=\"async\" loading=\"lazy\" width=\"352\" height=\"269\" class=\"alignnone size-full wp-image-2628\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/boats.png\" alt=\"\" \/><\/a><\/p>\n<p>I lead VantTec, a student robotics group and we build an autonomous robotic boat for RoboBoat. The competition encourages collaboration between unmanned aerial vehicles (UAVs) and unmanned surface vehicles (USVs) for the docking task \u2013 the UAV tells\u00a0the USV where to dock. We decided to take this collaboration further and use the UAV to develop a path for the USV to follow through the course.<\/p>\n<p>&nbsp;<\/p>\n<p>The challenges with autonomous navigation of a robot are threefold:<\/p>\n<ol>\n<li>Creating a map of the environment<\/li>\n<li>Choosing\/developing a path planning algorithm<\/li>\n<li>Developing a robust controller to follow the desired path<\/li>\n<\/ol>\n<p>So, how do we tackle these challenges?<\/p>\n<h1>Creating a Map of the Environment<\/h1>\n<p>To create a map of the environment we use our UAV to click a bird&#8217;s-eye-view photo of the course. This photo can create a grid to work on. Here, computer vision\u00a0and artificial intelligence\u00a0algorithms can give a relative position of obstacles, referenced to the picture\u00a0dimensions\u00a0or the vehicle itself.<\/p>\n<p>For this to work, first we take a picture from above with the aerial vehicle. We use a <a href=\"https:\/\/www.dji.com\/phantom-4\">DJI Phantom 4<\/a> with a mobile application we developed for autonomous waypoint navigation; the UAV takes the picture and\u00a0sends it\u00a0to a mobile phone. Next, we send this picture to our central ground station, where a\u00a0neural network\u00a0we developed\u00a0detects the buoys and creates bounding boxes around them. From these bounding boxes, we obtain the center of each buoy, which we arrange in a matrix to create the map.<\/p>\n<p>Using the Robotics System Toolbox\u2019s binary occupancy grid, the data gathered creates a map where the robot can navigate.\u00a0Here, the obstacles&#8217; relative coordinates will set their location inside the grid.<\/p>\n<p>Below, is an example on how to create the grid; the values 50 and 10\u00a0should be changed\u00a0to the dimensions in meters that the UAV camera frames on the taken picture. Then, the\u00a0variable\u00a0xy\u00a0is the\u00a0set of obstacles taken from their centers. The sample\u00a0code is an example of the kind of matrix that\u00a0should be introduced. Our computer vision module\u00a0creates a\u00a0similar matrix with a corresponding vector of coordinates for each obstacle.<\/p>\n<pre class=\"codeinput\">robotics.BinaryOccupancyGrid(50,10,30);\r\nxy = [3 2; 8 5; 13 7; 20 1; 25 8; 32 6; 38 3; 40 9; 42 4; 23 2; 28 5; 33 7];\r\nsetOccupancy(map, xy, 1);\r\n<\/pre>\n<p>Then, the function inflate can change the obstacle dimensions by a known or obtained radius.<\/p>\n<pre class=\"codeinput\">inflate(map,0.3);\r\n<\/pre>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/occupancyGrid_crop.jpg\"><img decoding=\"async\" loading=\"lazy\" width=\"559\" height=\"185\" class=\"alignnone size-full wp-image-2706\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/occupancyGrid_crop.jpg\" alt=\"\" \/><\/a><\/p>\n<h1>Choosing\/ Developing a Path Planning Algorithm<\/h1>\n<p>The Robotics Systems Toolbox presents another solution, this time using a sampling-based path planner algorithm called <a href=\"https:\/\/www.mathworks.com\/help\/robotics\/ug\/probabilistic-roadmaps-prm.html?searchHighlight=PRM&amp;s_tid=doc_srchtitle\">Probabilistic Roadmap<\/a>. In this case, a tag on the vehicle can help for its aerial recognition, resulting in the start location coordinates and end location coordinates and number of nodes to set are required to get the route the vehicle needs to follow.<\/p>\n<pre class=\"codeinput\">prm\u202f=\u202frobotics.PRM\u202f \r\nprm.Map\u202f=\u202fmap;\u202f \r\nstartLocation\u202f= [3 3];\u202f \r\nendLocation\u202f= [47 7];\u202f \r\nprm.NumNodes\u202f= 25;\u202f \r\n%\u202fSearch for a solution between start and end location.\u202f \r\npath\u202f=\u202ffindpath(prm,\u202fstartLocation,\u202fendLocation);\u202f \r\nwhile\u202fisempty(path)\u202f \r\n\u202f\u202f\u202f\u202fprm.NumNodes\u202f=\u202fprm.NumNodes\u202f+ 25;\u202f \r\n\u202f\u202f\u202f\u202fupdate(prm);\u202f \r\n\u202f\u202f\u202f\u202fpath\u202f=\u202ffindpath(prm,\u202fstartLocation,\u202fendLocation);\u202f \r\nend\u202f \r\n<\/pre>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/occupanyGridPRM_crop.jpg\"><img decoding=\"async\" loading=\"lazy\" width=\"559\" height=\"175\" class=\"alignnone size-full wp-image-2704\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/occupanyGridPRM_crop.jpg\" alt=\"\" \/><\/a><\/p>\n<h1>Developing a Robust Controller<\/h1>\n<p>The challenge of developing a robust controller is easier with a model of the vehicle to reference it. The better your model, the better your controller. A kinematic model serves as a start, but a dynamic model of the robot is better suited to create a simulation environment. For an underactuated USV, a 3 DOF dynamic model can achieve the environment needed to work with.<\/p>\n<p>Simulink is a great tool to develop these kinds of model, even more using the toolboxes available. Aerospace Blockset presents Utilities blocks, which includes math operations with 3&#215;3 matrices, needed for 3 DOF dynamic models.<\/p>\n<h2>Building the Model<\/h2>\n<p>The equation for the dynamic model is:<\/p>\n<p style=\"text-align: center;\">$ \\tau = M \\dot{\\nu} + C(\\nu)\\nu + D(\\nu)\\nu $<\/p>\n<p>or rewritten:<\/p>\n<p style=\"text-align: center;\">$ \\dot{\\nu} = M^{-1} [\\tau &#8211; C(\\nu) &#8211; D(\\nu)] $<\/p>\n<p>The first matrix in the equation is the inertia tensor. This M matrix is constructed using the 3&#215;3 Matrix utility block from the Aerospace Blockset.<\/p>\n<p style=\"text-align: center;\">$M = \\begin{pmatrix}\u00a0m &#8211; X_{\\dot{u}} \u00a0&amp; 0 &amp; -m y_G \\\\ 0 &amp; m &#8211; Y_{\\dot{u}} &amp; m x_{G} &#8211; Y_{\\dot{r}} \\\\ -my_{G} &amp; m x_{G} &#8211; N_{\\dot{\\nu}} &amp; I_{Z} &#8211; N_{\\dot{r}} \\end{pmatrix} $<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/mMatrix-e1552921013732.png\"><img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"423\" class=\"alignnone size-full wp-image-2710\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/mMatrix-e1552921013732.png\" alt=\"\" \/><\/a><\/p>\n<p>Then, it was made a subsystem for the overall dynamic model, having the vehicle physical constants (m, X_G, Y_G, I_Z) and hydrodynamic coefficients needed as inputs and the matrix (M) as output.<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/mSubsystem-e1552923926532.png\"><img decoding=\"async\" loading=\"lazy\" width=\"220\" height=\"297\" class=\"alignnone size-full wp-image-2786\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/mSubsystem-e1552923926532.png\" alt=\"\" \/><\/a><\/p>\n<p>The second matrix in the system is a vector of forces ($\\tau $-matrix) which is programmed as shown below. Then, it was inserted into a subsystem for the overall model, with the boat beam (B) and individual thrust (Tport &amp; Tstbd) as inputs and the vector of forces (T) as output.<\/p>\n<p style=\"text-align: center;\">$ \\tau =\u00a0\\begin{pmatrix} \\tau_{x} \\\\\u00a0\\tau_{y} \\\\\u00a0\\tau_{z} \\end{pmatrix} =\u00a0\\begin{pmatrix}\u00a0(T_{port} + T_{stbd}) \\\\ 0 \\\\ 0.5*B (T_{port} &#8211; T_{stbd}) \\end{pmatrix} $<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/tMatrix-e1552921377457.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-2722 size-full\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/tMatrix-e1552923852775.png\" alt=\"\" width=\"600\" height=\"198\" \/><\/a><\/p>\n<p>Then, it was inserted into a subsystem for the overall model, with the boat beam and individual thrust as inputs and the vector of forces as output.<\/p>\n<p>Similarly, the next matrix is the Coriolis matrix (C matrix). As shown below, the sum of two 3&#215;3 matrices is needed and hence the matrix sum block was used. Then, a subsystem was created which has, as inputs, physical parameters (X_G, Y_G, m), hydrodynamic coefficients and the values of the surge and sway speed as well as the yaw rate (V local) and the Coriolis matrix as the output:<\/p>\n<p style=\"text-align: center;\">$ C(\\nu) = \\begin{pmatrix}\u00a00 &amp; 0&amp; -m(x_G r + \\nu) \\\\ 0 &amp; 0&amp; -m(y_G r &#8211; u) \\\\ m(x_G r + \\nu) &amp; m(y_G r &#8211; u) &amp; 0\u00a0 \\end{pmatrix} +\u00a0\\begin{pmatrix}\u00a00 &amp; 0&amp; \\frac{Y_{\\dot{\\nu}} \\nu +\\frac{Y_{\\dot{r}} + N_{\\dot{\\nu}}}{2}r}{200}\\\\ 0 &amp; 0 &amp; -X_{\\dot{u}} u \\\\ \\frac{-Y_{\\dot{\\nu}} \\nu -\\frac{Y_{\\dot{r}} + N_{\\dot{\\nu}}}{2}r}{200} &amp; X_{\\dot{u}} u &amp; 0 \u00a0\\end{pmatrix} \u00a0$<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/cMatrix-1-e1552925286537.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"516\" class=\"alignnone size-full wp-image-2812\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/cMatrix-1-e1552925286537.png\" alt=\"\" \/><\/a><\/p>\n<p>The next matrix is the drag matrices. Like the Coriolis matrix, the Drag matrix is a sum of two matrices, but this time with a negative sign. Again, a subsystem was created, with all the hydrodynamic coefficients required, surge and sway speeds, and the yaw rate as inputs and the matrix as output.<\/p>\n<p style=\"text-align: center;\">$D(\\nu) = \\begin{pmatrix} Y_u &amp; 0 &amp; 0 \\\\ 0 &amp; Y_{\\nu} &amp; Y_r \\\\ 0 &amp; N_{\\nu} &amp; N_r\u00a0 \\end{pmatrix} &#8211; \\begin{pmatrix}\u00a0X_{u\\mid u \\mid}\\mid u \\mid &amp; 0 &amp; 0 \\\\ 0 &amp; Y_{\\nu \\mid \\nu \\mid}\u00a0\\mid \\nu \\mid +\u00a0Y_{\\nu \\mid r \\mid}\u00a0\\mid r \\mid &amp;\u00a0Y_{r \\mid \\nu \\mid}\u00a0\\mid \\nu \\mid +\u00a0Y_{r \\mid r \\mid}\u00a0\\mid r \\mid \\\\ 0 &amp; Y_{\\nu \\mid \\nu \\mid}\u00a0\\mid \\nu \\mid +\u00a0Y_{\\nu \\mid r \\mid}\u00a0\\mid r \\mid &amp;\u00a0Y_{r \\mid \\nu \\mid}\u00a0\\mid \\nu \\mid +\u00a0Y_{r \\mid r \\mid}\u00a0\\mid r \\mid \u00a0\\end{pmatrix} $<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/dMatrix-1-e1552925326313.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"549\" class=\"alignnone size-full wp-image-2814\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/dMatrix-1-e1552925326313.png\" alt=\"\" \/><\/a><\/p>\n<p>Afterwards, a matrix sum was used for the first algebraic part of the equation.<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/matrixAlgebra-e1552922682179.png\"><img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"557\" class=\"alignnone size-full wp-image-2750\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/matrixAlgebra-e1552922682179.png\" alt=\"\" \/><\/a><\/p>\n<p>Then, the resultant matrix is multiplied with the inverted M matrix. The result is the derivative of the local reference frame velocity vector, and it is subsequently integrated.<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/v_local-e1552922892988.png\"><img decoding=\"async\" loading=\"lazy\" width=\"801\" height=\"479\" class=\"alignnone size-full wp-image-2752\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/v_local-e1552922892988.png\" alt=\"\" \/><\/a><\/p>\n<p>The transformation matrix is represented as shown below and is used to relate the local reference frame with the global reference frame:<\/p>\n<p style=\"text-align: center;\">$ J(\\eta) =\u00a0 \\begin{pmatrix} cos \\psi &amp; -sin\u00a0\\psi &amp; 0 \\\\\u00a0sin \\psi &amp; cos \\psi &amp; 0\\\\ 0 &amp; 0 &amp; 1 \\\\ \\end{pmatrix} \u00a0$<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/tformMatrix-e1552923144460.png\"><img decoding=\"async\" loading=\"lazy\" width=\"799\" height=\"389\" class=\"alignnone size-full wp-image-2760\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/tformMatrix-e1552923144460.png\" alt=\"\" \/><\/a><\/p>\n<p>The local velocity vector represented by V-local is transformed to the global reference frame and then integrated to obtain the x,y and orientation or heading of the boat and is stored in the vector defined by \u201cn_global\u201d as shown below. You can use a demux block to index into the individual elements of the vector.<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/tformComputations.png\"><img decoding=\"async\" loading=\"lazy\" width=\"588\" height=\"332\" class=\"alignnone size-full wp-image-2762\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/tformComputations.png\" alt=\"\" \/><\/a><\/p>\n<p>Finally, a subsystem was created with the equations necessary to obtain the hydrodynamic coefficients, after introducing parameters that can be measured or estimated. These hydrodynamic coefficients are collected into a Simulink Bus to enable data transfer to other subsystems of the model.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/completeModel-1-e1552925424297.png\"><img decoding=\"async\" loading=\"lazy\" width=\"1024\" height=\"528\" class=\"alignnone size-full wp-image-2818\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/completeModel-1-e1552925424297.png\" alt=\"\" \/><\/a><\/p>\n<h1>Developing a Model-Based Controller<\/h1>\n<p>The programmed equation creates a dynamic boat model to base a controller on. Here the body-fixed frame (v) and North-East-Down -fixed frame (n) are the outputs and the thruster values or control commands as inputs to the model. You can also set up the boat parameters to be accepted as mask variables, this will give you a parameterized model that can be modified as you make physical changes to your boat. With this parameterized model, you can use Control System Toolbox and Simulink Control Design to design a controller that can follow the desired path generated earlier.<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/dynamicModel-e1552923274418.png\"><img decoding=\"async\" loading=\"lazy\" width=\"602\" height=\"186\" class=\"alignnone size-full wp-image-2766\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/dynamicModel-e1552923274418.png\" alt=\"\" \/><\/a><\/p>\n<p>Here I show you an example surge speed and heading controller that we developed. To test this controller, we used the Signal Builder block to create an example sinusoidal trajectory that represents the desired heading. As you can imagine, in our complete system this trajectory is generated from the map as we discussed earlier, but we are showing a test input for now.<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/controllerTest-e1552923303513.png\"><img decoding=\"async\" loading=\"lazy\" width=\"801\" height=\"611\" class=\"alignnone size-full wp-image-2768\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/controllerTest-e1552923303513.png\" alt=\"\" \/><\/a><\/p>\n<p>From the plots below, we can see that our controller is able to track the heading fairly well. This can be improved by <a href=\"https:\/\/www.researchgate.net\/publication\/333115323_Modeling_identification_and_control_of_an_unmanned_surface_vehicle\">tuning the controller gains.<\/a> The XY Graph below shows the boats trajectory given a sinusoidal heading and a step velocity as test inputs.<\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/controlPlots-e1552923333590.png\"><img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"357\" class=\"alignnone size-full wp-image-2770\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/controlPlots-e1552923333590.png\" alt=\"\" \/><\/a><\/p>\n<p><a href=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/trajFinal.png\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone wp-image-2772 size-full\" src=\"https:\/\/blogs.mathworks.com\/racing-lounge\/files\/2019\/03\/trajFinal-e1552925475897.png\" alt=\"\" width=\"500\" height=\"371\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><em>* A. Gonzalez-Garcia and H. Casta\u00f1eda, \u201cModeling, Identification and Control of an Unmanned Surface Vehicle,\u201c AUVSI XPONENTIAL 2019: All Things Unmanned, 2019<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/student-lounge\/files\/2019\/03\/boats.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div>\n<p>Connell D&#8217;Souza our co-blogger has worked with a team that develops robotic boats. The outcome is clearly impressive.<br \/>\n&#8212;<br \/>\nFor today\u2019s post, I would like to introduce you to Alejandro&#8230; <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/student-lounge\/2019\/03\/18\/modeling-robotic-boats-in-simulink\/\">read more >><\/a><\/p>\n","protected":false},"author":151,"featured_media":2628,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[52,14,8,10,13,12],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/posts\/2624"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/users\/151"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/comments?post=2624"}],"version-history":[{"count":84,"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/posts\/2624\/revisions"}],"predecessor-version":[{"id":4013,"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/posts\/2624\/revisions\/4013"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/media\/2628"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/media?parent=2624"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/categories?post=2624"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/student-lounge\/wp-json\/wp\/v2\/tags?post=2624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}